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    
266                    List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
267    
268                    for (int i = 0; i < typeParameters.size(); i++) {
269                        parameters.add(new LazyTypeParameterDescriptor(c, LazyClassDescriptor.this, typeParameters.get(i), i));
270                    }
271    
272                    return parameters;
273                }
274            });
275    
276            this.scopeForInitializerResolution = storageManager.createLazyValue(new Function0<LexicalScope>() {
277                @Override
278                public LexicalScope invoke() {
279                    return ClassResolutionScopesSupportKt.scopeForInitializerResolution(LazyClassDescriptor.this,
280                                                                                        createInitializerScopeParent(),
281                                                                                        classLikeInfo.getPrimaryConstructorParameters());
282                }
283            });
284        }
285    
286        @NotNull
287        private DeclarationDescriptor createInitializerScopeParent() {
288            ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
289            if (primaryConstructor != null) return primaryConstructor;
290    
291            return new FunctionDescriptorImpl(LazyClassDescriptor.this, null, Annotations.Companion.getEMPTY(),
292                                              Name.special("<init-blocks>"),
293                                              CallableMemberDescriptor.Kind.SYNTHESIZED, SourceElement.NO_SOURCE) {
294                @NotNull
295                @Override
296                protected FunctionDescriptorImpl createSubstitutedCopy(
297                        @NotNull DeclarationDescriptor newOwner,
298                        @Nullable FunctionDescriptor original,
299                        @NotNull Kind kind,
300                        @Nullable Name newName,
301                        boolean preserveSource
302                ) {
303                    throw new UnsupportedOperationException();
304                }
305    
306                @NotNull
307                @Override
308                public FunctionDescriptor copy(
309                        DeclarationDescriptor newOwner,
310                        Modality modality,
311                        Visibility visibility,
312                        Kind kind,
313                        boolean copyOverrides
314                ) {
315                    throw new UnsupportedOperationException();
316                }
317            };
318        }
319    
320        // NOTE: Called from constructor!
321        @NotNull
322        protected LazyClassMemberScope createMemberScope(
323                @NotNull LazyClassContext c,
324                @NotNull ClassMemberDeclarationProvider declarationProvider
325        ) {
326            return new LazyClassMemberScope(c, declarationProvider, this, c.getTrace());
327        }
328    
329        @NotNull
330        @Override
331        public MemberScope getUnsubstitutedMemberScope() {
332            return unsubstitutedMemberScope;
333        }
334    
335        @NotNull
336        protected LexicalScope getOuterScope() {
337            return c.getDeclarationScopeProvider().getResolutionScopeForDeclaration(declarationProvider.getOwnerInfo().getScopeAnchor());
338        }
339    
340        @Override
341        @NotNull
342        public LexicalScope getScopeForClassHeaderResolution() {
343            return resolutionScopesSupport.getScopeForClassHeaderResolution().invoke();
344        }
345    
346        @Override
347        @NotNull
348        public LexicalScope getScopeForConstructorHeaderResolution() {
349            return resolutionScopesSupport.getScopeForConstructorHeaderResolution().invoke();
350        }
351    
352        @Override
353        @NotNull
354        public LexicalScope getScopeForCompanionObjectHeaderResolution() {
355            return resolutionScopesSupport.getScopeForCompanionObjectHeaderResolution().invoke();
356        }
357    
358        @Override
359        @NotNull
360        public LexicalScope getScopeForMemberDeclarationResolution() {
361            return resolutionScopesSupport.getScopeForMemberDeclarationResolution().invoke();
362        }
363    
364        @Override
365        @NotNull
366        public LexicalScope getScopeForStaticMemberDeclarationResolution() {
367            return resolutionScopesSupport.getScopeForStaticMemberDeclarationResolution().invoke();
368        }
369    
370        @Override
371        @NotNull
372        public LexicalScope getScopeForInitializerResolution() {
373            return scopeForInitializerResolution.invoke();
374        }
375    
376        @NotNull
377        @Override
378        public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
379            //noinspection unchecked
380            return (Collection) CollectionsKt.filter(
381                    DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope),
382                    new Function1<DeclarationDescriptor, Boolean>() {
383                        @Override
384                        public Boolean invoke(DeclarationDescriptor descriptor) {
385                            return descriptor instanceof CallableMemberDescriptor
386                                   && ((CallableMemberDescriptor) descriptor).getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
387                        }
388                    }
389            );
390        }
391    
392        @NotNull
393        @Override
394        public MemberScope getStaticScope() {
395            return staticScope;
396        }
397    
398        @NotNull
399        @Override
400        public Collection<ConstructorDescriptor> getConstructors() {
401            return unsubstitutedMemberScope.getConstructors();
402        }
403    
404        @Override
405        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
406            return unsubstitutedMemberScope.getPrimaryConstructor();
407        }
408    
409        @NotNull
410        @Override
411        public TypeConstructor getTypeConstructor() {
412            return typeConstructor;
413        }
414    
415        @Override
416        public LazyClassDescriptor getCompanionObjectDescriptor() {
417            return companionObjectDescriptor.invoke();
418        }
419    
420        @NotNull
421        @ReadOnly
422        public List<ClassDescriptor> getDescriptorsForExtraCompanionObjects() {
423            final KtObjectDeclaration allowedCompanionObject = getCompanionObjectIfAllowed();
424    
425            return CollectionsKt.map(
426                    CollectionsKt.filter(
427                            declarationProvider.getOwnerInfo().getCompanionObjects(),
428                            new Function1<KtObjectDeclaration, Boolean>() {
429                                @Override
430                                public Boolean invoke(KtObjectDeclaration companionObject) {
431                                    return companionObject != allowedCompanionObject;
432                                }
433                            }
434                    ),
435                    new Function1<KtObjectDeclaration, ClassDescriptor>() {
436                        @Override
437                        public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
438                            return extraCompanionObjectDescriptors.invoke(companionObject);
439                        }
440                    }
441            );
442        }
443    
444        @Nullable
445        private LazyClassDescriptor computeCompanionObjectDescriptor(@Nullable KtObjectDeclaration companionObject) {
446            KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
447            if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
448                return null;
449            }
450            Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName();
451            assert name != null;
452            getUnsubstitutedMemberScope().getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
453            ClassDescriptor companionObjectDescriptor = c.getTrace().get(BindingContext.CLASS, companionObject);
454            if (companionObjectDescriptor instanceof LazyClassDescriptor) {
455                assert DescriptorUtils.isCompanionObject(companionObjectDescriptor) : "Not a companion object: " + companionObjectDescriptor;
456                return (LazyClassDescriptor) companionObjectDescriptor;
457            }
458            else {
459                return null;
460            }
461        }
462    
463        @Nullable
464        private static KtClassLikeInfo getCompanionObjectInfo(@Nullable KtObjectDeclaration companionObject) {
465            if (companionObject != null) {
466                return KtClassInfoUtil.createClassLikeInfo(companionObject);
467            }
468    
469            return null;
470        }
471    
472        @Nullable
473        private KtObjectDeclaration getCompanionObjectIfAllowed() {
474            KtObjectDeclaration companionObject = firstOrNull(declarationProvider.getOwnerInfo().getCompanionObjects());
475            return (companionObject != null && isCompanionObjectAllowed()) ? companionObject : null;
476        }
477    
478        private boolean isCompanionObjectAllowed() {
479            return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this));
480        }
481    
482        @NotNull
483        @Override
484        public ClassKind getKind() {
485            return kind.invoke();
486        }
487    
488        @NotNull
489        @Override
490        public Modality getModality() {
491            return modality;
492        }
493    
494        @NotNull
495        @Override
496        public Visibility getVisibility() {
497            return visibility;
498        }
499    
500        @Override
501        public boolean isInner() {
502            return isInner.invoke();
503        }
504    
505        @Override
506        public boolean isData() {
507            return isData.invoke();
508        }
509    
510        @Override
511        public boolean isCompanionObject() {
512            return isCompanionObject;
513        }
514    
515        @NotNull
516        @Override
517        public Annotations getAnnotations() {
518            return annotations;
519        }
520    
521        @NotNull
522        public Annotations getDanglingAnnotations() {
523            return danglingAnnotations;
524        }
525    
526        @Override
527        public String toString() {
528            // not using descriptor render to preserve laziness
529            return "lazy class " + getName().toString();
530        }
531    
532        @Override
533        public void forceResolveAllContents() {
534            forceResolveAllContents.invoke();
535        }
536    
537        private void doForceResolveAllContents() {
538            resolveMemberHeaders();
539            ClassDescriptor companionObjectDescriptor = getCompanionObjectDescriptor();
540            if (companionObjectDescriptor != null) {
541                ForceResolveUtil.forceResolveAllContents(companionObjectDescriptor);
542            }
543    
544            ForceResolveUtil.forceResolveAllContents(getConstructors());
545            ForceResolveUtil.forceResolveAllContents(getDescriptorsForExtraCompanionObjects());
546            ForceResolveUtil.forceResolveAllContents(getUnsubstitutedMemberScope());
547            ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
548        }
549    
550        // Note: headers of member classes' members are not resolved
551        public void resolveMemberHeaders() {
552            ForceResolveUtil.forceResolveAllContents(getAnnotations());
553            ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());
554    
555            getCompanionObjectDescriptor();
556    
557            getDescriptorsForExtraCompanionObjects();
558    
559            getConstructors();
560            getContainingDeclaration();
561            getThisAsReceiverParameter();
562            getKind();
563            getModality();
564            getName();
565            getOriginal();
566            getScopeForClassHeaderResolution();
567            getScopeForMemberDeclarationResolution();
568            DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope());
569            getScopeForInitializerResolution();
570            getUnsubstitutedInnerClassesScope();
571            getTypeConstructor().getSupertypes();
572            for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
573                typeParameterDescriptor.getUpperBounds();
574            }
575            getUnsubstitutedPrimaryConstructor();
576            getVisibility();
577        }
578    
579        @NotNull
580        @Override
581        public List<TypeParameterDescriptor> getDeclaredTypeParameters() {
582            return parameters.invoke();
583        }
584    
585        private static class Supertypes {
586            @Mutable
587            public final Collection<KotlinType> trueSupertypes;
588            @Mutable
589            public final Collection<KotlinType> allSuperTypes;
590    
591            private Supertypes(@Mutable @NotNull Collection<KotlinType> allSuperTypes) {
592                this.trueSupertypes = allSuperTypes;
593                this.allSuperTypes = new ArrayList<KotlinType>(allSuperTypes);
594            }
595    
596            @NotNull
597            public Collection<KotlinType> getAllSupertypes() {
598                return allSuperTypes;
599            }
600        }
601    
602        private class LazyClassTypeConstructor extends AbstractClassTypeConstructor implements LazyEntity {
603            private final NotNullLazyValue<Supertypes> supertypes = c.getStorageManager().createLazyValueWithPostCompute(
604                    new Function0<Supertypes>() {
605                        @Override
606                        public Supertypes invoke() {
607                            if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
608                                return new Supertypes(Collections.<KotlinType>emptyList());
609                            }
610    
611                            KtClassOrObject classOrObject = declarationProvider.getOwnerInfo().getCorrespondingClassOrObject();
612                            if (classOrObject == null) {
613                                return new Supertypes(Collections.singleton(c.getModuleDescriptor().getBuiltIns().getAnyType()));
614                            }
615    
616                            List<KotlinType> allSupertypes = c.getDescriptorResolver()
617                                    .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
618                                                       c.getTrace());
619    
620                            return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)));
621                        }
622                    },
623                    new Function1<Boolean, Supertypes>() {
624                        @Override
625                        public Supertypes invoke(Boolean firstTime) {
626                            return new Supertypes(Collections.<KotlinType>emptyList());
627                        }
628                    },
629                    new Function1<Supertypes, Unit>() {
630                        @Override
631                        public Unit invoke(@NotNull Supertypes supertypes) {
632                            findAndDisconnectLoopsInTypeHierarchy(supertypes.trueSupertypes);
633                            return Unit.INSTANCE;
634                        }
635                    }
636            );
637    
638            private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = c.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
639                @Override
640                public List<TypeParameterDescriptor> invoke() {
641                    return TypeParameterUtilsKt.computeConstructorTypeParameters(LazyClassDescriptor.this);
642                }
643            });
644    
645            private final NullableLazyValue<Void> forceResolveAllContents =
646                    c.getStorageManager().createRecursionTolerantNullableLazyValue(new Function0<Void>() {
647                        @Override
648                        public Void invoke() {
649                            doForceResolveAllContents();
650                            return null;
651                        }
652                    }, null);
653    
654            @NotNull
655            @Override
656            public List<TypeParameterDescriptor> getParameters() {
657                return parameters.invoke();
658            }
659    
660            @NotNull
661            @Override
662            public Collection<KotlinType> getSupertypes() {
663                return supertypes.invoke().trueSupertypes;
664            }
665    
666            private void findAndDisconnectLoopsInTypeHierarchy(@Mutable Collection<KotlinType> supertypes) {
667                c.getSupertypeLoopChecker().findLoopsInSupertypesAndDisconnect(
668                        typeConstructor, supertypes,
669                        new Function1<TypeConstructor, Iterable<? extends KotlinType>>() {
670                            @Override
671                            public Iterable<? extends KotlinType> invoke(TypeConstructor typeConstructor) {
672                                return getNeighbors(typeConstructor);
673                            }
674                        },
675                        new Function1<KotlinType, Unit>() {
676                            @Override
677                            public Unit invoke(KotlinType type) {
678                                ClassifierDescriptor supertypeDescriptor = type.getConstructor().getDeclarationDescriptor();
679                                if (supertypeDescriptor instanceof ClassDescriptor) {
680                                    ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
681                                    reportCyclicInheritanceHierarchyError(c.getTrace(), LazyClassDescriptor.this, superclass);
682                                }
683    
684                                return Unit.INSTANCE;
685                            }
686                        }
687                );
688            }
689    
690            private void reportCyclicInheritanceHierarchyError(
691                    @NotNull BindingTrace trace,
692                    @NotNull ClassDescriptor classDescriptor,
693                    @NotNull ClassDescriptor superclass
694            ) {
695                PsiElement psiElement = DescriptorToSourceUtils.getSourceFromDescriptor(classDescriptor);
696    
697                PsiElement elementToMark = null;
698                if (psiElement instanceof KtClassOrObject) {
699                    KtClassOrObject classOrObject = (KtClassOrObject) psiElement;
700                    for (KtSuperTypeListEntry delegationSpecifier : classOrObject.getSuperTypeListEntries()) {
701                        KtTypeReference typeReference = delegationSpecifier.getTypeReference();
702                        if (typeReference == null) continue;
703                        KotlinType supertype = trace.get(TYPE, typeReference);
704                        if (supertype != null && supertype.getConstructor() == superclass.getTypeConstructor()) {
705                            elementToMark = typeReference;
706                        }
707                    }
708                }
709                if (elementToMark == null && psiElement instanceof PsiNameIdentifierOwner) {
710                    PsiNameIdentifierOwner namedElement = (PsiNameIdentifierOwner) psiElement;
711                    PsiElement nameIdentifier = namedElement.getNameIdentifier();
712                    if (nameIdentifier != null) {
713                        elementToMark = nameIdentifier;
714                    }
715                }
716                if (elementToMark != null) {
717                    trace.report(CYCLIC_INHERITANCE_HIERARCHY.on(elementToMark));
718                }
719            }
720    
721            private Collection<KotlinType> getNeighbors(TypeConstructor from) {
722                // Supertypes + type for container
723                Collection<KotlinType> neighbours = new ArrayList<KotlinType>(
724                        from instanceof LazyClassTypeConstructor
725                                 ? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes()
726                                 : from.getSupertypes()
727                );
728    
729                ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor();
730                if (fromDescriptor != null) {
731                    DeclarationDescriptor container = fromDescriptor.getContainingDeclaration();
732                    if (container instanceof ClassDescriptor) {
733                        neighbours.add(((ClassDescriptor) container).getDefaultType());
734                    }
735                }
736                return neighbours;
737            }
738    
739            @Override
740            public boolean isFinal() {
741                return getModality() == Modality.FINAL;
742            }
743    
744            @Override
745            public boolean isDenotable() {
746                return true;
747            }
748    
749            @Override
750            @NotNull
751            public ClassifierDescriptor getDeclarationDescriptor() {
752                return LazyClassDescriptor.this;
753            }
754    
755            @NotNull
756            @Override
757            public Annotations getAnnotations() {
758                return Annotations.Companion.getEMPTY(); // TODO
759            }
760    
761            @Override
762            public String toString() {
763                return LazyClassDescriptor.this.getName().toString();
764            }
765    
766            @Override
767            public void forceResolveAllContents() {
768                forceResolveAllContents.invoke();
769            }
770    
771            private void doForceResolveAllContents() {
772                ForceResolveUtil.forceResolveAllContents(getAnnotations());
773                ForceResolveUtil.forceResolveAllContents(getSupertypes());
774                ForceResolveUtil.forceResolveAllContents(getParameters());
775            }
776        }
777    }