jodd-proxetta/src/main/java/jodd/asm7/signature/SignatureReader.java
private static int parseType(
      final String signature, final int startOffset, final SignatureVisitor signatureVisitor) {
    int offset = startOffset; // Current offset in the parsed signature.
    char currentChar = signature.charAt(offset++); // The signature character at 'offset'.

    // Switch based on the first character of the JavaTypeSignature, which indicates its kind.
    switch (currentChar) {
      case 'Z':
      case 'C':
      case 'B':
      case 'S':
      case 'I':
      case 'F':
      case 'J':
      case 'D':
      case 'V':
        // Case of a BaseType or a VoidDescriptor.
        signatureVisitor.visitBaseType(currentChar);
        return offset;

      case '[':
        // Case of an ArrayTypeSignature, a '[' followed by a JavaTypeSignature.
        return parseType(signature, offset, signatureVisitor.visitArrayType());

      case 'T':
        // Case of TypeVariableSignature, an identifier between 'T' and ';'.
        int endOffset = signature.indexOf(';', offset);
        signatureVisitor.visitTypeVariable(signature.substring(offset, endOffset));
        return endOffset + 1;

      case 'L':
        // Case of a ClassTypeSignature, which ends with ';'.
        // These signatures have a main class type followed by zero or more inner class types
        // (separated by '.'). Each can have type arguments, inside '<' and '>'.
        int start = offset; // The start offset of the currently parsed main or inner class name.
        boolean visited = false; // Whether the currently parsed class name has been visited.
        boolean inner = false; // Whether we are currently parsing an inner class type.
        // Parses the signature, one character at a time.
        while (true) {
          currentChar = signature.charAt(offset++);
          if (currentChar == '.' || currentChar == ';') {
            // If a '.' or ';' is encountered, this means we have fully parsed the main class name
            // or an inner class name. This name may already have been visited it is was followed by
            // type arguments between '<' and '>'. If not, we need to visit it here.
            if (!visited) {
              String name = signature.substring(start, offset - 1);
              if (inner) {
                signatureVisitor.visitInnerClassType(name);
              } else {
                signatureVisitor.visitClassType(name);
              }
            }
            // If we reached the end of the ClassTypeSignature return, otherwise start the parsing
            // of a new class name, which is necessarily an inner class name.
            if (currentChar == ';') {
              signatureVisitor.visitEnd();
              break;
            }
            start = offset;
            visited = false;
            inner = true;
          } else if (currentChar == '<') {
            // If a '<' is encountered, this means we have fully parsed the main class name or an
            // inner class name, and that we now need to parse TypeArguments. First, we need to
            // visit the parsed class name.
            String name = signature.substring(start, offset - 1);
            if (inner) {
              signatureVisitor.visitInnerClassType(name);
            } else {
              signatureVisitor.visitClassType(name);
            }
            visited = true;
            // Now, parse the TypeArgument(s), one at a time.
            while ((currentChar = signature.charAt(offset)) != '>') {
              switch (currentChar) {
                case '*':
                  // Unbounded TypeArgument.
                  ++offset;
                  signatureVisitor.visitTypeArgument();
                  break;
                case '+':
                case '-':
                  // Extends or Super TypeArgument. Use offset + 1 to skip the '+' or '-'.
                  offset =
                      parseType(
                          signature, offset + 1, signatureVisitor.visitTypeArgument(currentChar));
                  break;
                default:
                  // Instanceof TypeArgument. The '=' is implicit.
                  offset = parseType(signature, offset, signatureVisitor.visitTypeArgument('='));
                  break;
              }
            }
          }
        }
        return offset;

      default:
        throw new IllegalArgumentException();
    }
  }
private static int parseType(
      final String signature, final int startOffset, final SignatureVisitor signatureVisitor) {
    int offset = startOffset; // Current offset in the parsed signature.
    char currentChar = signature.charAt(offset++); // The signature character at 'offset'.

    // Switch based on the first character of the JavaTypeSignature, which indicates its kind.
    switch (currentChar) {
      case 'Z':
      case 'C':
      case 'B':
      case 'S':
      case 'I':
      case 'F':
      case 'J':
      case 'D':
      case 'V':
        // Case of a BaseType or a VoidDescriptor.
        signatureVisitor.visitBaseType(currentChar);
        return offset;

      case '[':
        // Case of an ArrayTypeSignature, a '[' followed by a JavaTypeSignature.
        return parseType(signature, offset, signatureVisitor.visitArrayType());

      case 'T':
        // Case of TypeVariableSignature, an identifier between 'T' and ';'.
        int endOffset = signature.indexOf(';', offset);
        signatureVisitor.visitTypeVariable(signature.substring(offset, endOffset));
        return endOffset + 1;

      case 'L':
        // Case of a ClassTypeSignature, which ends with ';'.
        // These signatures have a main class type followed by zero or more inner class types
        // (separated by '.'). Each can have type arguments, inside '<' and '>'.
        int start = offset; // The start offset of the currently parsed main or inner class name.
        boolean visited = false; // Whether the currently parsed class name has been visited.
        boolean inner = false; // Whether we are currently parsing an inner class type.
        // Parses the signature, one character at a time.
        while (true) {
          currentChar = signature.charAt(offset++);
          if (currentChar == '.' || currentChar == ';') {
            // If a '.' or ';' is encountered, this means we have fully parsed the main class name
            // or an inner class name. This name may already have been visited it is was followed by
            // type arguments between '<' and '>'. If not, we need to visit it here.
            if (!visited) {
              String name = signature.substring(start, offset - 1);
              if (inner) {
                signatureVisitor.visitInnerClassType(name);
              } else {
                signatureVisitor.visitClassType(name);
              }
            }
            // If we reached the end of the ClassTypeSignature return, otherwise start the parsing
            // of a new class name, which is necessarily an inner class name.
            if (currentChar == ';') {
              signatureVisitor.visitEnd();
              break;
            }
            start = offset;
            visited = false;
            inner = true;
          } else if (currentChar == '<') {
            // If a '<' is encountered, this means we have fully parsed the main class name or an
            // inner class name, and that we now need to parse TypeArguments. First, we need to
            // visit the parsed class name.
            String name = signature.substring(start, offset - 1);
            if (inner) {
              signatureVisitor.visitInnerClassType(name);
            } else {
              signatureVisitor.visitClassType(name);
            }
            visited = true;
            // Now, parse the TypeArgument(s), one at a time.
            while ((currentChar = signature.charAt(offset)) != '>') {
              switch (currentChar) {
                case '*':
                  // Unbounded TypeArgument.
                  ++offset;
                  signatureVisitor.visitTypeArgument();
                  break;
                case '+':
                case '-':
                  // Extends or Super TypeArgument. Use offset + 1 to skip the '+' or '-'.
                  offset =
                      parseType(
                          signature, offset + 1, signatureVisitor.visitTypeArgument(currentChar));
                  break;
                default:
                  // Instanceof TypeArgument. The '=' is implicit.
                  offset = parseType(signature, offset, signatureVisitor.visitTypeArgument('='));
                  break;
              }
            }
          }
        }
        return offset;

      default:
        throw new IllegalArgumentException();
    }
  }
