Skip to content

Commit

Permalink
Merge pull request #233 from basil/asm
Browse files Browse the repository at this point in the history
Reduce ASM dep in `ClassDescriptor`
  • Loading branch information
jglick committed Jun 1, 2021
2 parents afc1340 + 8f337b8 commit 3da2d02
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 2 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@
* Groovy AST transformation that capture necessary parameter names.
*
* @author Kohsuke Kawaguchi
* @see CapturedParameterNames
*/
@MetaInfServices
@GroovyASTTransformation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@
* to do than generating the same files that the annotation processor does.
*
* @author Kohsuke Kawaguchi
* @see CaptureParameterNameTransformation
*/
@Retention(RUNTIME)
public @interface CapturedParameterNames {
Expand Down
28 changes: 26 additions & 2 deletions core/src/main/java/org/kohsuke/stapler/ClassDescriptor.java
Original file line number Diff line number Diff line change
Expand Up @@ -35,9 +35,11 @@
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.lang.reflect.Parameter;
import java.lang.reflect.ParameterizedType;
import java.net.URL;
import java.util.ArrayList;
Expand All @@ -52,6 +54,7 @@
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Logger;
import java.util.stream.Stream;

import static java.util.logging.Level.FINE;
import static java.util.logging.Level.WARNING;
Expand Down Expand Up @@ -191,9 +194,15 @@ public static String[] loadParameterNames(Method m) {
CapturedParameterNames cpn = m.getAnnotation(CapturedParameterNames.class);
if(cpn!=null) return cpn.value();

// reflection is the most efficient and supported system
String[] n = loadParameterNamesFromReflection(m);
if (n != null) {
return n;
}

// debug information, if present, is more trustworthy
try {
String[] n = ASM.loadParametersFromAsm(m);
n = ASM.loadParametersFromAsm(m);
if (n!=null) return n;
} catch (LinkageError e) {
LOGGER.log(FINE, "Incompatible ASM", e);
Expand Down Expand Up @@ -228,9 +237,15 @@ public static String[] loadParameterNames(Constructor<?> m) {
CapturedParameterNames cpn = m.getAnnotation(CapturedParameterNames.class);
if(cpn!=null) return cpn.value();

// reflection is the most efficient and supported system
String[] n = loadParameterNamesFromReflection(m);
if (n != null) {
return n;
}

// debug information, if present, is more trustworthy
try {
String[] n = ASM.loadParametersFromAsm(m);
n = ASM.loadParametersFromAsm(m);
if (n!=null) return n;
} catch (LinkageError e) {
LOGGER.log(FINE, "Incompatible ASM", e);
Expand All @@ -242,6 +257,15 @@ public static String[] loadParameterNames(Constructor<?> m) {
return EMPTY_ARRAY;
}

static String[] loadParameterNamesFromReflection(final Executable m) {
Parameter[] ps = m.getParameters();
if (Stream.of(ps).allMatch(Parameter::isNamePresent)) {
return Stream.of(ps).map(Parameter::getName).toArray(String[]::new);
} else {
return null;
}
}

/**
* Determines the constructor parameter names.
*
Expand Down
26 changes: 26 additions & 0 deletions core/src/test/java/org/kohsuke/stapler/ClassDescriptorTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,32 @@ public class ClassDescriptorTest {
assertEquals("[a, b, x]",Arrays.asList(names).toString());
}

@Test public void loadParameterNamesFromReflection() throws Exception {
// collect test cases
Map<String,Method> testCases = new HashMap<String,Method>();
for (Method m : ClassDescriptorTest.class.getDeclaredMethods())
if (m.getName().startsWith("methodWith"))
testCases.put(m.getName().substring(10), m);
// expected results
Map<String,String[]> expected = new HashMap<String,String[]>();
expected.put("NoParams", new String[0]);
expected.put("NoParams_static", new String[0]);
expected.put("ManyParams", new String[] { "a", "b", "c", "d", "e", "f", "g", "h", "i" });
expected.put("Params_static", new String[] { "abc", "def", "ghi" });
// run tests
for (Map.Entry<String,String[]> entry : expected.entrySet()) {
Method testMethod = testCases.get(entry.getKey());
assertNotNull("Method missing for " + entry.getKey(), testMethod);
String[] result = ClassDescriptor.loadParameterNamesFromReflection(testMethod);
assertNotNull("Null result for " + entry.getKey(), result);
if (!Arrays.equals(entry.getValue(), result)) {
StringBuilder buf = new StringBuilder('|');
for (String s : result) buf.append(s).append('|');
fail("Unexpected result for " + entry.getKey() + ": " + buf);
}
}
}

@Test public void loadParametersFromAsm() throws Exception {
// get private method that is being tested
Method lpfa = ClassDescriptor.ASM.class.getDeclaredMethod(
Expand Down

0 comments on commit 3da2d02

Please sign in to comment.