This is an automated email from the ASF dual-hosted git repository.

sunlan pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git


The following commit(s) were added to refs/heads/master by this push:
     new 40121ec647 GROOVY-11694: SC: implicit-this call to static method of 
super class (#2251)
40121ec647 is described below

commit 40121ec6470793f0c517f062862b0a665805260c
Author: Eric Milles <eric.mil...@thomsonreuters.com>
AuthorDate: Sun Jun 8 00:48:46 2025 -0500

    GROOVY-11694: SC: implicit-this call to static method of super class (#2251)
---
 .../classgen/asm/sc/StaticInvocationWriter.java    | 20 +++++++++-----------
 .../StaticMethodCallExpressionTransformer.java     | 11 ++++++++---
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 22 +++++++++++++++++-----
 3 files changed, 34 insertions(+), 19 deletions(-)

diff --git 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
index 68cbee26d4..f1486ffe7e 100644
--- 
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
+++ 
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticInvocationWriter.java
@@ -78,11 +78,6 @@ import static 
org.apache.groovy.ast.tools.ExpressionUtils.isNullConstant;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isSuperExpression;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isThisExpression;
 import static org.apache.groovy.ast.tools.ExpressionUtils.isThisOrSuper;
-import static org.codehaus.groovy.ast.ClassHelper.isGStringType;
-import static org.codehaus.groovy.ast.ClassHelper.isGeneratedFunction;
-import static org.codehaus.groovy.ast.ClassHelper.isObjectType;
-import static org.codehaus.groovy.ast.ClassHelper.isPrimitiveVoid;
-import static org.codehaus.groovy.ast.ClassHelper.isStringType;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
@@ -187,7 +182,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
 
     private Expression thisObjectExpression(final ClassNode source, final 
ClassNode target) {
         ClassNode thisType = source;
-        while (isGeneratedFunction(thisType)) {
+        while (ClassHelper.isGeneratedFunction(thisType)) {
             thisType = thisType.getOuterClass();
         }
         Expression thisExpr;
@@ -287,7 +282,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             mv.visitMethodInsn(INVOKESTATIC, owner, target.getName(), desc, 
false);
             controller.getOperandStack().remove(argumentList.size());
 
-            if (isPrimitiveVoid(returnType)) {
+            if (ClassHelper.isPrimitiveVoid(returnType)) {
                 if (currentCall != null && 
currentCall.getNodeMetaData(AsmClassGenerator.ELIDE_EXPRESSION_VALUE) != null) {
                     return true; // do not load value
                 }
@@ -304,6 +299,9 @@ public class StaticInvocationWriter extends 
InvocationWriter {
         }
 
         ClassNode receiverType = receiver == null ? ClassHelper.OBJECT_TYPE : 
controller.getTypeChooser().resolveType(receiver, controller.getThisType());
+        if 
(StaticTypeCheckingSupport.isClassClassNodeWrappingConcreteType(receiverType) 
&& !ClassHelper.isClassType(declaringClass)) {
+            receiverType = receiverType.getGenericsTypes()[0].getType(); // 
GROOVY-11694
+        }
 
         if 
(AsmClassGenerator.isMemberDirectlyAccessible(target.getModifiers(), 
declaringClass, enclosingClass)
                 && !(target.isProtected() && !inSamePackage(declaringClass, 
enclosingClass) && !isSubtype(receiverType, enclosingClass))) { // GROOVY-7325
@@ -375,7 +373,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
         if (lastPrmType.isArray() && (nArgs > nPrms || nArgs == nPrms - 1
                 || (nArgs == nPrms && !lastArgType.isArray()
                     && 
(StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(lastArgType, 
lastPrmType.getComponentType())
-                        || isGStringType(lastArgType) && 
isStringType(lastPrmType.getComponentType())))
+                        || ClassHelper.isGStringType(lastArgType) && 
ClassHelper.isStringType(lastPrmType.getComponentType())))
         )) {
             OperandStack operandStack = controller.getOperandStack();
             // first arguments/parameters as usual
@@ -665,7 +663,7 @@ public class StaticInvocationWriter extends 
InvocationWriter {
             if (visitor instanceof AsmClassGenerator) {
                 ClassNode topOperand = 
controller.getOperandStack().getTopOperand();
                 ClassNode type = getType();
-                if (isGStringType(topOperand) && isStringType(type)) {
+                if (ClassHelper.isGStringType(topOperand) && 
ClassHelper.isStringType(type)) {
                     // perform regular type conversion
                     controller.getOperandStack().doGroovyCast(type);
                     return;
@@ -702,12 +700,12 @@ public class StaticInvocationWriter extends 
InvocationWriter {
                             && typeClass != EnumConstantClassNode.class) {
                         type = declaringClass; // ex: LUB type
                     }
-                    if (isObjectType(declaringClass)) {
+                    if (ClassHelper.isObjectType(declaringClass)) {
                         // checkcast not necessary because Object never evolves
                         // and it prevents a potential ClassCastException if 
the
                         // delegate of a closure is changed in an SC closure
                         type = ClassHelper.OBJECT_TYPE;
-                    } else if (isObjectType(type)) {
+                    } else if (ClassHelper.isObjectType(type)) {
                         // can happen for compiler rewritten code, where type 
information is missing
                         type = declaringClass;
                     }
diff --git 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticMethodCallExpressionTransformer.java
 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticMethodCallExpressionTransformer.java
index d2a1d9aeaa..285490015d 100644
--- 
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticMethodCallExpressionTransformer.java
+++ 
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/StaticMethodCallExpressionTransformer.java
@@ -35,10 +35,15 @@ class StaticMethodCallExpressionTransformer {
     }
 
     Expression transformStaticMethodCallExpression(final 
StaticMethodCallExpression smce) {
-        Object target = smce.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+        var target = smce.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
         if (target instanceof MethodNode) {
-            ClassExpression receiver = new 
ClassExpression(smce.getOwnerType().getPlainNodeReference());
-            MethodCallExpression mce = new MethodCallExpression(receiver, 
smce.getMethod(), smce.getArguments());
+            var receiver = new 
ClassExpression(smce.getOwnerType().getPlainNodeReference());
+            receiver.setLineNumber(smce.getLineNumber());
+            receiver.setColumnNumber(smce.getColumnNumber());
+            receiver.setLastLineNumber(receiver.getLineNumber());
+            receiver.setLastColumnNumber(receiver.getColumnNumber());
+
+            var mce = new MethodCallExpression(receiver, smce.getMethod(), 
smce.getArguments());
             mce.setMethodTarget((MethodNode) target);
             mce.setSourcePosition(smce);
             mce.copyNodeMetaData(smce);
diff --git a/src/test/groovy/groovy/transform/stc/MethodCallsSTCTest.groovy 
b/src/test/groovy/groovy/transform/stc/MethodCallsSTCTest.groovy
index aa0eec4ce8..b9f068fad7 100644
--- a/src/test/groovy/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -104,6 +104,14 @@ class MethodCallsSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
+    void testStaticMethodCallThroughInstance() {
+        assertScript '''
+            A a = new A()
+            String echo = a.echo 'echo'
+            assert echo == 'echo'
+        '''
+    }
+
     void testStaticMethodCallWithInheritance() {
         assertScript '''
             String echo = B.echo 'echo'
@@ -111,11 +119,13 @@ class MethodCallsSTCTest extends 
StaticTypeCheckingTestCase {
         '''
     }
 
-    void testStaticMethodCallThroughInstance() {
+    // GROOVY-11694
+    void testStaticMethodCallWithInheritance2() {
         assertScript '''
-            A a = new A()
-            String echo = a.echo 'echo'
-            assert echo == 'echo'
+            class D extends C {
+                def m() { protect() }
+            }
+            assert new D().m() != null
         '''
     }
 
@@ -2067,7 +2077,9 @@ class MethodCallsSTCTest extends 
StaticTypeCheckingTestCase {
         T[] identity(T... args) { args }
     }
 
-    static class MyMethodCallTestClass3 extends MyMethodCallTestClass2<String> 
{}
+    static class MyMethodCallTestClass3 extends MyMethodCallTestClass2<String> 
{
+        protected static String protect() { '' }
+    }
 
     static class GroovyPage {
         final void printHtmlPart(int partNumber) {}

Reply via email to