XZen
XZen

Reputation: 455

Groovy, convenient print signatures for methods with arguments

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?

Upvotes: 4

Views: 3213

Answers (1)

tim_yates
tim_yates

Reputation: 171144

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 : []

Upvotes: 6

Related Questions