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