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