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.resolve.lazy.descriptors;
018
019 import com.google.common.base.Predicate;
020 import com.google.common.collect.Collections2;
021 import com.google.common.collect.Lists;
022 import com.intellij.psi.PsiElement;
023 import com.intellij.psi.PsiNameIdentifierOwner;
024 import kotlin.collections.CollectionsKt;
025 import kotlin.Unit;
026 import kotlin.jvm.functions.Function0;
027 import kotlin.jvm.functions.Function1;
028 import org.jetbrains.annotations.Mutable;
029 import org.jetbrains.annotations.NotNull;
030 import org.jetbrains.annotations.Nullable;
031 import org.jetbrains.annotations.ReadOnly;
032 import org.jetbrains.kotlin.builtins.KotlinBuiltIns;
033 import org.jetbrains.kotlin.descriptors.*;
034 import org.jetbrains.kotlin.descriptors.annotations.Annotations;
035 import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorBase;
036 import org.jetbrains.kotlin.descriptors.impl.FunctionDescriptorImpl;
037 import org.jetbrains.kotlin.incremental.components.NoLookupLocation;
038 import org.jetbrains.kotlin.lexer.KtTokens;
039 import org.jetbrains.kotlin.name.Name;
040 import org.jetbrains.kotlin.psi.*;
041 import org.jetbrains.kotlin.psi.psiUtil.KtPsiUtilKt;
042 import org.jetbrains.kotlin.resolve.*;
043 import org.jetbrains.kotlin.resolve.lazy.ForceResolveUtil;
044 import org.jetbrains.kotlin.resolve.lazy.LazyClassContext;
045 import org.jetbrains.kotlin.resolve.lazy.LazyEntity;
046 import org.jetbrains.kotlin.resolve.lazy.data.KtClassInfoUtil;
047 import org.jetbrains.kotlin.resolve.lazy.data.KtClassLikeInfo;
048 import org.jetbrains.kotlin.resolve.lazy.data.KtClassOrObjectInfo;
049 import org.jetbrains.kotlin.resolve.lazy.data.KtObjectInfo;
050 import org.jetbrains.kotlin.resolve.lazy.declarations.ClassMemberDeclarationProvider;
051 import org.jetbrains.kotlin.resolve.scopes.MemberScope;
052 import org.jetbrains.kotlin.resolve.scopes.LexicalScope;
053 import org.jetbrains.kotlin.resolve.scopes.StaticScopeForKotlinClass;
054 import org.jetbrains.kotlin.resolve.source.KotlinSourceElementKt;
055 import org.jetbrains.kotlin.storage.MemoizedFunctionToNotNull;
056 import org.jetbrains.kotlin.storage.NotNullLazyValue;
057 import org.jetbrains.kotlin.storage.NullableLazyValue;
058 import org.jetbrains.kotlin.storage.StorageManager;
059 import org.jetbrains.kotlin.types.*;
060
061 import java.util.ArrayList;
062 import java.util.Collection;
063 import java.util.Collections;
064 import java.util.List;
065
066 import static kotlin.collections.CollectionsKt.firstOrNull;
067 import static org.jetbrains.kotlin.diagnostics.Errors.CYCLIC_INHERITANCE_HIERARCHY;
068 import static org.jetbrains.kotlin.diagnostics.Errors.TYPE_PARAMETERS_IN_ENUM;
069 import static org.jetbrains.kotlin.resolve.BindingContext.TYPE;
070 import static org.jetbrains.kotlin.resolve.ModifiersChecker.*;
071
072 public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDescriptorWithResolutionScopes, LazyEntity {
073 private static final Predicate<KotlinType> VALID_SUPERTYPE = new Predicate<KotlinType>() {
074 @Override
075 public boolean apply(KotlinType type) {
076 assert !type.isError() : "Error types must be filtered out in DescriptorResolver";
077 return TypeUtils.getClassDescriptor(type) != null;
078 }
079 };
080 private final LazyClassContext c;
081
082 private final ClassMemberDeclarationProvider declarationProvider;
083
084 private final LazyClassTypeConstructor typeConstructor;
085 private final Modality modality;
086 private final Visibility visibility;
087 private final NotNullLazyValue<ClassKind> kind;
088 private final NotNullLazyValue<Boolean> isInner;
089 private final NotNullLazyValue<Boolean> isData;
090
091 private final Annotations annotations;
092 private final Annotations danglingAnnotations;
093 private final NullableLazyValue<LazyClassDescriptor> companionObjectDescriptor;
094 private final MemoizedFunctionToNotNull<KtObjectDeclaration, ClassDescriptor> extraCompanionObjectDescriptors;
095
096 private final LazyClassMemberScope unsubstitutedMemberScope;
097 private final MemberScope staticScope;
098
099 private final NullableLazyValue<Void> forceResolveAllContents;
100 private final boolean isCompanionObject;
101
102 private final ClassResolutionScopesSupport resolutionScopesSupport;
103 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters;
104
105 private final NotNullLazyValue<LexicalScope> scopeForInitializerResolution;
106
107 public LazyClassDescriptor(
108 @NotNull final LazyClassContext c,
109 @NotNull DeclarationDescriptor containingDeclaration,
110 @NotNull Name name,
111 @NotNull final KtClassLikeInfo classLikeInfo
112 ) {
113 super(c.getStorageManager(), containingDeclaration, name,
114 KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject())
115 );
116 this.c = c;
117
118 KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
119 if (classOrObject != null) {
120 this.c.getTrace().record(BindingContext.CLASS, classOrObject, this);
121 }
122 this.c.getTrace().record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this);
123
124 this.declarationProvider = c.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);
125
126 this.unsubstitutedMemberScope = createMemberScope(c, this.declarationProvider);
127 this.staticScope = new StaticScopeForKotlinClass(this);
128
129 this.typeConstructor = new LazyClassTypeConstructor();
130
131 final ClassKind syntaxKind = classLikeInfo.getClassKind();
132 this.isCompanionObject = classLikeInfo instanceof KtObjectInfo && ((KtObjectInfo) classLikeInfo).isCompanionObject();
133
134 final KtModifierList modifierList = classLikeInfo.getModifierList();
135 if (syntaxKind.isSingleton()) {
136 this.modality = Modality.FINAL;
137 }
138 else {
139 Modality defaultModality = syntaxKind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL;
140 this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
141 }
142
143 boolean isLocal = classOrObject != null && KtPsiUtil.isLocal(classOrObject);
144 Visibility defaultVisibility;
145 if (syntaxKind == ClassKind.ENUM_ENTRY || (syntaxKind == ClassKind.OBJECT && isCompanionObject)) {
146 defaultVisibility = Visibilities.PUBLIC;
147 }
148 else {
149 defaultVisibility = Visibilities.DEFAULT_VISIBILITY;
150 }
151 this.visibility = isLocal ? Visibilities.LOCAL : resolveVisibilityFromModifiers(modifierList, defaultVisibility);
152
153 StorageManager storageManager = c.getStorageManager();
154 final ClassDescriptor descriptor = this;
155
156 this.isInner = storageManager.createLazyValue(new Function0<Boolean>() {
157 @Override
158 public Boolean invoke() {
159 return isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(descriptor);
160 }
161 });
162
163 this.isData = storageManager.createLazyValue(new Function0<Boolean>() {
164 @Override
165 public Boolean invoke() {
166 return modifierList != null && modifierList.hasModifier(KtTokens.DATA_KEYWORD);
167 }
168 });
169
170 this.kind = storageManager.createLazyValue(new Function0<ClassKind>() {
171 @Override
172 public ClassKind invoke() {
173 return (syntaxKind == ClassKind.CLASS && modifierList != null && modifierList.hasModifier(KtTokens.ANNOTATION_KEYWORD)) ? ClassKind.ANNOTATION_CLASS : syntaxKind;
174 }
175 });
176 // Annotation entries are taken from both own annotations (if any) and object literal annotations (if any)
177 List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
178 if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
179 // TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
180 annotationEntries.addAll(KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
181 }
182 if (modifierList != null) {
183 annotationEntries.addAll(modifierList.getAnnotationEntries());
184 }
185 if (!annotationEntries.isEmpty()) {
186 this.annotations = new LazyAnnotations(
187 new LazyAnnotationsContext(
188 c.getAnnotationResolver(),
189 storageManager,
190 c.getTrace()
191 ) {
192 @NotNull
193 @Override
194 public LexicalScope getScope() {
195 return getOuterScope();
196 }
197 },
198 annotationEntries
199 );
200 }
201 else {
202 this.annotations = Annotations.Companion.getEMPTY();
203 }
204
205 List<KtAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations();
206 if (jetDanglingAnnotations.isEmpty()) {
207 this.danglingAnnotations = Annotations.Companion.getEMPTY();
208 }
209 else {
210 this.danglingAnnotations = new LazyAnnotations(
211 new LazyAnnotationsContext(
212 c.getAnnotationResolver(),
213 storageManager,
214 c.getTrace()
215 ) {
216 @NotNull
217 @Override
218 public LexicalScope getScope() {
219 return getScopeForMemberDeclarationResolution();
220 }
221 },
222 jetDanglingAnnotations
223 );
224 }
225
226 this.companionObjectDescriptor = storageManager.createNullableLazyValue(new Function0<LazyClassDescriptor>() {
227 @Override
228 public LazyClassDescriptor invoke() {
229 return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed());
230 }
231 });
232 this.extraCompanionObjectDescriptors = storageManager.createMemoizedFunction(new Function1<KtObjectDeclaration, ClassDescriptor>() {
233 @Override
234 public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
235 return computeCompanionObjectDescriptor(companionObject);
236 }
237 });
238 this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0<Void>() {
239 @Override
240 public Void invoke() {
241 doForceResolveAllContents();
242 return null;
243 }
244 }, null);
245
246 this.resolutionScopesSupport = new ClassResolutionScopesSupport(this, storageManager, new Function0<LexicalScope>() {
247 @Override
248 public LexicalScope invoke() {
249 return getOuterScope();
250 }
251 });
252
253 this.parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
254 @Override
255 public List<TypeParameterDescriptor> invoke() {
256 KtClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
257 KtTypeParameterList typeParameterList = classInfo.getTypeParameterList();
258 if (typeParameterList == null) return Collections.emptyList();
259
260 if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) {
261 c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList));
262 }
263
264 List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
265 if (typeParameters.isEmpty()) return Collections.emptyList();
266
267 List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
268
269 for (int i = 0; i < typeParameters.size(); i++) {
270 parameters.add(new LazyTypeParameterDescriptor(c, LazyClassDescriptor.this, typeParameters.get(i), i));
271 }
272
273 return parameters;
274 }
275 });
276
277 this.scopeForInitializerResolution = storageManager.createLazyValue(new Function0<LexicalScope>() {
278 @Override
279 public LexicalScope invoke() {
280 return ClassResolutionScopesSupportKt.scopeForInitializerResolution(LazyClassDescriptor.this,
281 createInitializerScopeParent(),
282 classLikeInfo.getPrimaryConstructorParameters());
283 }
284 });
285 }
286
287 @NotNull
288 private DeclarationDescriptor createInitializerScopeParent() {
289 ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
290 if (primaryConstructor != null) return primaryConstructor;
291
292 return new FunctionDescriptorImpl(LazyClassDescriptor.this, null, Annotations.Companion.getEMPTY(),
293 Name.special("<init-blocks>"),
294 CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE) {
295 @NotNull
296 @Override
297 protected FunctionDescriptorImpl createSubstitutedCopy(
298 @NotNull DeclarationDescriptor newOwner,
299 @Nullable FunctionDescriptor original,
300 @NotNull Kind kind,
301 @Nullable Name newName,
302 boolean preserveSource
303 ) {
304 throw new UnsupportedOperationException();
305 }
306
307 @NotNull
308 @Override
309 public FunctionDescriptor copy(
310 DeclarationDescriptor newOwner,
311 Modality modality,
312 Visibility visibility,
313 Kind kind,
314 boolean copyOverrides
315 ) {
316 throw new UnsupportedOperationException();
317 }
318 };
319 }
320
321 // NOTE: Called from constructor!
322 @NotNull
323 protected LazyClassMemberScope createMemberScope(
324 @NotNull LazyClassContext c,
325 @NotNull ClassMemberDeclarationProvider declarationProvider
326 ) {
327 return new LazyClassMemberScope(c, declarationProvider, this, c.getTrace());
328 }
329
330 @NotNull
331 @Override
332 public MemberScope getUnsubstitutedMemberScope() {
333 return unsubstitutedMemberScope;
334 }
335
336 @NotNull
337 protected LexicalScope getOuterScope() {
338 return c.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declarationProvider.getOwnerInfo().getScopeAnchor());
339 }
340
341 @Override
342 @NotNull
343 public LexicalScope getScopeForClassHeaderResolution() {
344 return resolutionScopesSupport.getScopeForClassHeaderResolution().invoke();
345 }
346
347 @Override
348 @NotNull
349 public LexicalScope getScopeForConstructorHeaderResolution() {
350 return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke();
351 }
352
353 @Override
354 @NotNull
355 public LexicalScope getScopeForCompanionObjectHeaderResolution() {
356 return resolutionScopesSupport.getScopeForCompanionObjectHeaderResolution().invoke();
357 }
358
359 @Override
360 @NotNull
361 public LexicalScope getScopeForMemberDeclarationResolution() {
362 return resolutionScopesSupport.getScopeForMemberDeclarationResolution().invoke();
363 }
364
365 @Override
366 @NotNull
367 public LexicalScope getScopeForStaticMemberDeclarationResolution() {
368 return resolutionScopesSupport.getScopeForStaticMemberDeclarationResolution().invoke();
369 }
370
371 @Override
372 @NotNull
373 public LexicalScope getScopeForInitializerResolution() {
374 return scopeForInitializerResolution.invoke();
375 }
376
377 @NotNull
378 @Override
379 public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
380 //noinspection unchecked
381 return (Collection) CollectionsKt.filter(
382 DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope),
383 new Function1<DeclarationDescriptor, Boolean>() {
384 @Override
385 public Boolean invoke(DeclarationDescriptor descriptor) {
386 return descriptor instanceof CallableMemberDescriptor
387 && ((CallableMemberDescriptor) descriptor).getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
388 }
389 }
390 );
391 }
392
393 @NotNull
394 @Override
395 public MemberScope getStaticScope() {
396 return staticScope;
397 }
398
399 @NotNull
400 @Override
401 public Collection<ConstructorDescriptor> getConstructors() {
402 return unsubstitutedMemberScope.getConstructors();
403 }
404
405 @Override
406 public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
407 return unsubstitutedMemberScope.getPrimaryConstructor();
408 }
409
410 @NotNull
411 @Override
412 public TypeConstructor getTypeConstructor() {
413 return typeConstructor;
414 }
415
416 @Override
417 public LazyClassDescriptor getCompanionObjectDescriptor() {
418 return companionObjectDescriptor.invoke();
419 }
420
421 @NotNull
422 @ReadOnly
423 public List<ClassDescriptor> getDescriptorsForExtraCompanionObjects() {
424 final KtObjectDeclaration allowedCompanionObject = getCompanionObjectIfAllowed();
425
426 return CollectionsKt.map(
427 CollectionsKt.filter(
428 declarationProvider.getOwnerInfo().getCompanionObjects(),
429 new Function1<KtObjectDeclaration, Boolean>() {
430 @Override
431 public Boolean invoke(KtObjectDeclaration companionObject) {
432 return companionObject != allowedCompanionObject;
433 }
434 }
435 ),
436 new Function1<KtObjectDeclaration, ClassDescriptor>() {
437 @Override
438 public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
439 return extraCompanionObjectDescriptors.invoke(companionObject);
440 }
441 }
442 );
443 }
444
445 @Nullable
446 private LazyClassDescriptor computeCompanionObjectDescriptor(@Nullable KtObjectDeclaration companionObject) {
447 KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
448 if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
449 return null;
450 }
451 Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName();
452 assert name != null;
453 getUnsubstitutedMemberScope().getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
454 ClassDescriptor companionObjectDescriptor = c.getTrace().get(BindingContext.CLASS, companionObject);
455 if (companionObjectDescriptor instanceof LazyClassDescriptor) {
456 assert DescriptorUtils.isCompanionObject(companionObjectDescriptor) : "Not a companion object: " + companionObjectDescriptor;
457 return (LazyClassDescriptor) companionObjectDescriptor;
458 }
459 else {
460 return null;
461 }
462 }
463
464 @Nullable
465 private static KtClassLikeInfo getCompanionObjectInfo(@Nullable KtObjectDeclaration companionObject) {
466 if (companionObject != null) {
467 return KtClassInfoUtil.createClassLikeInfo(companionObject);
468 }
469
470 return null;
471 }
472
473 @Nullable
474 private KtObjectDeclaration getCompanionObjectIfAllowed() {
475 KtObjectDeclaration companionObject = firstOrNull(declarationProvider.getOwnerInfo().getCompanionObjects());
476 return (companionObject != null && isCompanionObjectAllowed()) ? companionObject : null;
477 }
478
479 private boolean isCompanionObjectAllowed() {
480 return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this));
481 }
482
483 @NotNull
484 @Override
485 public ClassKind getKind() {
486 return kind.invoke();
487 }
488
489 @NotNull
490 @Override
491 public Modality getModality() {
492 return modality;
493 }
494
495 @NotNull
496 @Override
497 public Visibility getVisibility() {
498 return visibility;
499 }
500
501 @Override
502 public boolean isInner() {
503 return isInner.invoke();
504 }
505
506 @Override
507 public boolean isData() {
508 return isData.invoke();
509 }
510
511 @Override
512 public boolean isCompanionObject() {
513 return isCompanionObject;
514 }
515
516 @NotNull
517 @Override
518 public Annotations getAnnotations() {
519 return annotations;
520 }
521
522 @NotNull
523 public Annotations getDanglingAnnotations() {
524 return danglingAnnotations;
525 }
526
527 @Override
528 public String toString() {
529 // not using descriptor render to preserve laziness
530 return "lazy class " + getName().toString();
531 }
532
533 @Override
534 public void forceResolveAllContents() {
535 forceResolveAllContents.invoke();
536 }
537
538 private void doForceResolveAllContents() {
539 resolveMemberHeaders();
540 ClassDescriptor companionObjectDescriptor = getCompanionObjectDescriptor();
541 if (companionObjectDescriptor != null) {
542 ForceResolveUtil.forceResolveAllContents(companionObjectDescriptor);
543 }
544
545 ForceResolveUtil.forceResolveAllContents(getConstructors());
546 ForceResolveUtil.forceResolveAllContents(getDescriptorsForExtraCompanionObjects());
547 ForceResolveUtil.forceResolveAllContents(getUnsubstitutedMemberScope());
548 ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
549 }
550
551 // Note: headers of member classes' members are not resolved
552 public void resolveMemberHeaders() {
553 ForceResolveUtil.forceResolveAllContents(getAnnotations());
554 ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());
555
556 getCompanionObjectDescriptor();
557
558 getDescriptorsForExtraCompanionObjects();
559
560 getConstructors();
561 getContainingDeclaration();
562 getThisAsReceiverParameter();
563 getKind();
564 getModality();
565 getName();
566 getOriginal();
567 getScopeForClassHeaderResolution();
568 getScopeForMemberDeclarationResolution();
569 DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope());
570 getScopeForInitializerResolution();
571 getUnsubstitutedInnerClassesScope();
572 getTypeConstructor().getSupertypes();
573 for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
574 typeParameterDescriptor.getUpperBounds();
575 }
576 getUnsubstitutedPrimaryConstructor();
577 getVisibility();
578 }
579
580 @NotNull
581 @Override
582 public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
583 return parameters.invoke();
584 }
585
586 private static class Supertypes {
587 @Mutable
588 public final Collection<KotlinType> trueSupertypes;
589 @Mutable
590 public final Collection<KotlinType> allSuperTypes;
591
592 private Supertypes(@Mutable @NotNull Collection<KotlinType> allSuperTypes) {
593 this.trueSupertypes = allSuperTypes;
594 this.allSuperTypes = new ArrayList<KotlinType>(allSuperTypes);
595 }
596
597 @NotNull
598 public Collection<KotlinType> getAllSupertypes() {
599 return allSuperTypes;
600 }
601 }
602
603 private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity {
604 private final NotNullLazyValue<Supertypes> supertypes = c.getStorageManager().createLazyValueWithPostCompute(
605 new Function0<Supertypes>() {
606 @Override
607 public Supertypes invoke() {
608 if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
609 return new Supertypes(Collections.<KotlinType>emptyList());
610 }
611
612 KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
613 if (classOrObject == null) {
614 return new Supertypes(Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType()));
615 }
616
617 List<KotlinType> allSupertypes = c.getDescriptorResolver()
618 .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
619 c.getTrace());
620
621 return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)));
622 }
623 },
624 new Function1<Boolean, Supertypes>() {
625 @Override
626 public Supertypes invoke(Boolean firstTime) {
627 return new Supertypes(Collections.<KotlinType>emptyList());
628 }
629 },
630 new Function1<Supertypes, Unit>() {
631 @Override
632 public Unit invoke(@NotNull Supertypes supertypes) {
633 findAndDisconnectLoopsInTypeHierarchy(supertypes.trueSupertypes);
634 return Unit.INSTANCE;
635 }
636 }
637 );
638
639 private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
640 @Override
641 public List<TypeParameterDescriptor> invoke() {
642 return TypeParameterUtilsKt.computeConstructorTypeParameters(LazyClassDescriptor.this);
643 }
644 });
645
646 private final NullableLazyValue<Void> forceResolveAllContents =
647 c.getStorageManager().createRecursionTolerantNullableLazyValue(new Function0<Void>() {
648 @Override
649 public Void invoke() {
650 doForceResolveAllContents();
651 return null;
652 }
653 }, null);
654
655 @NotNull
656 @Override
657 public List<TypeParameterDescriptor> getParameters() {
658 return parameters.invoke();
659 }
660
661 @NotNull
662 @Override
663 public Collection<KotlinType> getSupertypes() {
664 return supertypes.invoke().trueSupertypes;
665 }
666
667 private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection<KotlinType> supertypes) {
668 c.getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect(
669 typeConstructor, supertypes,
670 new Function1<TypeConstructor, Iterable<? extends KotlinType>>() {
671 @Override
672 public Iterable<? extends KotlinType> invoke(TypeConstructor typeConstructor) {
673 return getNeighbors(typeConstructor);
674 }
675 },
676 new Function1<KotlinType, Unit>() {
677 @Override
678 public Unit invoke(KotlinType type) {
679 ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor();
680 if (supertypeDescriptor instanceof ClassDescriptor) {
681 ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
682 reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass);
683 }
684
685 return Unit.INSTANCE;
686 }
687 }
688 );
689 }
690
691 private void reportCyclicInheritanceHierarchyError(
692 @NotNull BindingTrace trace,
693 @NotNull ClassDescriptor classDescriptor,
694 @NotNull ClassDescriptor superclass
695 ) {
696 PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);
697
698 PsiElement elementToMark = null;
699 if (psiElement instanceof KtClassOrObject) {
700 KtClassOrObject classOrObject = (KtClassOrObject) psiElement;
701 for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) {
702 KtTypeReference typeReference = delegationSpecifier.getTypeReference();
703 if (typeReference == null) continue;
704 KotlinType supertype = trace.get(TYPE, typeReference);
705 if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
706 elementToMark = typeReference;
707 }
708 }
709 }
710 if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
711 PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
712 PsiElement nameIdentifier = namedElement.getNameIdentifier();
713 if (nameIdentifier != null) {
714 elementToMark = nameIdentifier;
715 }
716 }
717 if (elementToMark != null) {
718 trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
719 }
720 }
721
722 private Collection<KotlinType> getNeighbors(TypeConstructor from) {
723 // Supertypes + type for container
724 Collection<KotlinType> neighbours = new ArrayList<KotlinType>(
725 from instanceof LazyClassTypeConstructor
726 ? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes()
727 : from.getSupertypes()
728 );
729
730 ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor();
731 if (fromDescriptor != null) {
732 DeclarationDescriptor container = fromDescriptor.getContainingDeclaration();
733 if (container instanceof ClassDescriptor) {
734 neighbours.add(((ClassDescriptor) container).getDefaultType());
735 }
736 }
737 return neighbours;
738 }
739
740 @Override
741 public boolean isFinal() {
742 return getModality() == Modality.FINAL;
743 }
744
745 @Override
746 public boolean isDenotable() {
747 return true;
748 }
749
750 @Override
751 @NotNull
752 public ClassifierDescriptor getDeclarationDescriptor() {
753 return LazyClassDescriptor.this;
754 }
755
756 @NotNull
757 @Override
758 public Annotations getAnnotations() {
759 return Annotations.Companion.getEMPTY(); // TODO
760 }
761
762 @Override
763 public String toString() {
764 return LazyClassDescriptor.this.getName().toString();
765 }
766
767 @Override
768 public void forceResolveAllContents() {
769 forceResolveAllContents.invoke();
770 }
771
772 private void doForceResolveAllContents() {
773 ForceResolveUtil.forceResolveAllContents(getAnnotations());
774 ForceResolveUtil.forceResolveAllContents(getSupertypes());
775 ForceResolveUtil.forceResolveAllContents(getParameters());
776 }
777 }
778 }