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    }