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