Skip to content

Instantly share code, notes, and snippets.

@pditommaso
Created April 19, 2012 09:12
Show Gist options
  • Save pditommaso/2419893 to your computer and use it in GitHub Desktop.
Save pditommaso/2419893 to your computer and use it in GitHub Desktop.
Return the list of a method parameters names
/**
* Based on Stackoverflow answer http://stackoverflow.com/a/2729907/395921
*
* @author Paolo Di Tommaso
*
*/
public class Names {
/**
* Returns a list containing one parameter name for each argument accepted
* by the given constructor. If the class was compiled with debugging
* symbols, the parameter names will match those provided in the Java source
* code. Otherwise, a generic "arg" parameter name is generated ("arg0" for
* the first argument, "arg1" for the second...).
*
* This method relies on the constructor's class loader to locate the
* bytecode resource that defined its class.
*
* @param constructor
* @return
* @throws IOException
*/
public static List<String> getParameterNames(Constructor<?> constructor) throws IOException {
Class<?> declaringClass = constructor.getDeclaringClass();
ClassLoader declaringClassLoader = declaringClass.getClassLoader();
Type declaringType = Type.getType(declaringClass);
String constructorDescriptor = Type.getConstructorDescriptor(constructor);
String url = declaringType.getInternalName() + ".class";
InputStream classFileInputStream = declaringClassLoader.getResourceAsStream(url);
if (classFileInputStream == null) {
throw new IllegalArgumentException("The constructor's class loader cannot find the bytecode that defined the constructor's class (URL: " + url + ")");
}
ClassNode classNode = getClassNode(classFileInputStream);
return getNames(classNode, "<init>", constructorDescriptor);
}
public static List<String> getParameterNames(Method method) throws IOException {
Class<?> declaringClass = method.getDeclaringClass();
ClassLoader declaringClassLoader = declaringClass.getClassLoader();
Type declaringType = Type.getType(declaringClass);
String constructorDescriptor = Type.getMethodDescriptor(method);
String url = declaringType.getInternalName() + ".class";
InputStream classFileInputStream = declaringClassLoader.getResourceAsStream(url);
if (classFileInputStream == null) {
throw new IllegalArgumentException("The constructor's class loader cannot find the bytecode that defined the constructor's class (URL: " + url + ")");
}
ClassNode classNode = getClassNode(classFileInputStream);
return getNames(classNode, method.getName(), constructorDescriptor);
}
private static List<String> getNames( ClassNode classNode, String methodName, String methodSignature ) {
@SuppressWarnings("unchecked")
List<MethodNode> methods = classNode.methods;
for (MethodNode method : methods) {
if (method.name.equals(methodName) && method.desc.equals(methodSignature)) {
Type[] argumentTypes = Type.getArgumentTypes(method.desc);
List<String> parameterNames = new ArrayList<String>(argumentTypes.length);
@SuppressWarnings("unchecked")
List<LocalVariableNode> localVariables = method.localVariables;
for (int i = 0; i < argumentTypes.length; i++) {
// The first local variable actually represents the "this" object
parameterNames.add(localVariables.get(i + 1).name);
}
return parameterNames;
}
}
return null;
}
private static ClassNode getClassNode( InputStream classFileInputStream ) throws IOException {
ClassNode classNode = null;
try {
classNode = new ClassNode();
ClassReader classReader = new ClassReader(classFileInputStream);
classReader.accept(classNode, 0);
} finally {
classFileInputStream.close();
}
return classNode;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment