001 /*
002 * Copyright 2010-2015 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.kotlin.descriptors.impl;
018
019 import kotlin.jvm.functions.Function0;
020 import kotlin.jvm.functions.Function1;
021 import org.jetbrains.annotations.NotNull;
022 import org.jetbrains.annotations.Nullable;
023 import org.jetbrains.kotlin.descriptors.*;
024 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
025 import org.jetbrains.kotlin.incremental.components.LookupLocation;
026 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
027 import org.jetbrains.kotlin.name.Name;
028 import org.jetbrains.kotlin.resolve.DescriptorFactory;
029 import org.jetbrains.kotlin.resolve.OverridingStrategy;
030 import org.jetbrains.kotlin.resolve.OverridingUtil;
031 import org.jetbrains.kotlin.resolve.scopes.DescriptorKindFilter;
032 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
033 import org.jetbrains.kotlin.resolve.scopes.MemberScopeImpl;
034 import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinClass;
035 import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
036 import org.jetbrains.kotlin.storage.NotNullLazyValue;
037 import org.jetbrains.kotlin.storage.StorageManager;
038 import org.jetbrains.kotlin.types.KotlinType;
039 import org.jetbrains.kotlin.types.TypeConstructor;
040 import org.jetbrains.kotlin.types.TypeConstructorImpl;
041 import org.jetbrains.kotlin.utils.Printer;
042
043 import java.util.*;
044
045 public class EnumEntrySyntheticClassDescriptor extends ClassDescriptorBase {
046 private final TypeConstructor typeConstructor;
047 private final ConstructorDescriptor primaryConstructor;
048 private final MemberScope scope;
049 private final MemberScope staticScope = new StaticScopeForKotlinClass(this);
050 private final NotNullLazyValue<Collection<Name>> enumMemberNames;
051 private final Annotations annotations;
052
053 /**
054 * Creates and initializes descriptors for enum entry with the given name and its companion 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 @NotNull Annotations annotations,
064 @NotNull SourceElement source
065 ) {
066 KotlinType enumType = enumClass.getDefaultType();
067
068 return new EnumEntrySyntheticClassDescriptor(storageManager, enumClass, enumType, name, enumMemberNames, annotations, source);
069 }
070
071 private EnumEntrySyntheticClassDescriptor(
072 @NotNull StorageManager storageManager,
073 @NotNull ClassDescriptor containingClass,
074 @NotNull KotlinType supertype,
075 @NotNull Name name,
076 @NotNull NotNullLazyValue<Collection<Name>> enumMemberNames,
077 @NotNull Annotations annotations,
078 @NotNull SourceElement source
079 ) {
080 super(storageManager, containingClass, name, source);
081 assert containingClass.getKind() == ClassKind.ENUM_CLASS;
082
083 this.annotations = annotations;
084 this.typeConstructor =
085 TypeConstructorImpl.createForClass(this, getAnnotations(), true, "enum entry", Collections.<TypeParameterDescriptor>emptyList(),
086 Collections.singleton(supertype));
087
088 this.scope = new EnumEntryScope(storageManager);
089 this.enumMemberNames = enumMemberNames;
090
091 ConstructorDescriptorImpl primaryConstructor = DescriptorFactory.createPrimaryConstructorForObject(this, source);
092 primaryConstructor.setReturnType(getDefaultType());
093 this.primaryConstructor = primaryConstructor;
094 }
095
096 @NotNull
097 @Override
098 public MemberScope getUnsubstitutedMemberScope() {
099 return scope;
100 }
101
102 @NotNull
103 @Override
104 public MemberScope getStaticScope() {
105 return staticScope;
106 }
107
108 @NotNull
109 @Override
110 public Collection<ConstructorDescriptor> getConstructors() {
111 return Collections.singleton(primaryConstructor);
112 }
113
114 @NotNull
115 @Override
116 public TypeConstructor getTypeConstructor() {
117 return typeConstructor;
118 }
119
120 @Nullable
121 @Override
122 public ClassDescriptor getCompanionObjectDescriptor() {
123 return null;
124 }
125
126 @NotNull
127 @Override
128 public ClassKind getKind() {
129 return ClassKind.ENUM_ENTRY;
130 }
131
132 @NotNull
133 @Override
134 public Modality getModality() {
135 return Modality.FINAL;
136 }
137
138 @NotNull
139 @Override
140 public Visibility getVisibility() {
141 return Visibilities.PUBLIC;
142 }
143
144 @Override
145 public boolean isInner() {
146 return false;
147 }
148
149 @Override
150 public boolean isData() {
151 return false;
152 }
153
154 @Override
155 public boolean isCompanionObject() {
156 return false;
157 }
158
159 @Nullable
160 @Override
161 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
162 return primaryConstructor;
163 }
164
165 @NotNull
166 @Override
167 public Annotations getAnnotations() {
168 return annotations;
169 }
170
171 @Override
172 public String toString() {
173 return "enum entry " + getName();
174 }
175
176 @NotNull
177 @Override
178 public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
179 return Collections.emptyList();
180 }
181
182 private class EnumEntryScope extends MemberScopeImpl {
183 private final MemoizedFunctionToNotNull<Name, Collection<FunctionDescriptor>> functions;
184 private final MemoizedFunctionToNotNull<Name, Collection<PropertyDescriptor>> properties;
185 private final NotNullLazyValue<Collection<DeclarationDescriptor>> allDescriptors;
186
187 public EnumEntryScope(@NotNull StorageManager storageManager) {
188 this.functions = storageManager.createMemoizedFunction(new Function1<Name, Collection<FunctionDescriptor>>() {
189 @Override
190 public Collection<FunctionDescriptor> invoke(Name name) {
191 return computeFunctions(name);
192 }
193 });
194
195 this.properties = storageManager.createMemoizedFunction(new Function1<Name, Collection<PropertyDescriptor>>() {
196 @Override
197 public Collection<PropertyDescriptor> invoke(Name name) {
198 return computeProperties(name);
199 }
200 });
201 this.allDescriptors = storageManager.createLazyValue(new Function0<Collection<DeclarationDescriptor>>() {
202 @Override
203 public Collection<DeclarationDescriptor> invoke() {
204 return computeAllDeclarations();
205 }
206 });
207 }
208
209 @NotNull
210 @Override
211 @SuppressWarnings({"unchecked"}) // KT-9898 Impossible implement kotlin interface in java
212 public Collection getContributedVariables(@NotNull Name name, @NotNull LookupLocation location) {
213 return properties.invoke(name);
214 }
215
216 @NotNull
217 @SuppressWarnings("unchecked")
218 private Collection<PropertyDescriptor> computeProperties(@NotNull Name name) {
219 return resolveFakeOverrides(name, (Collection) getSupertypeScope().getContributedVariables(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
220 }
221
222 @NotNull
223 @Override
224 public Collection<FunctionDescriptor> getContributedFunctions(@NotNull Name name, @NotNull LookupLocation location) {
225 return functions.invoke(name);
226 }
227
228 @NotNull
229 private Collection<FunctionDescriptor> computeFunctions(@NotNull Name name) {
230 return resolveFakeOverrides(name, getSupertypeScope().getContributedFunctions(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
231 }
232
233 @NotNull
234 private MemberScope getSupertypeScope() {
235 Collection<KotlinType> supertype = getTypeConstructor().getSupertypes();
236 assert supertype.size() == 1 : "Enum entry and its companion object both should have exactly one supertype: " + supertype;
237 return supertype.iterator().next().getMemberScope();
238 }
239
240 @NotNull
241 private <D extends CallableMemberDescriptor> Collection<D> resolveFakeOverrides(
242 @NotNull Name name,
243 @NotNull Collection<D> fromSupertypes
244 ) {
245 final Set<D> result = new LinkedHashSet<D>();
246
247 OverridingUtil.generateOverridesInFunctionGroup(
248 name, fromSupertypes, Collections.<D>emptySet(), EnumEntrySyntheticClassDescriptor.this,
249 new OverridingStrategy() {
250 @Override
251 @SuppressWarnings("unchecked")
252 public void addFakeOverride(@NotNull CallableMemberDescriptor fakeOverride) {
253 OverridingUtil.resolveUnknownVisibilityForMember(fakeOverride, null);
254 result.add((D) fakeOverride);
255 }
256
257 @Override
258 public void conflict(@NotNull CallableMemberDescriptor fromSuper, @NotNull CallableMemberDescriptor fromCurrent) {
259 // Do nothing
260 }
261 }
262 );
263
264 return result;
265 }
266
267 @NotNull
268 @Override
269 public Collection<DeclarationDescriptor> getContributedDescriptors(
270 @NotNull DescriptorKindFilter kindFilter,
271 @NotNull Function1<? super Name, Boolean> nameFilter
272 ) {
273 return allDescriptors.invoke();
274 }
275
276 @NotNull
277 private Collection<DeclarationDescriptor> computeAllDeclarations() {
278 Collection<DeclarationDescriptor> result = new HashSet<DeclarationDescriptor>();
279 for (Name name : enumMemberNames.invoke()) {
280 result.addAll(getContributedFunctions(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
281 result.addAll(getContributedVariables(name, NoLookupLocation.FOR_NON_TRACKED_SCOPE));
282 }
283 return result;
284 }
285
286 @Override
287 public void printScopeStructure(@NotNull Printer p) {
288 p.println("enum entry scope for " + EnumEntrySyntheticClassDescriptor.this);
289 }
290 }
291 }