This is an automated email from the ASF dual-hosted git repository.
emilles 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 899f8d8841 GROOVY-11366: STC: implicit-`this` closure field call (pt.2)
899f8d8841 is described below
commit 899f8d8841ed636dc82c6c82346ebec362bef11a
Author: Eric Milles <[email protected]>
AuthorDate: Wed Sep 11 12:35:14 2024 -0500
GROOVY-11366: STC: implicit-`this` closure field call (pt.2)
---
.../MethodCallExpressionTransformer.java | 122 ++++++++++-----------
.../StaticMethodCallExpressionTransformer.java | 10 +-
2 files changed, 61 insertions(+), 71 deletions(-)
diff --git
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
index 9360c271aa..095055b191 100644
---
a/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
+++
b/src/main/java/org/codehaus/groovy/transform/sc/transformers/MethodCallExpressionTransformer.java
@@ -18,12 +18,11 @@
*/
package org.codehaus.groovy.transform.sc.transformers;
-import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.ClassNode;
import org.codehaus.groovy.ast.MethodNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.TupleExpression;
import org.codehaus.groovy.ast.expr.VariableExpression;
import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.classgen.asm.MopWriter;
@@ -32,51 +31,77 @@ import
org.codehaus.groovy.transform.stc.ExtensionMethodNode;
import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
import org.codehaus.groovy.transform.stc.StaticTypesMarker;
-import java.util.List;
import java.util.Optional;
+import static org.apache.groovy.ast.tools.ClassNodeUtils.getField;
+import static org.codehaus.groovy.classgen.AsmClassGenerator.argumentSize;
import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
-public class MethodCallExpressionTransformer {
- private static final ClassNode DGM_CLASSNODE =
ClassHelper.make(DefaultGroovyMethods.class);
+class MethodCallExpressionTransformer {
- private final StaticCompilationTransformer staticCompilationTransformer;
+ private final StaticCompilationTransformer scTransformer;
- public MethodCallExpressionTransformer(StaticCompilationTransformer
staticCompilationTransformer) {
- this.staticCompilationTransformer = staticCompilationTransformer;
+ MethodCallExpressionTransformer(final StaticCompilationTransformer
scTransformer) {
+ this.scTransformer = scTransformer;
}
- Expression transformMethodCallExpression(final MethodCallExpression expr) {
- Expression trn = tryTransformIsToCompareIdentity(expr);
- if (trn!=null) {
- return trn;
+ Expression transformMethodCallExpression(final MethodCallExpression mce) {
+ Expression arguments = mce.getArguments();
+
+ // replace call to DefaultGroovyMethods#is(Object,Object) with a
CompareIdentityExpression
+ if (!mce.isSafe() && !mce.isSpreadSafe() &&
isIsExtension(mce.getMethodTarget()) && argumentSize(arguments) == 1) {
+ Expression lhs =
scTransformer.transform(mce.getObjectExpression());
+ Expression rhs = scTransformer.transform(arguments instanceof
TupleExpression ? ((TupleExpression) arguments).getExpression(0) : arguments);
+ Expression cmp = new CompareIdentityExpression(lhs, rhs);
+ cmp.setSourcePosition(mce);
+ return cmp;
}
- var superCallReceiver =
expr.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
+
+ var superCallReceiver =
mce.getNodeMetaData(StaticTypesMarker.SUPER_MOP_METHOD_REQUIRED);
if (superCallReceiver instanceof ClassNode) {
- return
transformMethodCallExpression(transformToMopSuperCall((ClassNode)
superCallReceiver, expr));
+ return
transformMethodCallExpression(transformToMopSuperCall((ClassNode)
superCallReceiver, mce));
}
- if (isCallOnClosure(expr)) {
- var field =
Optional.ofNullable(staticCompilationTransformer.getClassNode()).map(cn ->
cn.getField(expr.getMethodAsString()));
+
+ if (isCallOnClosure(mce)) {
+ var field =
Optional.ofNullable(scTransformer.getClassNode()).map(cn -> getField(cn,
mce.getMethodAsString()));
if (field.isPresent()) {
- MethodCallExpression result = new MethodCallExpression(
+ var closureFieldCall = new MethodCallExpression(
new VariableExpression(field.get()),
"call",
-
staticCompilationTransformer.transform(expr.getArguments())
- );
- result.setImplicitThis(false);
- result.setSourcePosition(expr);
- result.setSafe(expr.isSafe());
- result.setSpreadSafe(expr.isSpreadSafe());
-
result.setMethodTarget(StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS);
- result.copyNodeMetaData(expr);
- return result;
+ scTransformer.transform(arguments));
+ // implicit-this "field(args)" expression has no place for
safe, spread-safe, or type arguments
+ closureFieldCall.setImplicitThis(false);
+
closureFieldCall.setMethodTarget(mce.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET));
+ closureFieldCall.setSourcePosition(mce);
+ closureFieldCall.copyNodeMetaData(mce);
+ return closureFieldCall;
}
}
- return staticCompilationTransformer.superTransform(expr);
+
+ return scTransformer.superTransform(mce);
+ }
+
+
//--------------------------------------------------------------------------
+
+ private static boolean isIsExtension(final MethodNode node) {
+ return node instanceof ExtensionMethodNode // guards null
+ && "is".equals(node.getName())
+ && node.getParameters().length == 1
+ && DefaultGroovyMethods.class.getName().equals(
+ ((ExtensionMethodNode)
node).getExtensionMethodNode().getDeclaringClass().getName());
+ }
+
+ private static boolean isCallOnClosure(final MethodCallExpression expr) {
+ MethodNode target =
expr.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
+ return expr.isImplicitThis()
+ && !"call".equals(expr.getMethodAsString())
+ && (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS
+ || target == StaticTypeCheckingVisitor.CLOSURE_CALL_NO_ARG
+ || target ==
StaticTypeCheckingVisitor.CLOSURE_CALL_ONE_ARG);
}
- private static MethodCallExpression transformToMopSuperCall(final
ClassNode superCallReceiver, final MethodCallExpression expr) {
+ private static MethodCallExpression transformToMopSuperCall(final
ClassNode superType, final MethodCallExpression expr) {
MethodNode mn =
expr.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
String mopName = MopWriter.getMopMethodName(mn, false);
MethodNode direct = new MethodNode(
@@ -87,7 +112,8 @@ public class MethodCallExpressionTransformer {
mn.getExceptions(),
EmptyStatement.INSTANCE
);
- direct.setDeclaringClass(superCallReceiver);
+ direct.setDeclaringClass(superType);
+
MethodCallExpression result = new MethodCallExpression(
new VariableExpression("this"),
mopName,
@@ -100,40 +126,4 @@ public class MethodCallExpressionTransformer {
result.setMethodTarget(direct);
return result;
}
-
- private static boolean isCallOnClosure(final MethodCallExpression expr) {
- MethodNode target =
expr.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET);
- return expr.isImplicitThis()
- && !"call".equals(expr.getMethodAsString())
- && (target == StaticTypeCheckingVisitor.CLOSURE_CALL_VARGS
- || target == StaticTypeCheckingVisitor.CLOSURE_CALL_NO_ARG
- || target ==
StaticTypeCheckingVisitor.CLOSURE_CALL_ONE_ARG);
- }
-
- /**
- * Identifies a method call expression on {@link
DefaultGroovyMethods#is(Object, Object)} and if recognized, transforms it into
a {@link CompareIdentityExpression}.
- * @param call a method call to be transformed
- * @return null if the method call is not DGM#is, or {@link
CompareIdentityExpression}
- */
- private static Expression
tryTransformIsToCompareIdentity(MethodCallExpression call) {
- if (call.isSafe()) return null;
- MethodNode methodTarget = call.getMethodTarget();
- if (methodTarget instanceof ExtensionMethodNode &&
"is".equals(methodTarget.getName()) && methodTarget.getParameters().length==1) {
- methodTarget = ((ExtensionMethodNode)
methodTarget).getExtensionMethodNode();
- ClassNode owner = methodTarget.getDeclaringClass();
- if (DGM_CLASSNODE.equals(owner)) {
- Expression args = call.getArguments();
- if (args instanceof ArgumentListExpression) {
- ArgumentListExpression arguments =
(ArgumentListExpression) args;
- List<Expression> exprs = arguments.getExpressions();
- if (exprs.size() == 1) {
- CompareIdentityExpression cid = new
CompareIdentityExpression(call.getObjectExpression(), exprs.get(0));
- cid.setSourcePosition(call);
- return cid;
- }
- }
- }
- }
- return null;
- }
-}
\ No newline at end of file
+}
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 dfa6ea9642..d2a1d9aeaa 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
@@ -28,10 +28,10 @@ import static
org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_
class StaticMethodCallExpressionTransformer {
- private final StaticCompilationTransformer transformer;
+ private final StaticCompilationTransformer scTransformer;
- StaticMethodCallExpressionTransformer(final StaticCompilationTransformer
sct) {
- transformer = sct;
+ StaticMethodCallExpressionTransformer(final StaticCompilationTransformer
scTransformer) {
+ this.scTransformer = scTransformer;
}
Expression transformStaticMethodCallExpression(final
StaticMethodCallExpression smce) {
@@ -43,9 +43,9 @@ class StaticMethodCallExpressionTransformer {
mce.setSourcePosition(smce);
mce.copyNodeMetaData(smce);
- return transformer.transform(mce);
+ return scTransformer.transform(mce);
}
- return transformer.superTransform(smce);
+ return scTransformer.superTransform(smce);
}
}