docs: public Object invokeMethod(Class sender, Object object, String methodName, Object[] originalArguments, boolean isCallToSuper, boolean fromInsideClass) {
          checkInitalised();
          if (object == null) {
              throw new NullPointerException("Cannot invoke method: " + methodName + " on null object");
          }
  
          final Object[] arguments = originalArguments == null ? EMPTY_ARGUMENTS : originalArguments;
  //        final Class[] argClasses = MetaClassHelper.convertToTypeArray(arguments);
  //
  //        unwrap(arguments);
  
          MetaMethod method = getMetaMethod(sender, object, methodName, isCallToSuper, arguments);
  
          final boolean isClosure = object instanceof Closure;
          if (isClosure) {
              final Closure closure = (Closure) object;
              final Object owner = closure.getOwner();
  
              if (CLOSURE_CALL_METHOD.equals(methodName) || CLOSURE_DO_CALL_METHOD.equals(methodName)) {
                  final Class objectClass = object.getClass();
                  if (objectClass == MethodClosure.class) {
                      return this.invokeMethodClosure(object, methodName, arguments);
                  } else if (objectClass == CurriedClosure.class) {
                      final CurriedClosure cc = (CurriedClosure) object;
                      // change the arguments for an uncurried call
                      final Object[] curriedArguments = cc.getUncurriedArguments(arguments);
                      final Class ownerClass = owner instanceof Class ? (Class) owner : owner.getClass();
                      final MetaClass ownerMetaClass = registry.getMetaClass(ownerClass);
                      return ownerMetaClass.invokeMethod(owner, methodName, curriedArguments);
                  }
                  if (method==null) invokeMissingMethod(object,methodName,arguments);
              }
  
              final Object delegate = closure.getDelegate();
              final boolean isClosureNotOwner = owner != closure;
              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 != closure && delegate != null) {
                          MetaClass delegateMetaClass = lookupObjectMetaClass(delegate);
                          method = delegateMetaClass.pickMethod(methodName, argClasses);
                          if (method != null)
                              return delegateMetaClass.invokeMethod(delegate, methodName, originalArguments);
                          else if (delegate != closure && (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.getFirst();
                      method = tuple.getSecond();
                      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 (isClosureNotOwner && (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.getFirst();
                      method = t.getSecond();
                      if (InvokeMethodResult.NONE != r) {
                          return r;
                      }
  
                      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 (isClosureNotOwner && (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) {
              return method.doMethodInvoke(object, arguments);
          } else {
              return invokePropertyOrMissing(object, methodName, originalArguments, fromInsideClass, isCallToSuper);
          }
      }