@Override
  protected synchronized void initialize() {
    setDefaultConstructor(null);

    UClass uClass = getUastElement();
    LOG.assertTrue(uClass != null);

    UDeclaration parent = UDeclarationKt.getContainingDeclaration(uClass);
    while (parent != null) {
      if (parent instanceof UMethod || parent instanceof UClass || parent instanceof UField) {
        break;
      }
      parent = UDeclarationKt.getContainingDeclaration(parent);
    }
    final RefManagerImpl manager = getRefManager();
    boolean utilityClass = true;
    final UClass[] innerClasses = uClass.getInnerClasses();
    for (UClass innerClass : innerClasses) {
      final PsiElement psi = innerClass.getSourcePsi();
      if (psi != null) {
        final RefElement refInnerClass = manager.getReference(psi);
        if (refInnerClass !=  null) {
          addChild(refInnerClass);
          if (!innerClass.isStatic()) utilityClass = false;
        }
      }
    }
    RefElement refParent = parent != null ? manager.getReference(parent.getSourcePsi()) : null;
    if (refParent != null) {
      setOwner((WritableRefEntity)refParent);
    }
    else {
      PsiFile containingFile = getContainingFile();
      if (isSyntheticJSP()) {
        final PsiFile psiFile = PsiUtilCore.getTemplateLanguageFile(getPsiElement());
        final RefFileImpl refFile = (RefFileImpl)manager.getReference(psiFile);
        LOG.assertTrue(refFile != null);
        refFile.add(this);
      }
      else if (isKindOfJvmLanguage(containingFile.getLanguage())) {
        String packageName = UastContextKt.toUElement(containingFile, UFile.class).getPackageName();
        if (!packageName.isEmpty()) {
          ((RefPackageImpl)getRefJavaManager().getPackage(packageName)).add(this);
        }
        else {
          ((RefPackageImpl)getRefJavaManager().getDefaultPackage()).add(this);
        }
      }
      else {
        ((WritableRefEntity)myRefModule).add(this);
      }
    }

    if (!myManager.isDeclarationsFound()) return;

    setInterface(uClass.isInterface());
    setAnnotationType(uClass.isAnnotationType());
    setAnonymous(uClass instanceof UAnonymousClass);
    final PsiClass psiClass = uClass.getJavaPsi();
    if (!isAnonymous()) {
      setRecord(psiClass.isRecord());
      setEnum(psiClass.isEnum());
      setAbstract(psiClass.hasModifier(JvmModifier.ABSTRACT));
      setLocal(parent != null && !(parent instanceof UClass));
    }

    initializeSuperReferences(uClass);

    UMethod[] uMethods = uClass.getMethods();
    UField[] uFields = uClass.getFields();

    boolean memberSeen = false;
    for (UField uField : uFields) {
      final RefField field = ObjectUtils.tryCast(manager.getReference(uField.getSourcePsi()), RefField.class);
      if (field != null) {
        memberSeen = true;
        addChild(field);
        if (!uField.isStatic() || uField instanceof UEnumConstant) utilityClass = false;
      }
    }
    RefMethodImpl varargConstructor = null;
    boolean constructorSeen = false;
    for (UMethod uMethod : uMethods) {
      RefMethodImpl refMethod = ObjectUtils.tryCast(manager.getReference(uMethod.getSourcePsi()), RefMethodImpl.class);

      if (refMethod != null) {
        addChild(refMethod);
        if (uMethod.isConstructor()) {
          constructorSeen = true;
          final List<UParameter> parameters = uMethod.getUastParameters();
          if (!parameters.isEmpty() || uMethod.getVisibility() != UastVisibility.PRIVATE) {
            utilityClass = false;
          }

          if (parameters.isEmpty()) {
            setDefaultConstructor(refMethod);
          }
          else if (parameters.size() == 1) {
            PsiElement parameterPsi = parameters.get(0).getJavaPsi();
            if (parameterPsi instanceof PsiParameter && ((PsiParameter)parameterPsi).isVarArgs()) {
              varargConstructor = refMethod;
            }
          }
        }
        else {
          memberSeen = true;
          if (!uMethod.isStatic()) utilityClass = false;
        }
      }
    }

    if (!memberSeen || isInterface() || isRecord() || isAnonymous()) {
      utilityClass = false;
    }
    if (!utilityClass && psiClass.getLanguage().isKindOf("kotlin")) {
      // Kotlin companion object is singleton
      utilityClass = ClassUtils.isSingleton(psiClass);
    }

    if (myDefaultConstructor == null && varargConstructor != null) {
      setDefaultConstructor(varargConstructor);
    }
    if (!constructorSeen && !isInterface() && !isAnonymous()) {
      // implicit constructor is generated by javac when the class has no other constructor
      setDefaultConstructor(new RefImplicitConstructorImpl(this));
    }

    setUtilityClass(utilityClass);

    if (!utilityClass) {
      setApplet(getRefJavaManager().getApplet() != null && JvmInheritanceUtil.isInheritor(uClass, getRefJavaManager().getAppletQName()));
      if (!isApplet()) {
        setServlet(JvmInheritanceUtil.isInheritor(psiClass, getRefJavaManager().getServletQName()));
      }
      if (!isApplet() && !isServlet()) {
        PsiElement psi = uClass.getSourcePsi();
        if (psi instanceof PsiClass) {
          final boolean isTestClass = TestFrameworks.getInstance().isTestClass((PsiClass)psi);
          setTestCase(isTestClass);
          if (isTestClass) {
            for (RefClass refBase : getBaseClasses()) {
              ((RefClassImpl)refBase).setTestCase(true);
            }
          }
        }
      }
    }
  }
@Override
  protected synchronized void initialize()