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