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