public Object invokeMethod()

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);
    }