@NotNull
    private MutableClassDescriptor createClassDescriptorForClass(
        @NotNull JetClass klass, @NotNull DeclarationDescriptor containingDeclaration) {
      ClassKind kind = getClassKind(klass);
      // Kind check is needed in order to not consider enums as inner in any case
      // (otherwise it would be impossible to create a class object in the enum)
      boolean isInner = kind == ClassKind.CLASS && klass.isInner();
      MutableClassDescriptor mutableClassDescriptor =
          new MutableClassDescriptor(
              containingDeclaration,
              outerScope,
              kind,
              isInner,
              JetPsiUtil.safeName(klass.getName()));
      c.getClasses().put(klass, mutableClassDescriptor);
      trace.record(
          FQNAME_TO_CLASS_DESCRIPTOR, JetPsiUtil.getUnsafeFQName(klass), mutableClassDescriptor);

      createClassObjectForEnumClass(mutableClassDescriptor);

      JetScope classScope = mutableClassDescriptor.getScopeForMemberDeclarationResolution();

      prepareForDeferredCall(classScope, mutableClassDescriptor, klass);

      return mutableClassDescriptor;
    }
 private List<MutableClassDescriptorLite> topologicallySortClassesAndObjects(
     @NotNull TopDownAnalysisContext c) {
   // A topsort is needed only for better diagnostics:
   //    edges that get removed to disconnect loops are more reasonable in this case
   //noinspection unchecked
   return DFS.topologicalOrder(
       (Iterable) c.getClasses().values(),
       new DFS.Neighbors<MutableClassDescriptorLite>() {
         @NotNull
         @Override
         public Iterable<MutableClassDescriptorLite> getNeighbors(
             MutableClassDescriptorLite current) {
           List<MutableClassDescriptorLite> result = Lists.newArrayList();
           for (JetType supertype : current.getSupertypes()) {
             DeclarationDescriptor declarationDescriptor =
                 supertype.getConstructor().getDeclarationDescriptor();
             if (declarationDescriptor instanceof MutableClassDescriptorLite) {
               MutableClassDescriptorLite classDescriptor =
                   (MutableClassDescriptorLite) declarationDescriptor;
               result.add(classDescriptor);
             }
           }
           return result;
         }
       });
 }
  private void resolveTypesInClassHeaders(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getClasses().entrySet()) {
      JetClassOrObject classOrObject = entry.getKey();
      if (classOrObject instanceof JetClass) {
        ClassDescriptorWithResolutionScopes descriptor = entry.getValue();
        //noinspection unchecked
        descriptorResolver.resolveGenericBounds(
            (JetClass) classOrObject,
            descriptor,
            descriptor.getScopeForClassHeaderResolution(),
            (List) descriptor.getTypeConstructor().getParameters(),
            trace);
      }
    }

    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getClasses().entrySet()) {
      descriptorResolver.resolveSupertypesForMutableClassDescriptor(
          entry.getKey(), (MutableClassDescriptor) entry.getValue(), trace);
    }
  }
    @NotNull
    private MutableClassDescriptor createClassDescriptorForSingleton(
        @NotNull JetClassOrObject declaration, @NotNull Name name, @NotNull ClassKind kind) {
      MutableClassDescriptor descriptor =
          new MutableClassDescriptor(owner.getOwnerForChildren(), outerScope, kind, false, name);

      prepareForDeferredCall(
          descriptor.getScopeForMemberDeclarationResolution(), descriptor, declaration);

      createPrimaryConstructorForObject(declaration, descriptor);
      trace.record(BindingContext.CLASS, declaration, descriptor);

      c.getClasses().put(declaration, descriptor);

      return descriptor;
    }
  private void createTypeConstructors(@NotNull TopDownAnalysisContext c) {
    for (Map.Entry<JetClassOrObject, ClassDescriptorWithResolutionScopes> entry :
        c.getClasses().entrySet()) {
      JetClassOrObject classOrObject = entry.getKey();
      MutableClassDescriptor descriptor = (MutableClassDescriptor) entry.getValue();
      if (classOrObject instanceof JetClass) {
        descriptorResolver.resolveMutableClassDescriptor(
            (JetClass) classOrObject, descriptor, trace);
      } else if (classOrObject instanceof JetObjectDeclaration) {
        descriptor.setModality(Modality.FINAL);
        descriptor.setVisibility(
            resolveVisibilityFromModifiers(classOrObject, getDefaultClassVisibility(descriptor)));
        descriptor.setTypeParameterDescriptors(Collections.<TypeParameterDescriptor>emptyList());
      }

      descriptor.createTypeConstructor();

      ClassKind kind = descriptor.getKind();
      if (kind == ClassKind.ENUM_ENTRY
          || kind == ClassKind.OBJECT
          || kind == ClassKind.ENUM_CLASS) {
        MutableClassDescriptorLite classObject = descriptor.getClassObjectDescriptor();
        assert classObject != null
            : "Enum entries and named objects should have class objects: "
                + classOrObject.getText();

        JetType supertype;
        if (kind == ClassKind.ENUM_CLASS) {
          supertype = KotlinBuiltIns.getInstance().getAnyType();
        } else {
          // This is a clever hack: each enum entry and object declaration (i.e. singleton) has a
          // synthetic class object.
          // We make this class object inherit from the singleton here, thus allowing to use the
          // singleton's class object where
          // the instance of the singleton is applicable. Effectively all members of the singleton
          // would be present in its class
          // object as fake overrides, so you can access them via standard class object notation:
          // ObjectName.memberName()
          supertype = descriptor.getDefaultType();
        }
        classObject.setSupertypes(Collections.singleton(supertype));
        classObject.createTypeConstructor();
      }
    }
  }