public static String typeSignatureToString()

in src/main/java/org/apache/bcel/classfile/Utility.java [1376:1535]


    public static String typeSignatureToString(final String signature, final boolean chopit) throws ClassFormatException {
        // corrected concurrent private static field acess
        wrap(CONSUMER_CHARS, 1); // This is the default, read just one char like 'B'
        try {
            switch (signature.charAt(0)) {
            case 'B':
                return "byte";
            case 'C':
                return "char";
            case 'D':
                return "double";
            case 'F':
                return "float";
            case 'I':
                return "int";
            case 'J':
                return "long";
            case 'T': { // TypeVariableSignature
                final int index = signature.indexOf(';'); // Look for closing ';'
                if (index < 0) {
                    throw new ClassFormatException("Invalid type variable signature: " + signature);
                }
                // corrected concurrent private static field acess
                wrap(CONSUMER_CHARS, index + 1); // "Tblabla;" 'T' and ';' are removed
                return compactClassName(signature.substring(1, index), chopit);
            }
            case 'L': { // Full class name
                // should this be a while loop? can there be more than
                // one generic clause? (markro)
                int fromIndex = signature.indexOf('<'); // generic type?
                if (fromIndex < 0) {
                    fromIndex = 0;
                } else {
                    fromIndex = signature.indexOf('>', fromIndex);
                    if (fromIndex < 0) {
                        throw new ClassFormatException("Invalid signature: " + signature);
                    }
                }
                final int index = signature.indexOf(';', fromIndex); // Look for closing ';'
                if (index < 0) {
                    throw new ClassFormatException("Invalid signature: " + signature);
                }

                // check to see if there are any TypeArguments
                final int bracketIndex = signature.substring(0, index).indexOf('<');
                if (bracketIndex < 0) {
                    // just a class identifier
                    wrap(CONSUMER_CHARS, index + 1); // "Lblabla;" 'L' and ';' are removed
                    return compactClassName(signature.substring(1, index), chopit);
                }
                // but make sure we are not looking past the end of the current item
                fromIndex = signature.indexOf(';');
                if (fromIndex < 0) {
                    throw new ClassFormatException("Invalid signature: " + signature);
                }
                if (fromIndex < bracketIndex) {
                    // just a class identifier
                    wrap(CONSUMER_CHARS, fromIndex + 1); // "Lblabla;" 'L' and ';' are removed
                    return compactClassName(signature.substring(1, fromIndex), chopit);
                }

                // we have TypeArguments; build up partial result
                // as we recurse for each TypeArgument
                final StringBuilder type = new StringBuilder(compactClassName(signature.substring(1, bracketIndex), chopit)).append("<");
                int consumedChars = bracketIndex + 1; // Shadows global var

                // check for wildcards
                if (signature.charAt(consumedChars) == '+') {
                    type.append("? extends ");
                    consumedChars++;
                } else if (signature.charAt(consumedChars) == '-') {
                    type.append("? super ");
                    consumedChars++;
                }

                // get the first TypeArgument
                if (signature.charAt(consumedChars) == '*') {
                    type.append("?");
                    consumedChars++;
                } else {
                    type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                    // update our consumed count by the number of characters the for type argument
                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
                    wrap(CONSUMER_CHARS, consumedChars);
                }

                // are there more TypeArguments?
                while (signature.charAt(consumedChars) != '>') {
                    type.append(", ");
                    // check for wildcards
                    if (signature.charAt(consumedChars) == '+') {
                        type.append("? extends ");
                        consumedChars++;
                    } else if (signature.charAt(consumedChars) == '-') {
                        type.append("? super ");
                        consumedChars++;
                    }
                    if (signature.charAt(consumedChars) == '*') {
                        type.append("?");
                        consumedChars++;
                    } else {
                        type.append(typeSignatureToString(signature.substring(consumedChars), chopit));
                        // update our consumed count by the number of characters the for type argument
                        consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
                        wrap(CONSUMER_CHARS, consumedChars);
                    }
                }

                // process the closing ">"
                consumedChars++;
                type.append(">");

                if (signature.charAt(consumedChars) == '.') {
                    // we have a ClassTypeSignatureSuffix
                    type.append(".");
                    // convert SimpleClassTypeSignature to fake ClassTypeSignature
                    // and then recurse to parse it
                    type.append(typeSignatureToString("L" + signature.substring(consumedChars + 1), chopit));
                    // update our consumed count by the number of characters the for type argument
                    // note that this count includes the "L" we added, but that is ok
                    // as it accounts for the "." we didn't consume
                    consumedChars = unwrap(CONSUMER_CHARS) + consumedChars;
                    wrap(CONSUMER_CHARS, consumedChars);
                    return type.toString();
                }
                if (signature.charAt(consumedChars) != ';') {
                    throw new ClassFormatException("Invalid signature: " + signature);
                }
                wrap(CONSUMER_CHARS, consumedChars + 1); // remove final ";"
                return type.toString();
            }
            case 'S':
                return "short";
            case 'Z':
                return "boolean";
            case '[': { // Array declaration
                int n;
                final StringBuilder brackets = new StringBuilder(); // Accumulate []'s
                // Count opening brackets and look for optional size argument
                for (n = 0; signature.charAt(n) == '['; n++) {
                    brackets.append("[]");
                }
                final int consumedChars = n; // Remember value
                // The rest of the string denotes a '<field_type>'
                final String type = typeSignatureToString(signature.substring(n), chopit);
                // corrected concurrent private static field acess
                // consumed_chars += consumed_chars; is replaced by:
                final int temp = unwrap(CONSUMER_CHARS) + consumedChars;
                wrap(CONSUMER_CHARS, temp);
                return type + brackets.toString();
            }
            case 'V':
                return "void";
            default:
                throw new ClassFormatException("Invalid signature: '" + signature + "'");
            }
        } catch (final StringIndexOutOfBoundsException e) { // Should never occur
            throw new ClassFormatException("Invalid signature: " + signature, e);
        }
    }