Pessoal, não sei se alguém já se deparou com este problema: conseguir obter os nomes dos parâmetros dos métodos de uma classe. Isso é muito utilizado quando se está desenvolvendo um editor de código, plugin, ferramenta de documentação, etc.
Eu já tinha tentado obter estes nomes via reflexão, ASM, etc. Inclusive eu cheguei a fazer um analisador sintático de Java, utilizando o ANTLR para fazer isso pra mim (imaginem a trabalheira).
Daí ontem no trabalho eu precisei fazer um esquema desse novamente, só que desta vez resolvi usar um pouco mais a cabeça e descobri que Java provê no seu pacote tools.javadoc algumas APIs que permitem percorrer código fonte Java como se fosse uma árvore de objetos. Ou seja, um analisador sintático pronto e feito pela Sun 
Então, eu fiz um código que utiliza essa API e me retorna os nomes dos parâmetros para um método, coloco o código aqui por que de repente pode ser útil para alguém:
import com.sun.javadoc.ClassDoc;
import com.sun.javadoc.MethodDoc;
import com.sun.javadoc.Parameter;
import com.sun.javadoc.RootDoc;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author Bruno Gama Catão
*/
public class ParameterNamesResolver {
private static Map<MethodSignature, List<String>> paramTable;
private static String targetClass;
private static void setTargetClass(String _targetClass) {
targetClass = _targetClass;
}
public static boolean start(RootDoc root) {
paramTable = createMap();
for (ClassDoc clsDoc : root.classes()) {
if (targetClass != null && targetClass.equals(clsDoc.name())) {
for(MethodDoc mDoc : clsDoc.methods()) {
List<String> paramNames = createList();
for (Parameter param : mDoc.parameters()) {
paramNames.add(param.name());
}
paramTable.put(new MethodSignature(mDoc.name(), mDoc.signature()), paramNames);
}
}
}
return true;
}
public static ParamNamesTable processClass(Class cls, String sourceFolder) {
String sourcePath = cls.getName().replaceAll("\\.", "/");
String pkgName = sourcePath.substring(0, sourcePath.lastIndexOf("/"));
String fileName = sourcePath.substring(sourcePath.lastIndexOf("/") + 1);
ParameterNamesResolver.setTargetClass(fileName);
String[] params = {
"-doclet", ParameterNamesResolver.class.getName(),
"-sourcepath", sourceFolder,
pkgName
};
com.sun.tools.javadoc.Main.execute(params);
return new ParamNamesTable(paramTable);
}
private static <T> List<T> createList() {
return new ArrayList<T>();
}
private static <K, V> Map<K, V> createMap() {
return new HashMap<K, V>();
}
private static class MethodSignature implements Comparable<MethodSignature> {
public String method;
public String signature;
public MethodSignature(String method, String signature) {
this.method = method;
this.signature = signature;
}
public int compareTo(MethodSignature ms) {
int mDif = method.compareTo(ms.method);
if (mDif != 0) return mDif;
return signature.compareTo(signature);
}
@Override
public boolean equals(Object obj) {
MethodSignature ms = MethodSignature.class.cast(obj);
return method.equals(ms.method) && signature.equals(ms.signature);
}
}
public static class ParamNamesTable {
private Map<MethodSignature, List<String>> paramTable;
ParamNamesTable(Map<MethodSignature, List<String>> paramTable) {
this.paramTable = paramTable;
}
public List<String> getParameterNames(String method, String signature) {
return paramTable.get(new MethodSignature(method, signature));
}
public List<String> getParameterNames(String method) {
for (MethodSignature ms : paramTable.keySet()) {
if (ms.method.equals(method)) {
return paramTable.get(ms);
}
}
return null;
}
}
}
Para utilizar você pode fazer:
ParameterNamesResolver.ParamNamesTable paramTable = ParameterNamesResolver.processClass(classe, "src");
List<String> names = paramTable.getParameterNames(methodName);
System.out.println("Parameters of method: " + methodName);
for (String name : names) {
System.out.println(name);
}
