Instantly share code, notes, and snippets.

Embed
What would you like to do?
Support for instance method references
Index: src/main/org/codehaus/groovy/runtime/MethodClosure.java
IDEA additional info:
Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP
<+>UTF-8
===================================================================
--- src/main/org/codehaus/groovy/runtime/MethodClosure.java (revision Local version)
+++ src/main/org/codehaus/groovy/runtime/MethodClosure.java (revision Shelved version)
@@ -19,8 +19,8 @@
package org.codehaus.groovy.runtime;
import groovy.lang.Closure;
+import groovy.lang.MetaClass;
import groovy.lang.MetaMethod;
-
import java.util.List;
@@ -31,24 +31,31 @@
* @author <a href="mailto:james@coredevelopers.net">James Strachan</a>
*/
public class MethodClosure extends Closure {
+ private final static Class[] EMPTY_CLASS_ARRAY = new Class[0];
public static boolean ALLOW_RESOLVE = false;
private static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
- private String method;
+ private final Object owner;
+ private final String method;
+ private final boolean classReceiver;
public MethodClosure(Object owner, String method) {
super(owner);
this.method = method;
+ this.owner = owner;
- final Class clazz = owner.getClass()==Class.class?(Class) owner:owner.getClass();
+ classReceiver = owner.getClass() == Class.class;
+ Class clazz = classReceiver ?(Class) owner:owner.getClass();
maximumNumberOfParameters = 0;
parameterTypes = EMPTY_CLASS_ARRAY;
- List<MetaMethod> methods = InvokerHelper.getMetaClass(clazz).respondsTo(owner, method);
+ MetaClass ownerMetaClass = InvokerHelper.getMetaClass(clazz);
+ List<MetaMethod> methods = ownerMetaClass.respondsTo(owner, method);
for(MetaMethod m : methods) {
+ if (classReceiver && !m.isStatic()) continue;
if (m.getParameterTypes().length > maximumNumberOfParameters) {
Class[] pt = m.getNativeParameterTypes();
maximumNumberOfParameters = pt.length;
@@ -56,13 +63,27 @@
}
}
}
-
+
public String getMethod() {
return method;
}
protected Object doCall(Object arguments) {
- return InvokerHelper.invokeMethod(getOwner(), method, arguments);
+ return InvokerHelper.invokeMethod(owner, method, arguments);
+ }
+
+ @Override
+ public Object call(final Object... args) {
+ if (parameterTypes == EMPTY_CLASS_ARRAY && classReceiver && args.length > 0 && args[0].getClass() == owner) {
+ // support String.&toUpperCase style method closures
+ // This implementation is limited to unambiguous cases in order to avoid relying on catching a
+ // MissingMethodException then potentially rethrowing it
+ Object instanceReceiver = args[0];
+ Object[] argsLeft = new Object[args.length - 1];
+ System.arraycopy(args, 1, argsLeft, 0, argsLeft.length);
+ return InvokerHelper.invokeMethod(instanceReceiver, method, argsLeft);
+ }
+ return super.call(args);
}
private Object readResolve() {
@@ -71,7 +92,7 @@
}
throw new UnsupportedOperationException();
}
-
+
public Object getProperty(String property) {
if ("method".equals(property)) {
return getMethod();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment