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