TypeInfo (@Nullable String text) { if (text == null) return TypeInfo.SimpleTypeInfo.NULL; TypeKind kind = TEXT_TO_KIND.get(text); if (kind != null) { return kind.isReference() ? new RefTypeInfo(text) : new SimpleTypeInfo(kind); } if (text.startsWith("? extends ")) { return new DerivedTypeInfo(TypeKind.EXTENDS, fromString(text.substring("? extends ".length()))); } if (text.startsWith("? super ")) { return new DerivedTypeInfo(TypeKind.SUPER, fromString(text.substring("? super ".length()))); } if (text.endsWith("[]")) { return fromString(text.substring(0, text.length() - 2)).arrayOf(); } if (text.endsWith("...")) { return new DerivedTypeInfo(TypeKind.ELLIPSIS, fromString(text.substring(0, text.length() - 3))); } if (text.endsWith(">")) { int depth = 1; int end = text.length() - 1; List<TypeInfo> components = new ArrayList<>(); for (int pos = end - 1; pos > 0; pos--) { char ch = text.charAt(pos); if (ch == '>') depth++; else if (ch == ',' && depth == 1) { String component = text.substring(pos + 1, end); end = pos; components.add(fromString(component)); } else if (ch == '<') { depth--; if (depth == 0) { String component = text.substring(pos + 1, end); components.add(fromString(component)); Collections.reverse(components); int prevGeneric = text.lastIndexOf('>', pos); RefTypeInfo outer; String name; if (prevGeneric > 0) { if (text.charAt(prevGeneric + 1) != '.') { throw new IllegalArgumentException("Malformed type: " + text); } outer = (RefTypeInfo)fromString(text.substring(0, prevGeneric + 1)); name = text.substring(prevGeneric + 2, pos); } else { name = text.substring(0, pos); outer = null; } return new RefTypeInfo(name, outer, components.toArray(EMPTY_ARRAY)); } } } throw new IllegalArgumentException("Malformed type: " + text); } return new RefTypeInfo(text); }