package japicmp.util; import java.util.LinkedList; import java.util.List; public class MethodDescriptorParser { private List<String> parameters = new LinkedList<String>(); private String returnType = "void"; /** * Parses a method descriptor as specified in the Java Virtual Machine Specification (see http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.3.3). * * @param methodDescriptor the method descriptor */ public void parse(String methodDescriptor) { int parenthesisCloseIndex = methodDescriptor.indexOf(')'); if (parenthesisCloseIndex > -1) { parseParameters(methodDescriptor, parenthesisCloseIndex); parseReturnValue(methodDescriptor, parenthesisCloseIndex); } } private void parseReturnValue(String signature, int parenthesisCloseIndex) { String retValPart = signature.substring(parenthesisCloseIndex + 1); List<String> retValTypes = parseTypes(retValPart); returnType = retValTypes.get(0); } private void parseParameters(String signature, int parenthesisCloseIndex) { String paramPart = signature.substring(1, parenthesisCloseIndex); List<String> paramTypes = parseTypes(paramPart); parameters.clear(); parameters.addAll(paramTypes); } public List<String> parseTypes(String paramPart) { List<String> types = new LinkedList<String>(); boolean arrayNotation = false; for (int i = 0; i < paramPart.length(); i++) { char c = paramPart.charAt(i); String type = "void"; switch (c) { case 'Z': type = "boolean"; break; case 'B': type = "byte"; break; case 'C': type = "char"; break; case 'S': type = "short"; break; case 'I': type = "int"; break; case 'J': type = "long"; break; case 'F': type = "float"; break; case 'D': type = "double"; break; case 'V': type = "void"; break; case '[': arrayNotation = true; continue; case 'L': StringBuilder fqn = new StringBuilder(); i++; while (i < paramPart.length()) { c = paramPart.charAt(i); if (c == ';') { break; } else if (c == '/') { fqn.append('.'); } else { fqn.append(c); } i++; } type = fqn.toString(); break; default: throw new IllegalStateException("Unknown type signature: '" + c + "'"); } if (arrayNotation) { type += "[]"; arrayNotation = false; } types.add(type); } return types; } public List<String> getParameters() { return parameters; } public String getReturnType() { return returnType; } public String getMethodSignature(String methodName) { StringBuilder sb = new StringBuilder(); int counter = 0; for (String parameter : parameters) { if (counter > 0) { sb.append(","); } sb.append(parameter); counter++; } return methodName + "(" + sb.toString() + ")"; } }