This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_5_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
The following commit(s) were added to refs/heads/GROOVY_5_0_X by this push:
new 920970323e GROOVY-11817: SC: dynamic property or method call keeps
method static
920970323e is described below
commit 920970323efc35c46dec6ec8bfbeabac80bdb969
Author: Eric Milles <[email protected]>
AuthorDate: Mon Dec 15 11:11:42 2025 -0600
GROOVY-11817: SC: dynamic property or method call keeps method static
- prevent static invocation writer and dynamic call site writer error
5_0_X backport
---
.../groovy/classgen/AsmClassGenerator.java | 11 +++---
.../groovy/classgen/asm/DelegatingController.java | 6 ++++
.../groovy/classgen/asm/WriterController.java | 5 +++
.../classgen/asm/sc/StaticInvocationWriter.java | 7 ++--
.../asm/sc/StaticTypesWriterController.java | 15 +++++---
.../transform/stc/StaticTypeCheckingVisitor.java | 4 +--
.../asm/sc/MixedModeStaticCompilationTest.groovy | 40 ++++++++++++++++++----
7 files changed, 66 insertions(+), 22 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index fe6acf45bf..8f2b726614 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -97,6 +97,7 @@ import org.codehaus.groovy.ast.stmt.WhileStatement;
import org.codehaus.groovy.ast.tools.WideningCategories;
import org.codehaus.groovy.classgen.asm.BytecodeHelper;
import org.codehaus.groovy.classgen.asm.BytecodeVariable;
+import org.codehaus.groovy.classgen.asm.CallSiteWriter;
import org.codehaus.groovy.classgen.asm.CompileStack;
import org.codehaus.groovy.classgen.asm.MethodCaller;
import org.codehaus.groovy.classgen.asm.MethodCallerMultiAdapter;
@@ -1185,12 +1186,14 @@ public class AsmClassGenerator extends ClassGenerator {
return;
}
- if (adapter == getGroovyObjectProperty && propertyName != null &&
!pexp.isSpreadSafe()) { // TODO: spread safe should be handled by each
-
controller.getCallSiteWriter().makeGroovyObjectGetPropertySite(objectExpression,
propertyName, pexp.isSafe(), pexp.isImplicitThis());
+ CallSiteWriter callSiteWriter = controller.getCallSiteWriterFor(pexp);
// GROOVY-11817
+
+ if (adapter == getGroovyObjectProperty && propertyName != null &&
!pexp.isSpreadSafe()) { // TODO: propagate spread safe
+ callSiteWriter.makeGroovyObjectGetPropertySite(objectExpression,
propertyName, pexp.isSafe(), pexp.isImplicitThis());
} else if (adapter == getProperty && propertyName != null &&
!pexp.isSpreadSafe()) {
-
controller.getCallSiteWriter().makeGetPropertySite(objectExpression,
propertyName, pexp.isSafe(), pexp.isImplicitThis());
+ callSiteWriter.makeGetPropertySite(objectExpression, propertyName,
pexp.isSafe(), pexp.isImplicitThis());
} else {
-
controller.getCallSiteWriter().fallbackAttributeOrPropertySite(pexp,
objectExpression, propertyName, adapter);
+ callSiteWriter.fallbackAttributeOrPropertySite(pexp,
objectExpression, propertyName, adapter);
}
}
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
index 3029237535..031fd27246 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/DelegatingController.java
@@ -22,6 +22,7 @@ import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.InterfaceHelperClassNode;
import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.control.SourceUnit;
@@ -64,6 +65,11 @@ public class DelegatingController extends WriterController {
return delegationController.getCallSiteWriter();
}
+ @Override
+ public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+ return delegationController.getCallSiteWriterFor(expression);
+ }
+
@Override
public StatementWriter getStatementWriter() {
return delegationController.getStatementWriter();
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
index 6c26671836..0968583dd8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/WriterController.java
@@ -23,6 +23,7 @@ import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.InterfaceHelperClassNode;
import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.classgen.asm.indy.IndyBinHelper;
@@ -210,6 +211,10 @@ public class WriterController {
return callSiteWriter;
}
+ public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+ return callSiteWriter;
+ }
+
public ClosureWriter getClosureWriter() {
return closureWriter;
}
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 816df9717a..914ec67217 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
@@ -469,11 +469,8 @@ public class StaticInvocationWriter extends
InvocationWriter {
@Override
public void makeCall(final Expression origin, final Expression receiver,
final Expression message, final Expression arguments, final
MethodCallerMultiAdapter adapter, final boolean safe, final boolean spreadSafe,
final boolean implicitThis) {
if (origin.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION) !=
null) {
- StaticTypesWriterController staticController =
(StaticTypesWriterController) controller;
- if (origin instanceof MethodCallExpression) {
- ((MethodCallExpression) origin).setMethodTarget(null);
- }
- InvocationWriter dynamicInvocationWriter =
staticController.getRegularInvocationWriter();
+ if (origin instanceof MethodCallExpression)
((MethodCallExpression) origin).setMethodTarget(null); // ensure dynamic resolve
+ InvocationWriter dynamicInvocationWriter =
((StaticTypesWriterController) controller).getRegularInvocationWriter();
dynamicInvocationWriter.makeCall(origin, receiver, message,
arguments, adapter, safe, spreadSafe, implicitThis);
return;
}
diff --git
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
index 5a7e216c77..78ceed9196 100644
---
a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
+++
b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesWriterController.java
@@ -21,6 +21,7 @@ package org.codehaus.groovy.classgen.asm.sc;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.ConstructorNode;
import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.classgen.AsmClassGenerator;
import org.codehaus.groovy.classgen.GeneratorContext;
import org.codehaus.groovy.classgen.asm.BinaryExpressionHelper;
@@ -37,10 +38,10 @@ import
org.codehaus.groovy.classgen.asm.UnaryExpressionHelper;
import org.codehaus.groovy.classgen.asm.WriterController;
import
org.codehaus.groovy.classgen.asm.indy.sc.IndyStaticTypesMultiTypeDispatcher;
import org.codehaus.groovy.control.CompilerConfiguration;
-import org.codehaus.groovy.transform.stc.StaticTypesMarker;
import org.objectweb.asm.ClassVisitor;
import static
org.codehaus.groovy.transform.sc.StaticCompilationVisitor.isStaticallyCompiled;
+import static
org.codehaus.groovy.transform.stc.StaticTypesMarker.DYNAMIC_RESOLUTION;
/**
* An alternative {@link org.codehaus.groovy.classgen.asm.WriterController}
which handles static types and method
@@ -103,14 +104,20 @@ public class StaticTypesWriterController extends
DelegatingController {
@Override
public CallSiteWriter getCallSiteWriter() {
- MethodNode methodNode = getMethodNode();
- if (isInStaticallyCheckedMethod && (methodNode == null
- ||
!Boolean.TRUE.equals(methodNode.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION))))
{
+ if (isInStaticallyCheckedMethod) {
return callSiteWriter;
}
return super.getCallSiteWriter();
}
+ @Override
+ public CallSiteWriter getCallSiteWriterFor(final Expression expression) {
+ if (expression.getNodeMetaData(DYNAMIC_RESOLUTION) != null) {
+ return getRegularCallSiteWriter(); // GROOVY-6263
+ }
+ return getCallSiteWriter();
+ }
+
public CallSiteWriter getRegularCallSiteWriter() {
return super.getCallSiteWriter();
}
diff --git
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index bf4451ecae..a1ef0d5107 100644
---
a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++
b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -739,7 +739,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
PropertyExpression pexp = thisPropX(true, dynName);
if (existsProperty(pexp,
!typeCheckingContext.isTargetOfEnclosingAssignment(vexp))) {
vexp.copyNodeMetaData(pexp.getObjectExpression());
- for (Object key : new Object[]{IMPLICIT_RECEIVER,
READONLY_PROPERTY, PV_FIELDS_ACCESS, PV_FIELDS_MUTATION,
DIRECT_METHOD_CALL_TARGET}) {
+ for (Object key : new Object[]{DIRECT_METHOD_CALL_TARGET,
DYNAMIC_RESOLUTION, IMPLICIT_RECEIVER, PV_FIELDS_ACCESS, PV_FIELDS_MUTATION,
READONLY_PROPERTY}) {
vexp.putNodeMetaData(key, pexp.getNodeMetaData(key));
}
ClassNode type = pexp.getNodeMetaData(INFERRED_TYPE);
@@ -748,7 +748,7 @@ public class StaticTypeCheckingVisitor extends
ClassCodeVisitorSupport {
}
if (type == null) type = OBJECT_TYPE;
vexp.putNodeMetaData(INFERRED_TYPE, type); // GROOVY-11007
- String receiver = vexp.getNodeMetaData(IMPLICIT_RECEIVER);
+ String receiver = pexp.getNodeMetaData(IMPLICIT_RECEIVER);
Boolean dynamic = pexp.getNodeMetaData(DYNAMIC_RESOLUTION);
// GROOVY-7701, GROOVY-7996: correct false assumption made by
VariableScopeVisitor
if (((receiver != null && !receiver.endsWith("owner")) ||
Boolean.TRUE.equals(dynamic))
diff --git
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
index db6a514c57..3a9b0e59c8 100644
---
a/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
+++
b/src/test/groovy/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
@@ -186,7 +186,7 @@ final class MixedModeStaticCompilationTest extends
StaticTypeCheckingTestCase im
'''
}
- void testAllowMetaClass() {
+ void testMetaClassUsage() {
assertScript '''
@CompileStatic(extensions='groovy/transform/sc/MixedMode.groovy')
void test() {
@@ -204,23 +204,49 @@ final class MixedModeStaticCompilationTest extends
StaticTypeCheckingTestCase im
'''
}
- void testRecognizeStaticMethodCall() {
+ void testDynamicClassMethod1() {
assertScript '''
@CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
Map<String, Integer> foo() {
String.map()
}
+ try {
+ String.metaClass.static.map = { -> [a:1,b:2] }
+ assert foo().values().sort() == [1,2]
+ } finally {
+ GroovySystem.getMetaClassRegistry().removeMetaClass(String)
+ }
+ '''
+ }
+
+ void testDynamicClassMethod2() {
+ assertScript '''
@CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
- List<Integer> bar() {
+ List<Integer> foo() {
Date.list()
}
try {
- String.metaClass.static.map = { [a: 1, b:2 ]}
- Date.metaClass.static.list = { [1,2] }
- assert foo().values().sort() == bar()
+ Date.metaClass.static.list = { -> [1,2] }
+ assert foo() == [1,2]
+ } finally {
+ GroovySystem.getMetaClassRegistry().removeMetaClass(Date)
+ }
+ '''
+ }
+
+ // GROOVY-11817
+ void testDynamicClassMethod3() {
+ assertScript '''
+ @CompileStatic(extensions='groovy/transform/sc/MixedMode2.groovy')
+ def foo() {
+ def list_of_integer = Date.list()
+ def integer = list_of_integer[0]
+ }
+ try {
+ Date.metaClass.static.list = { -> [1,2] }
+ assert foo() == 1
} finally {
GroovySystem.getMetaClassRegistry().removeMetaClass(Date)
- GroovySystem.getMetaClassRegistry().removeMetaClass(String)
}
'''
}