in src/main/java/groovy/lang/MetaClassImpl.java [1095:1241]
public Object invokeMethod(final Class sender, final Object object, final String methodName, final Object[] originalArguments, final boolean isCallToSuper, final boolean fromInsideClass) {
checkInitalised();
if (object == null) {
throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
}
final Object[] arguments = Optional.ofNullable(originalArguments).orElse(EMPTY_ARGUMENTS);
MetaMethod method = getMetaMethod(sender, object, methodName, isCallToSuper, arguments);
if (object instanceof Closure) {
final Closure closure = (Closure)object;
final Object owner = closure.getOwner();
if (CALL_METHOD.equals(methodName) || DO_CALL_METHOD.equals(methodName)) {
var closureClass = closure.getClass();
if (closureClass == MethodClosure.class) {
return invokeMethodClosure((MethodClosure) closure, arguments);
} else if (closureClass == CurriedClosure.class) {
MetaClass ownerMetaClass = registry.getMetaClass(owner instanceof Class ? (Class) owner : owner.getClass());
return ownerMetaClass.invokeMethod(owner, methodName, ((CurriedClosure) closure).getUncurriedArguments(arguments));
}
if (method == null) invokeMissingMethod(object, methodName, arguments);
}
final Object delegate = closure.getDelegate();
final int resolveStrategy = closure.getResolveStrategy();
final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
switch (resolveStrategy) {
case Closure.TO_SELF:
method = closure.getMetaClass().pickMethod(methodName, argClasses);
if (method != null) return method.invoke(closure, arguments);
break;
case Closure.DELEGATE_ONLY:
if (method == null && delegate != null && delegate != closure) {
MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
method = delegateMetaClass.pickMethod(methodName, argClasses);
if (method != null) {
return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
}
if (delegate instanceof GroovyObject) {
return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
}
}
break;
case Closure.OWNER_ONLY:
if (method == null && owner != closure) {
MetaClass ownerMetaClass = lookupObjectMetaClass(owner);
return ownerMetaClass.invokeMethod(owner, methodName, originalArguments);
}
break;
case Closure.DELEGATE_FIRST:
Tuple2<Object, MetaMethod> tuple = invokeMethod(method, delegate, closure, methodName, argClasses, originalArguments, owner);
Object result = tuple.getV1();
method = tuple.getV2();
if (InvokeMethodResult.NONE != result) {
return result;
}
if (method == null && resolveStrategy != Closure.TO_SELF) {
// still no methods found, test if delegate or owner are GroovyObjects
// and invoke the method on them if so.
MissingMethodException last = null;
if (delegate != closure && delegate instanceof GroovyObject) {
try {
return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
} catch (MissingMethodException mme) {
if (last == null) last = mme;
}
}
if (owner != closure && owner instanceof GroovyObject) {
try {
return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
} catch (MissingMethodException mme) {
last = mme;
}
}
if (last != null)
return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
}
break;
default:
Tuple2<Object, MetaMethod> t = invokeMethod(method, delegate, closure, methodName, argClasses, originalArguments, owner);
Object r = t.getV1();
method = t.getV2();
if (InvokeMethodResult.NONE != r) {
return r;
}
if (method == null && resolveStrategy != Closure.TO_SELF) {
// still no methods found, if delegate or owner are GroovyObjects, invoke the method on them
MissingMethodException last = null;
if (owner != closure && owner instanceof GroovyObject) {
try {
return invokeMethodOnGroovyObject(methodName, originalArguments, owner);
} catch (MissingMethodException mme) {
if (methodName.equals(mme.getMethod())) {
if (last == null) last = mme;
} else {
throw mme;
}
} catch (InvokerInvocationException iie) {
if (iie.getCause() instanceof MissingMethodException) {
MissingMethodException mme = (MissingMethodException) iie.getCause();
if (methodName.equals(mme.getMethod())) {
if (last == null) last = mme;
} else {
throw iie;
}
} else {
throw iie;
}
}
}
if (delegate != closure && delegate instanceof GroovyObject) {
try {
return invokeMethodOnGroovyObject(methodName, originalArguments, delegate);
} catch (MissingMethodException mme) {
last = mme;
} catch (InvokerInvocationException iie) {
if (iie.getCause() instanceof MissingMethodException) {
last = (MissingMethodException) iie.getCause();
} else {
throw iie;
}
}
}
if (last != null)
return invokeMissingMethod(object, methodName, originalArguments, last, isCallToSuper);
}
}
}
if (method != null) {
if (arguments.length == 0 && "clone".equals(methodName) && method.getDeclaringClass() == ReflectionCache.OBJECT_CLASS) {
throw method.processDoMethodInvokeException(new CloneNotSupportedException(), object, arguments);
}
MetaMethod transformedMetaMethod = VM_PLUGIN.transformMetaMethod(this, method);
return transformedMetaMethod.doMethodInvoke(object, arguments);
}
return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
}