private static int parseType ( final String signature , final int startOffset , final SignatureVisitor signatureVisitor ) { int offset = startOffset ; // Current offset in the parsed signature. char currentChar = signature . charAt ( offset ++ ) ; // The signature character at 'offset'. // Switch based on the first character of the JavaTypeSignature, which indicates its kind. switch ( currentChar ) { case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : case ' ' : // Case of a BaseType or a VoidDescriptor. signatureVisitor . visitBaseType ( currentChar ) ; return offset ; case ' ' : // Case of an ArrayTypeSignature, a '[' followed by a JavaTypeSignature. return parseType ( signature , offset , signatureVisitor . visitArrayType ( ) ) ; case ' ' : // Case of TypeVariableSignature, an identifier between 'T' and ';'. int endOffset = signature . indexOf ( ' ' , offset ) ; signatureVisitor . visitTypeVariable ( signature . substring ( offset , endOffset ) ) ; return endOffset + 1 ; case ' ' : // Case of a ClassTypeSignature, which ends with ';'. // These signatures have a main class type followed by zero or more inner class types // (separated by '.'). Each can have type arguments, inside '<' and '>'. int start = offset ; // The start offset of the currently parsed main or inner class name. boolean visited = false ; // Whether the currently parsed class name has been visited. boolean inner = false ; // Whether we are currently parsing an inner class type. // Parses the signature, one character at a time. while ( true ) { currentChar = signature . charAt ( offset ++ ) ; if ( currentChar == ' ' || currentChar == ' ' ) { // If a '.' or ';' is encountered, this means we have fully parsed the main class name // or an inner class name. This name may already have been visited it is was followed by // type arguments between '<' and '>'. If not, we need to visit it here. if ( ! visited ) { String name = signature . substring ( start , offset - 1 ) ; if ( inner ) { signatureVisitor . visitInnerClassType ( name ) ; } else { signatureVisitor . visitClassType ( name ) ; } } // If we reached the end of the ClassTypeSignature return, otherwise start the parsing // of a new class name, which is necessarily an inner class name. if ( currentChar == ' ' ) { signatureVisitor . visitEnd ( ) ; break ; } start = offset ; visited = false ; inner = true ; } else if ( currentChar == ' ' ) { // If a '<' is encountered, this means we have fully parsed the main class name or an // inner class name, and that we now need to parse TypeArguments. First, we need to // visit the parsed class name. String name = signature . substring ( start , offset - 1 ) ; if ( inner ) { signatureVisitor . visitInnerClassType ( name ) ; } else { signatureVisitor . visitClassType ( name ) ; } visited = true ; // Now, parse the TypeArgument(s), one at a time. while ( ( currentChar = signature . charAt ( offset ) ) != ' ' ) { switch ( currentChar ) { case ' ' : // Unbounded TypeArgument. ++ offset ; signatureVisitor . visitTypeArgument ( ) ; break ; case ' ' : case ' ' : // Extends or Super TypeArgument. Use offset + 1 to skip the '+' or '-'. offset = parseType ( signature , offset + 1 , signatureVisitor . visitTypeArgument ( currentChar ) ) ; break ; default : // Instanceof TypeArgument. The '=' is implicit. offset = parseType ( signature , offset , signatureVisitor . visitTypeArgument ( ' ' ) ) ; break ; } } } } return offset ; default : throw new IllegalArgumentException ( ) ; } }
Parses a JavaTypeSignature and makes the given visitor visit it.

@param signature a string containing the signature that must be parsed.
@param startOffset index of the first character of the signature to parsed.
@param signatureVisitor the visitor that must visit this signature.
@return the index of the first character after the parsed signature.
Parses a JavaTypeSignature and makes the given visitor visit it .