Created
April 19, 2012 09:12
-
-
Save pditommaso/2419893 to your computer and use it in GitHub Desktop.
Return the list of a method parameters names
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* 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