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 <eric.mil...@thomsonreuters.com>
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);
     }
 }

Reply via email to