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