001 /*
002 * Copyright 2010-2013 JetBrains s.r.o.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 * http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017 package org.jetbrains.jet.lang.descriptors.impl;
018
019 import jet.Function0;
020 import jet.Function1;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.jet.lang.descriptors.*;
024 import org.jetbrains.jet.lang.descriptors.annotations.AnnotationDescriptor;
025 import org.jetbrains.jet.lang.resolve.DescriptorFactory;
026 import org.jetbrains.jet.lang.resolve.OverridingUtil;
027 import org.jetbrains.jet.lang.resolve.name.Name;
028 import org.jetbrains.jet.lang.resolve.name.SpecialNames;
029 import org.jetbrains.jet.lang.resolve.scopes.JetScope;
030 import org.jetbrains.jet.lang.resolve.scopes.JetScopeImpl;
031 import org.jetbrains.jet.lang.types.JetType;
032 import org.jetbrains.jet.lang.types.TypeConstructor;
033 import org.jetbrains.jet.lang.types.TypeConstructorImpl;
034 import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
035 import org.jetbrains.jet.storage.NotNullLazyValue;
036 import org.jetbrains.jet.storage.StorageManager;
037 import org.jetbrains.jet.utils.Printer;
038
039 import java.util.*;
040
041 public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
042 private final ClassKind kind;
043 private final TypeConstructor typeConstructor;
044 private final ConstructorDescriptor primaryConstructor;
045 private final JetScope scope;
046 private final EnumEntrySyntheticClassDescriptor classObjectDescriptor;
047 private final NotNullLazyValue<Collection<Name>> enumMemberNames;
048
049 /**
050 * Creates and initializes descriptors for enum entry with the given name and its class object
051 * @param enumMemberNames needed for fake overrides resolution
052 */
053 @NotNull
054 public static EnumEntrySyntheticClassDescriptor create(
055 @NotNull StorageManager storageManager,
056 @NotNull ClassDescriptor enumClass,
057 @NotNull Name name,
058 @NotNull NotNullLazyValue<Collection<Name>> enumMemberNames
059 ) {
060 JetType enumType = enumClass.getDefaultType();
061
062 return new EnumEntrySyntheticClassDescriptor(storageManager, enumClass, enumType, name, ClassKind.ENUM_ENTRY, enumMemberNames);
063 }
064
065 private EnumEntrySyntheticClassDescriptor(
066 @NotNull StorageManager storageManager,
067 @NotNull ClassDescriptor containingClass,
068 @NotNull JetType supertype,
069 @NotNull Name name,
070 @NotNull ClassKind kind,
071 @NotNull NotNullLazyValue<Collection<Name>> enumMemberNames
072 ) {
073 super(storageManager, containingClass, name);
074 this.kind = kind;
075
076 this.typeConstructor =
077 new TypeConstructorImpl(this, getAnnotations(), true, "enum entry", Collections.<TypeParameterDescriptor>emptyList(),
078 Collections.singleton(supertype));
079
080 this.scope = new EnumEntryScope(storageManager);
081 this.enumMemberNames = enumMemberNames;
082
083 ConstructorDescriptorImpl primaryConstructor = DescriptorFactory.createPrimaryConstructorForObject(this);
084 primaryConstructor.setReturnType(getDefaultType());
085 this.primaryConstructor = primaryConstructor;
086
087 this.classObjectDescriptor =
088 kind == ClassKind.CLASS_OBJECT
089 ? null
090 : new EnumEntrySyntheticClassDescriptor(storageManager, this, getDefaultType(), SpecialNames.getClassObjectName(name),
091 ClassKind.CLASS_OBJECT, enumMemberNames);
092 }
093
094 @NotNull
095 @Override
096 protected JetScope getScopeForMemberLookup() {
097 return scope;
098 }
099
100 @NotNull
101 @Override
102 public Collection<ConstructorDescriptor> getConstructors() {
103 return Collections.singleton(primaryConstructor);
104 }
105
106 @NotNull
107 @Override
108 public TypeConstructor getTypeConstructor() {
109 return typeConstructor;
110 }
111
112 @Nullable
113 @Override
114 public ClassDescriptor getClassObjectDescriptor() {
115 return classObjectDescriptor;
116 }
117
118 @NotNull
119 @Override
120 public ClassKind getKind() {
121 return kind;
122 }
123
124 @NotNull
125 @Override
126 public Modality getModality() {
127 return Modality.FINAL;
128 }
129
130 @NotNull
131 @Override
132 public Visibility getVisibility() {
133 return Visibilities.PUBLIC;
134 }
135
136 @Override
137 public boolean isInner() {
138 return false;
139 }
140
141 @Nullable
142 @Override
143 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
144 return primaryConstructor;
145 }
146
147 @NotNull
148 @Override
149 public List<AnnotationDescriptor> getAnnotations() {
150 // TODO
151 return Collections.emptyList();
152 }
153
154 private class EnumEntryScope extends JetScopeImpl {
155 private final MemoizedFunctionToNotNull<Name, Collection<FunctionDescriptor>> functions;
156 private final MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> properties;
157 private final NotNullLazyValue<Collection<DeclarationDescriptor>> allDescriptors;
158
159 public EnumEntryScope(@NotNull StorageManager storageManager) {
160 this.functions = storageManager.createMemoizedFunction(new Function1<Name, Collection<FunctionDescriptor>>() {
161 @Override
162 public Collection<FunctionDescriptor> invoke(Name name) {
163 return computeFunctions(name);
164 }
165 });
166 this.properties = storageManager.createMemoizedFunction(new Function1<Name, Collection<PropertyDescriptor>>() {
167 @Override
168 public Collection<PropertyDescriptor> invoke(Name name) {
169 return computeProperties(name);
170 }
171 });
172 this.allDescriptors = storageManager.createLazyValue(new Function0<Collection<DeclarationDescriptor>>() {
173 @Override
174 public Collection<DeclarationDescriptor> invoke() {
175 return computeAllDeclarations();
176 }
177 });
178 }
179
180 @NotNull
181 @Override
182 @SuppressWarnings("unchecked")
183 public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
184 return (Collection) properties.invoke(name);
185 }
186
187 @NotNull
188 @SuppressWarnings("unchecked")
189 private Collection<PropertyDescriptor> computeProperties(@NotNull Name name) {
190 return resolveFakeOverrides(name, (Collection) getSupertypeScope().getProperties(name));
191 }
192
193 @NotNull
194 @Override
195 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
196 return functions.invoke(name);
197 }
198
199 @NotNull
200 private Collection<FunctionDescriptor> computeFunctions(@NotNull Name name) {
201 return resolveFakeOverrides(name, getSupertypeScope().getFunctions(name));
202 }
203
204 @NotNull
205 private JetScope getSupertypeScope() {
206 Collection<JetType> supertype = getTypeConstructor().getSupertypes();
207 assert supertype.size() == 1 : "Enum entry and its class object both should have exactly one supertype: " + supertype;
208 return supertype.iterator().next().getMemberScope();
209 }
210
211 @NotNull
212 private <D extends CallableMemberDescriptor> Collection<D> resolveFakeOverrides(
213 @NotNull Name name,
214 @NotNull Collection<D> fromSupertypes
215 ) {
216 final Set<D> result = new HashSet<D>();
217
218 OverridingUtil.generateOverridesInFunctionGroup(
219 name, fromSupertypes, Collections.<D>emptySet(), EnumEntrySyntheticClassDescriptor.this,
220 new OverridingUtil.DescriptorSink() {
221 @Override
222 @SuppressWarnings("unchecked")
223 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
224 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, new OverridingUtil.NotInferredVisibilitySink() {
225 @Override
226 public void cannotInferVisibility(@NotNull CallableMemberDescriptor descriptor) {
227 // Do nothing
228 }
229 });
230 result.add((D) fakeOverride);
231 }
232
233 @Override
234 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
235 // Do nothing
236 }
237 }
238 );
239
240 return result;
241 }
242
243 @NotNull
244 @Override
245 public DeclarationDescriptor getContainingDeclaration() {
246 return EnumEntrySyntheticClassDescriptor.this;
247 }
248
249 @NotNull
250 @Override
251 public Collection<DeclarationDescriptor> getAllDescriptors() {
252 return allDescriptors.invoke();
253 }
254
255 @NotNull
256 private Collection<DeclarationDescriptor> computeAllDeclarations() {
257 Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
258 for (Name name : enumMemberNames.invoke()) {
259 result.addAll(getFunctions(name));
260 result.addAll(getProperties(name));
261 }
262 return result;
263 }
264
265 @Override
266 public void printScopeStructure(@NotNull Printer p) {
267 p.println("enum entry scope for " + EnumEntrySyntheticClassDescriptor.this);
268 }
269 }
270 }