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