// Note: headers of member classes' members are not resolved
  public void resolveMemberHeaders() {
    ForceResolveUtil.forceResolveAllContents(getAnnotations());
    ForceResolveUtil.forceResolveAllContents(getDanglingAnnotations());

    getCompanionObjectDescriptor();

    getDescriptorsForExtraCompanionObjects();

    getConstructors();
    getContainingDeclaration();
    getThisAsReceiverParameter();
    getKind();
    getModality();
    getName();
    getOriginal();
    getScopeForClassHeaderResolution();
    getScopeForMemberDeclarationResolution();
    DescriptorUtils.getAllDescriptors(getUnsubstitutedMemberScope());
    getScopeForInitializerResolution();
    getUnsubstitutedInnerClassesScope();
    getTypeConstructor().getSupertypes();
    for (TypeParameterDescriptor typeParameterDescriptor : getTypeConstructor().getParameters()) {
      typeParameterDescriptor.getUpperBounds();
    }
    getUnsubstitutedPrimaryConstructor();
    getVisibility();
  }
 @NotNull
 @Override
 public Collection<CallableMemberDescriptor> getDeclaredCallableMembers() {
   //noinspection unchecked
   return (Collection)
       CollectionsKt.filter(
           DescriptorUtils.getAllDescriptors(unsubstitutedMemberScope),
           new Function1<DeclarationDescriptor, Boolean>() {
             @Override
             public Boolean invoke(DeclarationDescriptor descriptor) {
               return descriptor instanceof CallableMemberDescriptor
                   && ((CallableMemberDescriptor) descriptor).getKind()
                       != CallableMemberDescriptor.Kind.FAKE_OVERRIDE;
             }
           });
 }
 @Nullable
 private LazyClassDescriptor computeCompanionObjectDescriptor(
     @Nullable KtObjectDeclaration companionObject) {
   KtClassLikeInfo companionObjectInfo = getCompanionObjectInfo(companionObject);
   if (!(companionObjectInfo instanceof KtClassOrObjectInfo)) {
     return null;
   }
   Name name = ((KtClassOrObjectInfo) companionObjectInfo).getName();
   assert name != null;
   getUnsubstitutedMemberScope()
       .getContributedClassifier(name, NoLookupLocation.WHEN_GET_COMPANION_OBJECT);
   ClassDescriptor companionObjectDescriptor =
       c.getTrace().get(BindingContext.CLASS, companionObject);
   if (companionObjectDescriptor instanceof LazyClassDescriptor) {
     assert DescriptorUtils.isCompanionObject(companionObjectDescriptor)
         : "Not a companion object: " + companionObjectDescriptor;
     return (LazyClassDescriptor) companionObjectDescriptor;
   } else {
     return null;
   }
 }
 private boolean isCompanionObjectAllowed() {
   return !(getKind().isSingleton() || isInner() || DescriptorUtils.isLocal(this));
 }
  public LazyClassDescriptor(
      @NotNull final LazyClassContext c,
      @NotNull DeclarationDescriptor containingDeclaration,
      @NotNull Name name,
      @NotNull final KtClassLikeInfo classLikeInfo) {
    super(
        c.getStorageManager(),
        containingDeclaration,
        name,
        KotlinSourceElementKt.toSourceElement(classLikeInfo.getCorrespondingClassOrObject()));
    this.c = c;

    KtClassOrObject classOrObject = classLikeInfo.getCorrespondingClassOrObject();
    if (classOrObject != null) {
      this.c.getTrace().record(BindingContext.CLASS, classOrObject, this);
    }
    this.c
        .getTrace()
        .record(BindingContext.FQNAME_TO_CLASS_DESCRIPTOR, DescriptorUtils.getFqName(this), this);

    this.declarationProvider =
        c.getDeclarationProviderFactory().getClassMemberDeclarationProvider(classLikeInfo);

    StorageManager storageManager = c.getStorageManager();

    this.unsubstitutedMemberScope = createMemberScope(c, this.declarationProvider);
    this.kind = classLikeInfo.getClassKind();
    this.staticScope =
        kind == ClassKind.ENUM_CLASS
            ? new StaticScopeForKotlinEnum(storageManager, this)
            : MemberScope.Empty.INSTANCE;

    this.typeConstructor = new LazyClassTypeConstructor();

    this.isCompanionObject =
        classLikeInfo instanceof KtObjectInfo && ((KtObjectInfo) classLikeInfo).isCompanionObject();

    KtModifierList modifierList = classLikeInfo.getModifierList();
    if (kind.isSingleton()) {
      this.modality = Modality.FINAL;
    } else {
      Modality defaultModality = kind == ClassKind.INTERFACE ? Modality.ABSTRACT : Modality.FINAL;
      this.modality =
          resolveModalityFromModifiers(modifierList, defaultModality, /* allowSealed = */ true);
    }

    boolean isLocal = classOrObject != null && KtPsiUtil.isLocal(classOrObject);
    Visibility defaultVisibility;
    if (kind == ClassKind.ENUM_ENTRY || (kind == ClassKind.OBJECT && isCompanionObject)) {
      defaultVisibility = Visibilities.PUBLIC;
    } else {
      defaultVisibility = Visibilities.DEFAULT_VISIBILITY;
    }
    this.visibility =
        isLocal
            ? Visibilities.LOCAL
            : resolveVisibilityFromModifiers(modifierList, defaultVisibility);

    this.isInner = isInnerClass(modifierList) && !ModifiersChecker.isIllegalInner(this);
    this.isData = modifierList != null && modifierList.hasModifier(KtTokens.DATA_KEYWORD);

    // Annotation entries are taken from both own annotations (if any) and object literal
    // annotations (if any)
    List<KtAnnotationEntry> annotationEntries = new ArrayList<KtAnnotationEntry>();
    if (classOrObject != null && classOrObject.getParent() instanceof KtObjectLiteralExpression) {
      // TODO: it would be better to have separate ObjectLiteralDescriptor without so much magic
      annotationEntries.addAll(
          KtPsiUtilKt.getAnnotationEntries((KtObjectLiteralExpression) classOrObject.getParent()));
    }
    if (modifierList != null) {
      annotationEntries.addAll(modifierList.getAnnotationEntries());
    }
    if (!annotationEntries.isEmpty()) {
      this.annotations =
          new LazyAnnotations(
              new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) {
                @NotNull
                @Override
                public LexicalScope getScope() {
                  return getOuterScope();
                }
              },
              annotationEntries);
    } else {
      this.annotations = Annotations.Companion.getEMPTY();
    }

    List<KtAnnotationEntry> jetDanglingAnnotations = classLikeInfo.getDanglingAnnotations();
    if (jetDanglingAnnotations.isEmpty()) {
      this.danglingAnnotations = Annotations.Companion.getEMPTY();
    } else {
      this.danglingAnnotations =
          new LazyAnnotations(
              new LazyAnnotationsContext(c.getAnnotationResolver(), storageManager, c.getTrace()) {
                @NotNull
                @Override
                public LexicalScope getScope() {
                  return getScopeForMemberDeclarationResolution();
                }
              },
              jetDanglingAnnotations);
    }

    this.companionObjectDescriptor =
        storageManager.createNullableLazyValue(
            new Function0<LazyClassDescriptor>() {
              @Override
              public LazyClassDescriptor invoke() {
                return computeCompanionObjectDescriptor(getCompanionObjectIfAllowed());
              }
            });
    this.extraCompanionObjectDescriptors =
        storageManager.createMemoizedFunction(
            new Function1<KtObjectDeclaration, ClassDescriptor>() {
              @Override
              public ClassDescriptor invoke(KtObjectDeclaration companionObject) {
                return computeCompanionObjectDescriptor(companionObject);
              }
            });
    this.forceResolveAllContents =
        storageManager.createRecursionTolerantNullableLazyValue(
            new Function0<Void>() {
              @Override
              public Void invoke() {
                doForceResolveAllContents();
                return null;
              }
            },
            null);

    this.resolutionScopesSupport =
        new ClassResolutionScopesSupport(
            this,
            storageManager,
            new Function0<LexicalScope>() {
              @Override
              public LexicalScope invoke() {
                return getOuterScope();
              }
            });

    this.parameters =
        c.getStorageManager()
            .createLazyValue(
                new Function0<List<TypeParameterDescriptor>>() {
                  @Override
                  public List<TypeParameterDescriptor> invoke() {
                    KtClassLikeInfo classInfo = declarationProvider.getOwnerInfo();
                    KtTypeParameterList typeParameterList = classInfo.getTypeParameterList();
                    if (typeParameterList == null) return Collections.emptyList();

                    if (classInfo.getClassKind() == ClassKind.ENUM_CLASS) {
                      c.getTrace().report(TYPE_PARAMETERS_IN_ENUM.on(typeParameterList));
                    }

                    List<KtTypeParameter> typeParameters = typeParameterList.getParameters();
                    if (typeParameters.isEmpty()) return Collections.emptyList();

                    List<TypeParameterDescriptor> parameters =
                        new ArrayList<TypeParameterDescriptor>(typeParameters.size());

                    for (int i = 0; i < typeParameters.size(); i++) {
                      parameters.add(
                          new LazyTypeParameterDescriptor(
                              c, LazyClassDescriptor.this, typeParameters.get(i), i));
                    }

                    return parameters;
                  }
                });

    this.scopeForInitializerResolution =
        storageManager.createLazyValue(
            new Function0<LexicalScope>() {
              @Override
              public LexicalScope invoke() {
                return ClassResolutionScopesSupportKt.scopeForInitializerResolution(
                    LazyClassDescriptor.this,
                    createInitializerScopeParent(),
                    classLikeInfo.getPrimaryConstructorParameters());
              }
            });
  }