public String getDisplayName() {
      String constructorName = type.getDisplayInnerTypeName();
      boolean isInnerClass = (constructorName != null);

      if (constructorName == null) constructorName = type.getDisplayTypeName();

      StringBuffer sb = new StringBuffer();
      writeMethodSignature(sb, access, access, isInnerClass, constructorName, name, descriptor);
      return sb.toString();
    }
    public void enterConstructorDeclaration(JavaParser.ConstructorDeclarationContext ctx) {
      int access = getClassBodyDeclarationAccessFlag(ctx.getParent().getParent());
      String paramDescriptors =
          createParamDescriptors(ctx.formalParameters().formalParameterList());
      String descriptor = paramDescriptors + "V";

      currentType.getMethods().add(new JavaMethod(currentType, access, "<init>", descriptor));
    }
    public void enterClassBodyDeclaration(JavaParser.ClassBodyDeclarationContext ctx) {
      if (ctx.getChildCount() == 2) {
        ParseTree first = ctx.getChild(0);

        if (first instanceof TerminalNode) {
          if (((TerminalNode) first).getSymbol().getType() == JavaParser.STATIC) {
            currentType
                .getMethods()
                .add(new JavaMethod(currentType, JavaType.FLAG_STATIC, "<clinit>", "()V"));
          }
        }
      }
    }
    public void enterMethodDeclaration(
        ParserRuleContext ctx,
        TerminalNode identifier,
        JavaParser.FormalParametersContext formalParameters,
        JavaParser.TypeContext returnType) {

      int access = getClassBodyDeclarationAccessFlag(ctx.getParent().getParent());
      String name = identifier.getText();
      String paramDescriptors = createParamDescriptors(formalParameters.formalParameterList());
      String returnDescriptor = createDescriptor(returnType, 0);
      String descriptor = paramDescriptors + returnDescriptor;

      currentType.getMethods().add(new JavaMethod(currentType, access, name, descriptor));
    }
    public void enterConstDeclaration(JavaParser.ConstDeclarationContext ctx) {
      JavaParser.TypeContext typeContext = ctx.type();
      int access = getClassBodyDeclarationAccessFlag(ctx.getParent().getParent());

      for (JavaParser.ConstantDeclaratorContext constantDeclaratorContext :
          ctx.constantDeclarator()) {
        TerminalNode identifier = constantDeclaratorContext.Identifier();
        String name = identifier.getText();
        int dimensionOnVariable = countDimension(constantDeclaratorContext.children);
        String descriptor = createDescriptor(typeContext, dimensionOnVariable);

        currentType.getFields().add(new JavaField(access, name, descriptor));
      }
    }
 protected void exitTypeDeclaration() {
   currentType = currentType.getOuterType();
 }
    protected void enterTypeDeclaration(ParserRuleContext ctx, int access) {
      String name = ctx.getToken(JavaParser.Identifier, 0).getText();

      JavaParser.TypeContext superType = ctx.getRuleContext(JavaParser.TypeContext.class, 0);
      String superQualifiedTypeName;

      if (superType == null) {
        superQualifiedTypeName =
            ((access & JavaType.FLAG_INTERFACE) == 0) ? "java/lang/Object" : "";
      } else {
        superQualifiedTypeName =
            resolveInternalTypeName(superType.classOrInterfaceType().Identifier());
      }

      ParserRuleContext parent = ctx.getParent();

      if (parent instanceof JavaParser.TypeDeclarationContext)
        access += getTypeDeclarationContextAccessFlag(parent);
      else if (parent instanceof JavaParser.MemberDeclarationContext)
        access += getMemberDeclarationContextAccessFlag(parent.getParent());

      if (currentType == null) {
        String internalTypeName = packageName.isEmpty() ? name : packageName + "/" + name;
        String outerName = null;
        String displayTypeName = name;
        String displayInnerTypeName = null;

        currentType =
            new JavaType(
                access,
                internalTypeName,
                superQualifiedTypeName,
                outerName,
                displayTypeName,
                displayInnerTypeName,
                displayPackageName,
                null);
        types.put(internalTypeName, currentType);
        rootTypes.add(currentType);
        nameToInternalTypeName.put(name, internalTypeName);

        if (mainType == null) {
          mainType = currentType;
        } else {
          // Multi class definitions in the same file
          String path = entry.getPath();
          int index = path.lastIndexOf('/') + 1;

          if (path.substring(index).startsWith(name + '.')) {
            // Select the correct root type
            mainType = currentType;
          }
        }
      } else {
        String internalTypeName = currentType.getName() + '$' + name;
        String outerName = currentType.getName();
        String displayTypeName = currentType.getDisplayTypeName() + '.' + name;
        String displayInnerTypeName = name;
        JavaType subType =
            new JavaType(
                access,
                internalTypeName,
                superQualifiedTypeName,
                outerName,
                displayTypeName,
                displayInnerTypeName,
                displayPackageName,
                currentType);

        currentType.getInnerTypes().add(subType);
        currentType = subType;
        types.put(internalTypeName, currentType);
        nameToInternalTypeName.put(name, internalTypeName);
      }
    }