001    /*
002     * Copyright 2010-2014 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.jet.lang.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 kotlin.Function0;
024    import kotlin.Function1;
025    import kotlin.KotlinPackage;
026    import kotlin.Unit;
027    import org.jetbrains.annotations.Mutable;
028    import org.jetbrains.annotations.NotNull;
029    import org.jetbrains.annotations.Nullable;
030    import org.jetbrains.annotations.ReadOnly;
031    import org.jetbrains.jet.lang.descriptors.*;
032    import org.jetbrains.jet.lang.descriptors.annotations.Annotations;
033    import org.jetbrains.jet.lang.descriptors.impl.ClassDescriptorBase;
034    import org.jetbrains.jet.lang.psi.*;
035    import org.jetbrains.jet.lang.resolve.BindingContext;
036    import org.jetbrains.jet.lang.resolve.DescriptorUtils;
037    import org.jetbrains.jet.lang.resolve.TypeHierarchyResolver;
038    import org.jetbrains.jet.lang.resolve.lazy.ForceResolveUtil;
039    import org.jetbrains.jet.lang.resolve.lazy.LazyEntity;
040    import org.jetbrains.jet.lang.resolve.lazy.ResolveSession;
041    import org.jetbrains.jet.lang.resolve.lazy.ScopeProvider;
042    import org.jetbrains.jet.lang.resolve.lazy.data.JetClassInfoUtil;
043    import org.jetbrains.jet.lang.resolve.lazy.data.JetClassLikeInfo;
044    import org.jetbrains.jet.lang.resolve.lazy.data.SyntheticClassObjectInfo;
045    import org.jetbrains.jet.lang.resolve.lazy.declarations.ClassMemberDeclarationProvider;
046    import org.jetbrains.jet.lang.resolve.name.Name;
047    import org.jetbrains.jet.lang.resolve.scopes.*;
048    import org.jetbrains.jet.lang.types.JetType;
049    import org.jetbrains.jet.lang.types.TypeConstructor;
050    import org.jetbrains.jet.lang.types.TypeUtils;
051    import org.jetbrains.jet.lang.types.lang.KotlinBuiltIns;
052    import org.jetbrains.jet.storage.MemoizedFunctionToNotNull;
053    import org.jetbrains.jet.storage.NotNullLazyValue;
054    import org.jetbrains.jet.storage.NullableLazyValue;
055    import org.jetbrains.jet.storage.StorageManager;
056    
057    import java.util.*;
058    
059    import static org.jetbrains.jet.lang.diagnostics.Errors.CLASS_OBJECT_NOT_ALLOWED;
060    import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isSyntheticClassObject;
061    import static org.jetbrains.jet.lang.resolve.ModifiersChecker.*;
062    import static org.jetbrains.jet.lang.resolve.name.SpecialNames.getClassObjectName;
063    
064    public class LazyClassDescriptor extends ClassDescriptorBase implements ClassDescriptorWithResolutionScopes, LazyEntity {
065        private static final Predicate<JetType> VALID_SUPERTYPE = new Predicate<JetType>() {
066            @Override
067            public boolean apply(JetType type) {
068                assert !type.isError() : "Error types must be filtered out in DescriptorResolver";
069                return TypeUtils.getClassDescriptor(type) != null;
070            }
071        };
072        private final ResolveSession resolveSession;
073    
074        private final JetClassLikeInfo originalClassInfo;
075        private final ClassMemberDeclarationProvider declarationProvider;
076    
077        private final LazyClassTypeConstructor typeConstructor;
078        private final Modality modality;
079        private final Visibility visibility;
080        private final ClassKind kind;
081        private final boolean isInner;
082    
083        private final Annotations annotations;
084        private final NullableLazyValue<ClassDescriptorWithResolutionScopes> classObjectDescriptor;
085        private final MemoizedFunctionToNotNull<JetClassObject, ClassDescriptorWithResolutionScopes> extraClassObjectDescriptors;
086    
087        private final LazyClassMemberScope unsubstitutedMemberScope;
088    
089        private final NotNullLazyValue<JetScope> scopeForClassHeaderResolution;
090        private final NotNullLazyValue<JetScope> scopeForMemberDeclarationResolution;
091        private final NotNullLazyValue<JetScope> scopeForPropertyInitializerResolution;
092    
093        private final NullableLazyValue<Void> forceResolveAllContents;
094    
095        public LazyClassDescriptor(
096                @NotNull final ResolveSession resolveSession,
097                @NotNull DeclarationDescriptor containingDeclaration,
098                @NotNull Name name,
099                @NotNull JetClassLikeInfo classLikeInfo
100        ) {
101            super(resolveSession.getStorageManager(), containingDeclaration, name);
102            this.resolveSession = resolveSession;
103    
104            if (classLikeInfo.getCorrespondingClassOrObject() != null) {
105                this.resolveSession.getTrace().record(BindingContext.CLASS, classLikeInfo.getCorrespondingClassOrObject(), this);
106            }
107            this.resolveSession.getTrace().record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this);
108    
109            this.originalClassInfo = classLikeInfo;
110            this.declarationProvider = resolveSession.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);
111    
112            this.unsubstitutedMemberScope = createMemberScope(resolveSession, this.declarationProvider);
113    
114            this.typeConstructor = new LazyClassTypeConstructor();
115    
116            this.kind = classLikeInfo.getClassKind();
117    
118            JetModifierList modifierList = classLikeInfo.getModifierList();
119            if (kind.isSingleton()) {
120                this.modality = Modality.FINAL;
121            }
122            else {
123                Modality defaultModality = kind == ClassKind.TRAIT ? Modality.ABSTRACT : Modality.FINAL;
124                this.modality = resolveModalityFromModifiers(modifierList, defaultModality);
125            }
126            this.visibility = isSyntheticClassObject(this)
127                              ? DescriptorUtils.getSyntheticClassObjectVisibility()
128                              : resolveVisibilityFromModifiers(modifierList, getDefaultClassVisibility(this));
129            this.isInner = isInnerClass(modifierList);
130    
131            StorageManager storageManager = resolveSession.getStorageManager();
132    
133    
134            if (modifierList != null) {
135                this.annotations = new LazyAnnotations(
136                        new LazyAnnotationsContext(
137                                resolveSession.getAnnotationResolver(),
138                                resolveSession.getStorageManager(),
139                                resolveSession.getTrace()
140                        ) {
141                            @NotNull
142                            @Override
143                            public JetScope getScope() {
144                                JetClassLikeInfo ownerInfo = declarationProvider.getOwnerInfo();
145                                return resolveSession.getScopeProvider().getResolutionScopeForDeclaration(ownerInfo.getScopeAnchor());
146                            }
147                        },
148                        modifierList.getAnnotationEntries()
149                    );
150    
151            }
152            else {
153                this.annotations = Annotations.EMPTY;
154            }
155    
156            this.classObjectDescriptor = storageManager.createNullableLazyValue(new Function0<ClassDescriptorWithResolutionScopes>() {
157                @Override
158                public ClassDescriptorWithResolutionScopes invoke() {
159                    return computeClassObjectDescriptor(declarationProvider.getOwnerInfo().getClassObject());
160                }
161            });
162            this.extraClassObjectDescriptors = storageManager.createMemoizedFunction(new Function1<JetClassObject, ClassDescriptorWithResolutionScopes>() {
163                @Override
164                public ClassDescriptorWithResolutionScopes invoke(JetClassObject classObject) {
165                    return computeClassObjectDescriptor(classObject);
166                }
167            });
168            this.scopeForClassHeaderResolution = storageManager.createLazyValue(new Function0<JetScope>() {
169                @Override
170                public JetScope invoke() {
171                    return computeScopeForClassHeaderResolution();
172                }
173            });
174            this.scopeForMemberDeclarationResolution = storageManager.createLazyValue(new Function0<JetScope>() {
175                @Override
176                public JetScope invoke() {
177                    return computeScopeForMemberDeclarationResolution();
178                }
179            });
180            this.scopeForPropertyInitializerResolution = storageManager.createLazyValue(new Function0<JetScope>() {
181                @Override
182                public JetScope invoke() {
183                    return computeScopeForPropertyInitializerResolution();
184                }
185            });
186            this.forceResolveAllContents = storageManager.createRecursionTolerantNullableLazyValue(new Function0<Void>() {
187                @Override
188                public Void invoke() {
189                    doForceResolveAllContents();
190                    return null;
191                }
192            }, null);
193        }
194    
195        // NOTE: Called from constructor!
196        @NotNull
197        protected LazyClassMemberScope createMemberScope(
198                @NotNull ResolveSession resolveSession,
199                @NotNull ClassMemberDeclarationProvider declarationProvider
200        ) {
201            return new LazyClassMemberScope(resolveSession, declarationProvider, this, resolveSession.getTrace());
202        }
203    
204        @NotNull
205        @Override
206        public JetScope getScopeForMemberLookup() {
207            return unsubstitutedMemberScope;
208        }
209    
210        @Override
211        @NotNull
212        public JetScope getScopeForClassHeaderResolution() {
213            return scopeForClassHeaderResolution.invoke();
214        }
215    
216        @NotNull
217        private JetScope computeScopeForClassHeaderResolution() {
218            WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with type parameters for " + getName());
219            for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
220                scope.addClassifierDescriptor(typeParameterDescriptor);
221            }
222            scope.changeLockLevel(WritableScope.LockLevel.READING);
223    
224            PsiElement scopeAnchor = declarationProvider.getOwnerInfo().getScopeAnchor();
225    
226            return new ChainedScope(this, "ScopeForClassHeaderResolution: " + getName(),
227                    scope,
228                    getScopeProvider().getResolutionScopeForDeclaration(scopeAnchor));
229        }
230    
231        @Override
232        @NotNull
233        public JetScope getScopeForMemberDeclarationResolution() {
234            return scopeForMemberDeclarationResolution.invoke();
235        }
236    
237        @NotNull
238        private JetScope computeScopeForMemberDeclarationResolution() {
239            WritableScopeImpl thisScope = new WritableScopeImpl(JetScope.EMPTY, this, RedeclarationHandler.DO_NOTHING, "Scope with 'this' for " + getName());
240            thisScope.addLabeledDeclaration(this);
241            thisScope.changeLockLevel(WritableScope.LockLevel.READING);
242    
243            ClassDescriptor classObject = getClassObjectDescriptor();
244            JetScope classObjectAdapterScope = (classObject != null) ? new ClassObjectMixinScope(classObject) : JetScope.EMPTY;
245    
246            return new ChainedScope(
247                    this,
248                    "ScopeForMemberDeclarationResolution: " + getName(),
249                    thisScope,
250                    getScopeForMemberLookup(),
251                    getScopeForClassHeaderResolution(),
252                    classObjectAdapterScope);
253        }
254    
255        @Override
256        @NotNull
257        public JetScope getScopeForInitializerResolution() {
258            return scopeForPropertyInitializerResolution.invoke();
259        }
260    
261        @NotNull
262        @Override
263        public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
264            //noinspection unchecked
265            return (Collection) KotlinPackage.filter(
266                    unsubstitutedMemberScope.getAllDescriptors(),
267                    new Function1<DeclarationDescriptor, Boolean>() {
268                        @Override
269                        public Boolean invoke(DeclarationDescriptor descriptor) {
270                            return descriptor instanceof CallableMemberDescriptor
271                                   && ((CallableMemberDescriptor) descriptor).getKind() != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
272                        }
273                    }
274            );
275        }
276    
277        @NotNull
278        private JetScope computeScopeForPropertyInitializerResolution() {
279            ConstructorDescriptor primaryConstructor = getUnsubstitutedPrimaryConstructor();
280            if (primaryConstructor == null) return getScopeForMemberDeclarationResolution();
281    
282            WritableScopeImpl scope = new WritableScopeImpl(JetScope.EMPTY, primaryConstructor, RedeclarationHandler.DO_NOTHING, "Scope with constructor parameters in " + getName());
283            for (int i = 0; i < originalClassInfo.getPrimaryConstructorParameters().size(); i++) {
284                JetParameter jetParameter = originalClassInfo.getPrimaryConstructorParameters().get(i);
285                if (jetParameter.getValOrVarNode() == null) {
286                    scope.addVariableDescriptor(primaryConstructor.getValueParameters().get(i));
287                }
288            }
289            scope.changeLockLevel(WritableScope.LockLevel.READING);
290    
291            return new ChainedScope(
292                    primaryConstructor,
293                    "ScopeForPropertyInitializerResolution: " + getName(),
294                    scope, getScopeForMemberDeclarationResolution());
295        }
296    
297        @NotNull
298        @Override
299        public Collection<ConstructorDescriptor> getConstructors() {
300            return unsubstitutedMemberScope.getConstructors();
301        }
302    
303        @Override
304        public ConstructorDescriptor getUnsubstitutedPrimaryConstructor() {
305            return unsubstitutedMemberScope.getPrimaryConstructor();
306        }
307    
308        @NotNull
309        @Override
310        public TypeConstructor getTypeConstructor() {
311            return typeConstructor;
312        }
313    
314        @Override
315        public ClassDescriptorWithResolutionScopes getClassObjectDescriptor() {
316            return classObjectDescriptor.invoke();
317        }
318    
319        @NotNull
320        @ReadOnly
321        public List<ClassDescriptor> getDescriptorsForExtraClassObjects() {
322            return KotlinPackage.map(
323                    KotlinPackage.filter(
324                            declarationProvider.getOwnerInfo().getClassObjects(),
325                            new Function1<JetClassObject, Boolean>() {
326                                @Override
327                                public Boolean invoke(JetClassObject classObject) {
328                                    return classObject != declarationProvider.getOwnerInfo().getClassObject();
329                                }
330                            }
331                    ),
332                    new Function1<JetClassObject, ClassDescriptor>() {
333                        @Override
334                        public ClassDescriptor invoke(JetClassObject classObject) {
335                            return extraClassObjectDescriptors.invoke(classObject);
336                        }
337                    }
338            );
339        }
340    
341        @Nullable
342        private ClassDescriptorWithResolutionScopes computeClassObjectDescriptor(@Nullable JetClassObject classObject) {
343            JetClassLikeInfo classObjectInfo = getClassObjectInfo(classObject);
344            if (classObjectInfo != null) {
345                return new LazyClassDescriptor(resolveSession, this, getClassObjectName(getName()), classObjectInfo);
346            }
347            return null;
348        }
349    
350        @Nullable
351        private JetClassLikeInfo getClassObjectInfo(@Nullable JetClassObject classObject) {
352            if (classObject != null) {
353                if (getKind() != ClassKind.CLASS && getKind() != ClassKind.TRAIT && getKind() != ClassKind.ANNOTATION_CLASS || isInner()) {
354                    resolveSession.getTrace().report(CLASS_OBJECT_NOT_ALLOWED.on(classObject));
355                }
356    
357                JetObjectDeclaration objectDeclaration = classObject.getObjectDeclaration();
358                return JetClassInfoUtil.createClassLikeInfo(objectDeclaration);
359            }
360            else if (getKind() == ClassKind.OBJECT || getKind() == ClassKind.ENUM_ENTRY || getKind() == ClassKind.ENUM_CLASS) {
361                return new SyntheticClassObjectInfo(originalClassInfo, this);
362            }
363    
364            return null;
365        }
366    
367        @NotNull
368        @Override
369        public ClassKind getKind() {
370            return kind;
371        }
372    
373        @NotNull
374        @Override
375        public Modality getModality() {
376            return modality;
377        }
378    
379        @NotNull
380        @Override
381        public Visibility getVisibility() {
382            return visibility;
383        }
384    
385        @Override
386        public boolean isInner() {
387            return isInner;
388        }
389    
390        @NotNull
391        @Override
392        public Annotations getAnnotations() {
393            return annotations;
394        }
395    
396        @Override
397        public String toString() {
398            // not using descriptor render to preserve laziness
399            return "lazy class " + getName().toString();
400        }
401    
402        @Override
403        public void forceResolveAllContents() {
404            forceResolveAllContents.invoke();
405        }
406    
407        private void doForceResolveAllContents() {
408            resolveMemberHeaders();
409            ClassDescriptor classObjectDescriptor = getClassObjectDescriptor();
410            if (classObjectDescriptor != null) {
411                ForceResolveUtil.forceResolveAllContents(classObjectDescriptor);
412            }
413    
414            ForceResolveUtil.forceResolveAllContents(getConstructors());
415            ForceResolveUtil.forceResolveAllContents(getDescriptorsForExtraClassObjects());
416            ForceResolveUtil.forceResolveAllContents(getScopeForMemberLookup());
417            ForceResolveUtil.forceResolveAllContents(getTypeConstructor());
418        }
419    
420        // Note: headers of member classes' members are not resolved
421        public void resolveMemberHeaders() {
422            ForceResolveUtil.forceResolveAllContents(getAnnotations());
423    
424            getClassObjectDescriptor();
425    
426            getDescriptorsForExtraClassObjects();
427    
428            getClassObjectType();
429            getConstructors();
430            getContainingDeclaration();
431            getThisAsReceiverParameter();
432            getKind();
433            getModality();
434            getName();
435            getOriginal();
436            getScopeForClassHeaderResolution();
437            getScopeForMemberDeclarationResolution();
438            getScopeForMemberLookup().getAllDescriptors();
439            getScopeForInitializerResolution();
440            getUnsubstitutedInnerClassesScope();
441            getTypeConstructor().getSupertypes();
442            for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
443                typeParameterDescriptor.getUpperBounds();
444                typeParameterDescriptor.getLowerBounds();
445            }
446            getUnsubstitutedPrimaryConstructor();
447            getVisibility();
448        }
449    
450        private static class Supertypes {
451            @Mutable
452            public final Collection<JetType> trueSupertypes;
453            @Mutable
454            public final Collection<JetType> cyclicSupertypes;
455    
456            private Supertypes(@Mutable @NotNull Collection<JetType> trueSupertypes) {
457                this(trueSupertypes, new ArrayList<JetType>(0));
458            }
459    
460            private Supertypes(@Mutable @NotNull Collection<JetType> trueSupertypes, @Mutable @NotNull Collection<JetType> cyclicSupertypes) {
461                this.trueSupertypes = trueSupertypes;
462                this.cyclicSupertypes = cyclicSupertypes;
463            }
464    
465            @NotNull
466            public Collection<JetType> getAllSupertypes() {
467                return KotlinPackage.plus(trueSupertypes, cyclicSupertypes);
468            }
469        }
470    
471        private class LazyClassTypeConstructor implements LazyEntity, TypeConstructor {
472            private final NotNullLazyValue<Supertypes> supertypes = resolveSession.getStorageManager().createLazyValueWithPostCompute(
473                    new Function0<Supertypes>() {
474                        @Override
475                        public Supertypes invoke() {
476                            if (KotlinBuiltIns.isSpecialClassWithNoSupertypes(LazyClassDescriptor.this)) {
477                                return new Supertypes(Collections.<JetType>emptyList());
478                            }
479    
480                            JetClassLikeInfo info = declarationProvider.getOwnerInfo();
481                            if (info instanceof SyntheticClassObjectInfo) {
482                                LazyClassDescriptor descriptor = ((SyntheticClassObjectInfo) info).getClassDescriptor();
483                                if (descriptor.getKind().isSingleton()) {
484                                    return new Supertypes(Collections.singleton(descriptor.getDefaultType()));
485                                }
486                            }
487    
488                            JetClassOrObject classOrObject = info.getCorrespondingClassOrObject();
489                            if (classOrObject == null) {
490                                return new Supertypes(Collections.singleton(KotlinBuiltIns.getInstance().getAnyType()));
491                            }
492    
493                            List<JetType> allSupertypes = resolveSession.getDescriptorResolver()
494                                    .resolveSupertypes(getScopeForClassHeaderResolution(), LazyClassDescriptor.this, classOrObject,
495                                                       resolveSession.getTrace());
496    
497                            return new Supertypes(Lists.newArrayList(Collections2.filter(allSupertypes, VALID_SUPERTYPE)));
498                        }
499                    },
500                    new Function1<Boolean, Supertypes>() {
501                        @Override
502                        public Supertypes invoke(Boolean firstTime) {
503                            return new Supertypes(Collections.<JetType>emptyList());
504                        }
505                    },
506                    new Function1<Supertypes, Unit>() {
507                        @Override
508                        public Unit invoke(@NotNull Supertypes supertypes) {
509                            findAndDisconnectLoopsInTypeHierarchy(supertypes);
510                            return Unit.VALUE;
511                        }
512                    }
513            );
514    
515            private final NotNullLazyValue<List<TypeParameterDescriptor>> parameters = resolveSession.getStorageManager().createLazyValue(new Function0<List<TypeParameterDescriptor>>() {
516                @Override
517                public List<TypeParameterDescriptor> invoke() {
518                    JetClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
519                    List<JetTypeParameter> typeParameters = classInfo.getTypeParameters();
520    
521                    List<TypeParameterDescriptor> parameters = new ArrayList<TypeParameterDescriptor>(typeParameters.size());
522                    for (int i = 0; i < typeParameters.size(); i++) {
523                        parameters.add(new LazyTypeParameterDescriptor(resolveSession, LazyClassDescriptor.this, typeParameters.get(i), i));
524                    }
525    
526                    return parameters;
527                }
528            });
529    
530            private final NullableLazyValue<Void> forceResolveAllContents =
531                    resolveSession.getStorageManager().createRecursionTolerantNullableLazyValue(new Function0<Void>() {
532                        @Override
533                        public Void invoke() {
534                            doForceResolveAllContents();
535                            return null;
536                        }
537                    }, null);
538    
539            @NotNull
540            @Override
541            public List<TypeParameterDescriptor> getParameters() {
542                return parameters.invoke();
543            }
544    
545            @NotNull
546            @Override
547            public Collection<JetType> getSupertypes() {
548                return supertypes.invoke().trueSupertypes;
549            }
550    
551            private void findAndDisconnectLoopsInTypeHierarchy(Supertypes supertypes) {
552                for (Iterator<JetType> iterator = supertypes.trueSupertypes.iterator(); iterator.hasNext(); ) {
553                    JetType supertype = iterator.next();
554                    if (isReachable(supertype.getConstructor(), this, new HashSet<TypeConstructor>())) {
555                        iterator.remove();
556                        supertypes.cyclicSupertypes.add(supertype);
557    
558                        ClassifierDescriptor supertypeDescriptor = supertype.getConstructor().getDeclarationDescriptor();
559                        if (supertypeDescriptor instanceof ClassDescriptor) {
560                            ClassDescriptor superclass = (ClassDescriptor) supertypeDescriptor;
561                            TypeHierarchyResolver.reportCyclicInheritanceHierarchyError(resolveSession.getTrace(), LazyClassDescriptor.this,
562                                                                                        superclass);
563                        }
564                    }
565                }
566            }
567    
568            private boolean isReachable(TypeConstructor from, TypeConstructor to, Set<TypeConstructor> visited) {
569                if (!visited.add(from)) return false;
570                for (JetType supertype : getNeighbors(from)) {
571                    TypeConstructor supertypeConstructor = supertype.getConstructor();
572                    if (supertypeConstructor == to) {
573                        return true;
574                    }
575                    if (isReachable(supertypeConstructor, to, visited)) {
576                        return true;
577                    }
578                }
579                return false;
580            }
581    
582            private Collection<JetType> getNeighbors(TypeConstructor from) {
583                // Supertypes + type for container
584                Collection<JetType> neighbours = new ArrayList<JetType>(
585                        from instanceof LazyClassTypeConstructor
586                                 ? ((LazyClassTypeConstructor) from).supertypes.invoke().getAllSupertypes()
587                                 : from.getSupertypes()
588                );
589    
590                ClassifierDescriptor fromDescriptor = from.getDeclarationDescriptor();
591                if (fromDescriptor != null) {
592                    DeclarationDescriptor container = fromDescriptor.getContainingDeclaration();
593                    if (container instanceof ClassDescriptor) {
594                        neighbours.add(((ClassDescriptor) container).getDefaultType());
595                    }
596                }
597                return neighbours;
598            }
599    
600            @Override
601            public boolean isFinal() {
602                return !getModality().isOverridable();
603            }
604    
605            @Override
606            public boolean isDenotable() {
607                return true;
608            }
609    
610            @Override
611            public ClassifierDescriptor getDeclarationDescriptor() {
612                return LazyClassDescriptor.this;
613            }
614    
615            @NotNull
616            @Override
617            public Annotations getAnnotations() {
618                return Annotations.EMPTY; // TODO
619            }
620    
621            @Override
622            public String toString() {
623                return LazyClassDescriptor.this.getName().toString();
624            }
625    
626            @Override
627            public void forceResolveAllContents() {
628                forceResolveAllContents.invoke();
629            }
630    
631            private void doForceResolveAllContents() {
632                ForceResolveUtil.forceResolveAllContents(getAnnotations());
633                ForceResolveUtil.forceResolveAllContents(getSupertypes());
634                ForceResolveUtil.forceResolveAllContents(getParameters());
635            }
636        }
637    
638        @NotNull
639        private ScopeProvider getScopeProvider() {
640            return resolveSession.getScopeProvider();
641        }
642    }