package japicmp.util;
import japicmp.exception.JApiCmpException;
import java.util.LinkedList;
import java.util.List;
public class SignatureParser {
private List<String> parameters = new LinkedList<String>();
private String returnType = "void";
public void parse(String signature) {
int parenthesisCloseIndex = signature.indexOf(')');
if (parenthesisCloseIndex > -1) {
parseParameters(signature, parenthesisCloseIndex);
parseReturnValue(signature, 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) {
int parenthesisOpenIndex = signature.indexOf('(');
if (parenthesisOpenIndex < 0) {
throw new JApiCmpException(JApiCmpException.Reason.IllegalState, "Signature does not contain '('.");
}
if (parenthesisCloseIndex - parenthesisOpenIndex < 1) {
throw new JApiCmpException(JApiCmpException.Reason.IllegalState, "Signature must contain the char '(' before the char ')'.");
}
String paramPart = signature.substring(parenthesisOpenIndex + 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;
}
}