Skip to content

Conversation

@eric-milles
Copy link
Member

@eric-milles eric-milles commented Jan 23, 2026

MetaClassImpl#invokeStaticMethod checked for closure property before super class method then lastly callable property. As noted in the issue ticket, the property check can be expensive. Therefore, I am proposing: check class for method, check super class for method, then check for callable property.

I think this is compatible with STC, which checks for callable property here:

// GROOVY-5705, GROOVY-5881, GROOVY-6324, GROOVY-11366: closure property

    public Object invokeStaticMethod(final Object object, final String methodName, final Object[] arguments) {
        // initialize and redirect until object class is theClass

        Object[] nonNullArguments = arguments != null ? arguments.clone() : EMPTY_ARGUMENTS;

        MetaMethod method = retrieveStaticMethod(methodName, nonNullArguments);
        if (method != null) {
            MetaClassHelper.unwrap(nonNullArguments);
            return method.doMethodInvoke(object, nonNullArguments);
        }

        Class<?>[] argumentTypes = MetaClassHelper.convertToTypeArray(nonNullArguments);
        MetaClassHelper.unwrap(nonNullArguments);

        for (var superClass = theClass.getSuperclass(); superClass != null; superClass = superClass.getSuperclass()) {
            MetaClass mc = registry.getMetaClass(superClass);
            method = mc.getStaticMetaMethod(methodName, argumentTypes);
            if (method != null) return method.doMethodInvoke(object, nonNullArguments);
        }

        Object propertyValue = null; // GROOVY-3284, GROOVY-3422, GROOVY-9779
        try {
            propertyValue = getProperty(theClass, theClass, methodName, false, false);
        } catch (MissingPropertyException ignore) {
        }
        if (propertyValue != null) {
            if (propertyValue instanceof Closure closure) {
                return closure.getMetaClass().invokeMethod(theClass, closure, DO_CALL_METHOD, arguments, false, false);
            } else {
                return registry.getMetaClass(propertyValue.getClass()).invokeMethod(propertyValue, CALL_METHOD, arguments);
            }
        }

        return invokeStaticMissingMethod(theClass, methodName, nonNullArguments);
    }

@codecov-commenter
Copy link

codecov-commenter commented Jan 23, 2026

Codecov Report

❌ Patch coverage is 86.11111% with 5 lines in your changes missing coverage. Please review.
✅ Project coverage is 67.0582%. Comparing base (c8ed37e) to head (bc6d7c4).
⚠️ Report is 1 commits behind head on master.

Files with missing lines Patch % Lines
src/main/java/groovy/lang/MetaClassImpl.java 86.1111% 1 Missing and 4 partials ⚠️
Additional details and impacted files

Impacted file tree graph

@@                Coverage Diff                 @@
##               master      #2372        +/-   ##
==================================================
- Coverage     67.0634%   67.0582%   -0.0051%     
  Complexity      29442      29442                
==================================================
  Files            1382       1382                
  Lines          116214     116199        -15     
  Branches        20471      20469         -2     
==================================================
- Hits            77937      77921        -16     
  Misses          31799      31799                
- Partials         6478       6479         +1     
Files with missing lines Coverage Δ
src/main/java/groovy/lang/MetaClassImpl.java 78.0138% <86.1111%> (+0.0969%) ⬆️

... and 6 files with indirect coverage changes

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants