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