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 kotlin.Function0;
020 import kotlin.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.Annotations;
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.resolve.scopes.StaticScopeForKotlinClass;
032 import org.jetbrains.jet.lang.types.JetType;
033 import org.jetbrains.jet.lang.types.TypeConstructor;
034 import org.jetbrains.jet.lang.types.TypeConstructorImpl;
035 import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
036 import org.jetbrains.jet.storage.NotNullLazyValue;
037 import org.jetbrains.jet.storage.StorageManager;
038 import org.jetbrains.jet.utils.Printer;
039
040 import java.util.Collection;
041 import java.util.Collections;
042 import java.util.HashSet;
043 import java.util.Set;
044
045 public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
046 private final ClassKind kind;
047 private final TypeConstructor typeConstructor;
048 private final ConstructorDescriptor primaryConstructor;
049 private final JetScope scope;
050 private final JetScope staticScope = new StaticScopeForKotlinClass(this);
051 private final EnumEntrySyntheticClassDescriptor classObjectDescriptor;
052 private final NotNullLazyValue<Collection<Name>> enumMemberNames;
053
054 /**
055 * Creates and initializes descriptors for enum entry with the given name and its class object
056 * @param enumMemberNames needed for fake overrides resolution
057 */
058 @NotNull
059 public static EnumEntrySyntheticClassDescriptor create(
060 @NotNull StorageManager storageManager,
061 @NotNull ClassDescriptor enumClass,
062 @NotNull Name name,
063 @NotNull NotNullLazyValue<Collection<Name>> enumMemberNames,
064 @NotNull SourceElement source
065 ) {
066 JetType enumType = enumClass.getDefaultType();
067
068 return new EnumEntrySyntheticClassDescriptor(storageManager, enumClass, enumType, name, ClassKind.ENUM_ENTRY, enumMemberNames, source);
069 }
070
071 private EnumEntrySyntheticClassDescriptor(
072 @NotNull StorageManager storageManager,
073 @NotNull ClassDescriptor containingClass,
074 @NotNull JetType supertype,
075 @NotNull Name name,
076 @NotNull ClassKind kind,
077 @NotNull NotNullLazyValue<Collection<Name>> enumMemberNames,
078 @NotNull SourceElement source
079 ) {
080 super(storageManager, containingClass, name, source);
081 this.kind = kind;
082
083 this.typeConstructor =
084 TypeConstructorImpl.createForClass(this, getAnnotations(), true, "enum entry", Collections.<TypeParameterDescriptor>emptyList(),
085 Collections.singleton(supertype));
086
087 this.scope = new EnumEntryScope(storageManager);
088 this.enumMemberNames = enumMemberNames;
089
090 ConstructorDescriptorImpl primaryConstructor = DescriptorFactory.createPrimaryConstructorForObject(this, source);
091 primaryConstructor.setReturnType(getDefaultType());
092 this.primaryConstructor = primaryConstructor;
093
094 this.classObjectDescriptor =
095 kind == ClassKind.CLASS_OBJECT
096 ? null
097 : new EnumEntrySyntheticClassDescriptor(storageManager, this, getDefaultType(), SpecialNames.getClassObjectName(name),
098 ClassKind.CLASS_OBJECT, enumMemberNames, SourceElement.NO_SOURCE);
099 }
100
101 @NotNull
102 @Override
103 protected JetScope getScopeForMemberLookup() {
104 return scope;
105 }
106
107 @NotNull
108 @Override
109 public JetScope getStaticScope() {
110 return staticScope;
111 }
112
113 @NotNull
114 @Override
115 public Collection<ConstructorDescriptor> getConstructors() {
116 return Collections.singleton(primaryConstructor);
117 }
118
119 @NotNull
120 @Override
121 public TypeConstructor getTypeConstructor() {
122 return typeConstructor;
123 }
124
125 @Nullable
126 @Override
127 public ClassDescriptor getClassObjectDescriptor() {
128 return classObjectDescriptor;
129 }
130
131 @NotNull
132 @Override
133 public ClassKind getKind() {
134 return kind;
135 }
136
137 @NotNull
138 @Override
139 public Modality getModality() {
140 return Modality.FINAL;
141 }
142
143 @NotNull
144 @Override
145 public Visibility getVisibility() {
146 return Visibilities.PUBLIC;
147 }
148
149 @Override
150 public boolean isInner() {
151 return false;
152 }
153
154 @Nullable
155 @Override
156 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
157 return primaryConstructor;
158 }
159
160 @NotNull
161 @Override
162 public Annotations getAnnotations() {
163 // TODO
164 return Annotations.EMPTY;
165 }
166
167 private class EnumEntryScope extends JetScopeImpl {
168 private final MemoizedFunctionToNotNull<Name, Collection<FunctionDescriptor>> functions;
169 private final MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> properties;
170 private final NotNullLazyValue<Collection<DeclarationDescriptor>> allDescriptors;
171
172 public EnumEntryScope(@NotNull StorageManager storageManager) {
173 this.functions = storageManager.createMemoizedFunction(new Function1<Name, Collection<FunctionDescriptor>>() {
174 @Override
175 public Collection<FunctionDescriptor> invoke(Name name) {
176 return computeFunctions(name);
177 }
178 });
179 this.properties = storageManager.createMemoizedFunction(new Function1<Name, Collection<PropertyDescriptor>>() {
180 @Override
181 public Collection<PropertyDescriptor> invoke(Name name) {
182 return computeProperties(name);
183 }
184 });
185 this.allDescriptors = storageManager.createLazyValue(new Function0<Collection<DeclarationDescriptor>>() {
186 @Override
187 public Collection<DeclarationDescriptor> invoke() {
188 return computeAllDeclarations();
189 }
190 });
191 }
192
193 @NotNull
194 @Override
195 @SuppressWarnings("unchecked")
196 public Collection<VariableDescriptor> getProperties(@NotNull Name name) {
197 return (Collection) properties.invoke(name);
198 }
199
200 @NotNull
201 @SuppressWarnings("unchecked")
202 private Collection<PropertyDescriptor> computeProperties(@NotNull Name name) {
203 return resolveFakeOverrides(name, (Collection) getSupertypeScope().getProperties(name));
204 }
205
206 @NotNull
207 @Override
208 public Collection<FunctionDescriptor> getFunctions(@NotNull Name name) {
209 return functions.invoke(name);
210 }
211
212 @NotNull
213 private Collection<FunctionDescriptor> computeFunctions(@NotNull Name name) {
214 return resolveFakeOverrides(name, getSupertypeScope().getFunctions(name));
215 }
216
217 @NotNull
218 private JetScope getSupertypeScope() {
219 Collection<JetType> supertype = getTypeConstructor().getSupertypes();
220 assert supertype.size() == 1 : "Enum entry and its class object both should have exactly one supertype: " + supertype;
221 return supertype.iterator().next().getMemberScope();
222 }
223
224 @NotNull
225 private <D extends CallableMemberDescriptor> Collection<D> resolveFakeOverrides(
226 @NotNull Name name,
227 @NotNull Collection<D> fromSupertypes
228 ) {
229 final Set<D> result = new HashSet<D>();
230
231 OverridingUtil.generateOverridesInFunctionGroup(
232 name, fromSupertypes, Collections.<D>emptySet(), EnumEntrySyntheticClassDescriptor.this,
233 new OverridingUtil.DescriptorSink() {
234 @Override
235 @SuppressWarnings("unchecked")
236 public void addToScope(@NotNull CallableMemberDescriptor fakeOverride) {
237 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null);
238 result.add((D) fakeOverride);
239 }
240
241 @Override
242 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
243 // Do nothing
244 }
245 }
246 );
247
248 return result;
249 }
250
251 @NotNull
252 @Override
253 public DeclarationDescriptor getContainingDeclaration() {
254 return EnumEntrySyntheticClassDescriptor.this;
255 }
256
257 @NotNull
258 @Override
259 public Collection<DeclarationDescriptor> getAllDescriptors() {
260 return allDescriptors.invoke();
261 }
262
263 @NotNull
264 private Collection<DeclarationDescriptor> computeAllDeclarations() {
265 Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
266 for (Name name : enumMemberNames.invoke()) {
267 result.addAll(getFunctions(name));
268 result.addAll(getProperties(name));
269 }
270 return result;
271 }
272
273 @Override
274 public void printScopeStructure(@NotNull Printer p) {
275 p.println("enum entry scope for " + EnumEntrySyntheticClassDescriptor.this);
276 }
277 }
278 }