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