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