Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Groovy, convenient print signatures for methods with arguments

Tags:

groovy

I have some Groovy class, for example:

class Apple {
   public void methodA(String myParam) {}
   public void methodB(String myParam2, String myParam3) {}
}

And I want to print all methods of class Apple in convenient format, for example:

Class Apple: 
- methodA <String: myParam>
- methodB <String: myParam2> <String: myParam3>

or just:

Class Apple: 
- methodA <myParam>
- methodB <myParam2> <myParam3>

Is it possible in Groovy?

For now I'm using for-each loop for Apple.metaClass.methods and printing method.name, for example:

for (MetaMethod metaMethod in Apple.metaClass.methods) {
    println metaMethod.name
}

But I can't find a way to print names of arguments.. Also, is it possible to know if there are default values for the arguments?

Could you please advise?

like image 418
XZen Avatar asked Oct 26 '25 11:10

XZen


1 Answers

No(*). Parameter names are not stored with the bytecode (I believe they might be if the class is compiled with debugging turned on, but I've not tried it).

(* it is possible with some non-reflection digging, but it relies on a lot of things, and feels like it would be quite a brittle point in your design)

With Java 7 and below, you can just get the types of the arguments. With Java 8, a new getParameters call was added to java.lang.reflect.Method, so with Java 8 and Groovy 2.3+ it's possible to do:

class Apple {
   public void methodA(String myParam) {}
   public void methodB(String myParam2, String myParam3) {}
}

Apple.class.declaredMethods
           .findAll { !it.synthetic }
           .each { println "$it.name $it.parameters.name" }

To print:

methodB : [arg0, arg1]
methodA : [arg0]

But as you can see, the original parameter names are again lost.

As for default values, the way Groovy handles these is to create multiple methods. If you declare a method:

class Apple {
    public void foo( bar="quux" ) { println bar }
}

Then this generates two methods in bytecode:

public void foo() { foo( 'quux' ) }
public void foo( bar ) { println bar }

If you run the above method inspector for this class containing the method foo, you'll see the output is:

foo : [arg0]
foo : []
like image 72
tim_yates Avatar answered Oct 28 '25 03:10

tim_yates