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