@Override
    public void visitLocalVariable(
        String name, String desc, String signature, Label start, Label end, int index) {
      if (index >= myIgnoreCount) {
        // long and double variables increase the index by 2, not by 1
        int paramIndex =
            (index - myIgnoreCount == myUsedParamSize) ? myUsedParamCount : index - myIgnoreCount;
        if (paramIndex >= myParamCount) return;

        if (ClsParsingUtil.isJavaIdentifier(name, LanguageLevel.HIGHEST)) {
          PsiParameterStubImpl parameterStub = myParamStubs[paramIndex];
          if (parameterStub != null) {
            parameterStub.setName(name);
          }
        }

        myUsedParamCount = paramIndex + 1;
        if ("D".equals(desc) || "J".equals(desc)) {
          myUsedParamSize += 2;
        } else {
          myUsedParamSize++;
        }
      }
    }
  @Override
  public void visit(
      int version,
      int access,
      String name,
      String signature,
      String superName,
      String[] interfaces) {
    String fqn = getFqn(name, myShortName);
    String shortName =
        myShortName != null && name.endsWith(myShortName)
            ? myShortName
            : PsiNameHelper.getShortClassName(fqn);

    int flags = myAccess | access;
    boolean isDeprecated = (flags & Opcodes.ACC_DEPRECATED) != 0;
    boolean isInterface = (flags & Opcodes.ACC_INTERFACE) != 0;
    boolean isEnum = (flags & Opcodes.ACC_ENUM) != 0;
    boolean isAnnotationType = (flags & Opcodes.ACC_ANNOTATION) != 0;

    byte stubFlags =
        PsiClassStubImpl.packFlags(
            isDeprecated, isInterface, isEnum, false, false, isAnnotationType, false, false);
    myResult =
        new PsiClassStubImpl(JavaStubElementTypes.CLASS, myParent, fqn, shortName, null, stubFlags);

    LanguageLevel languageLevel = ClsParsingUtil.getLanguageLevelByVersion(version);
    if (languageLevel == null) languageLevel = LanguageLevel.HIGHEST;
    ((PsiClassStubImpl) myResult).setLanguageLevel(languageLevel);

    myModList = new PsiModifierListStubImpl(myResult, packClassFlags(flags));

    CharacterIterator signatureIterator =
        signature != null ? new StringCharacterIterator(signature) : null;
    if (signatureIterator != null) {
      try {
        SignatureParsing.parseTypeParametersDeclaration(signatureIterator, myResult);
      } catch (ClsFormatException e) {
        signatureIterator = null;
      }
    } else {
      new PsiTypeParameterListStubImpl(myResult);
    }

    String convertedSuper;
    List<String> convertedInterfaces = new ArrayList<String>();
    if (signatureIterator == null) {
      convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces);
    } else {
      try {
        convertedSuper = parseClassSignature(signatureIterator, convertedInterfaces);
      } catch (ClsFormatException e) {
        new PsiTypeParameterListStubImpl(myResult);
        convertedSuper = parseClassDescription(superName, interfaces, convertedInterfaces);
      }
    }

    if (isInterface) {
      if (isAnnotationType) {
        convertedInterfaces.remove(JAVA_LANG_ANNOTATION_ANNOTATION);
      }
      newReferenceList(
          JavaStubElementTypes.EXTENDS_LIST,
          myResult,
          ArrayUtil.toStringArray(convertedInterfaces));
      newReferenceList(JavaStubElementTypes.IMPLEMENTS_LIST, myResult);
    } else {
      if (convertedSuper == null
          || JAVA_LANG_OBJECT.equals(convertedSuper)
          || isEnum
              && (JAVA_LANG_ENUM.equals(convertedSuper)
                  || (JAVA_LANG_ENUM + "<" + fqn + ">").equals(convertedSuper))) {
        newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult);
      } else {
        newReferenceList(JavaStubElementTypes.EXTENDS_LIST, myResult, convertedSuper);
      }
      newReferenceList(
          JavaStubElementTypes.IMPLEMENTS_LIST,
          myResult,
          ArrayUtil.toStringArray(convertedInterfaces));
    }
  }