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