You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/11/28 16:45:40 UTC

[groovy] branch master updated: GROOVY-10383: SC: optimize `a !in b`

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 c6b4b79  GROOVY-10383: SC: optimize `a !in b`
c6b4b79 is described below

commit c6b4b79b0c22bac055b275f792aecf6698e000dd
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 27 18:39:26 2021 -0600

    GROOVY-10383: SC: optimize `a !in b`
---
 .../transformers/BinaryExpressionTransformer.java  | 13 +++----
 .../transform/stc/STCnAryExpressionTest.groovy     | 40 ++++++++++++++++++++++
 2 files changed, 47 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
index f1a6de5..5f8907b 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/transformers/BinaryExpressionTransformer.java
@@ -61,7 +61,6 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.classX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
-import static org.codehaus.groovy.ast.tools.GeneralUtils.isNullX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
@@ -115,7 +114,9 @@ public class BinaryExpressionTransformer {
             }
             break;
           case Types.KEYWORD_IN:
-            return transformInOperation(bin);
+            equal = true; //fallthrough
+          case Types.COMPARE_NOT_IN:
+            return transformInOperation(bin, equal);
           case Types.COMPARE_EQUAL:
           case Types.COMPARE_IDENTICAL:
             equal = true; //fallthrough
@@ -226,12 +227,12 @@ public class BinaryExpressionTransformer {
                 pos);
     }
 
-    private Expression transformInOperation(final BinaryExpression bin) {
+    private Expression transformInOperation(final BinaryExpression bin, final boolean in) {
         Expression leftExpression = bin.getLeftExpression();
         Expression rightExpression = bin.getRightExpression();
 
-        // transform "left in right" into "right.isCase(left)"
-        MethodCallExpression call = callX(rightExpression, "isCase", leftExpression);
+        // transform "left [!]in right" into "right.is[Not]Case(left)"
+        MethodCallExpression call = callX(rightExpression, in ? "isCase" : "isNotCase", leftExpression);
         call.setImplicitThis(false); call.setSourcePosition(bin); call.copyNodeMetaData(bin);
         call.setMethodTarget(bin.getNodeMetaData(StaticTypesMarker.DIRECT_METHOD_CALL_TARGET));
         // GROOVY-7473: no null test for simple cases
@@ -245,7 +246,7 @@ public class BinaryExpressionTransformer {
 
         // GROOVY-6137, GROOVY-7473: null safety and one-time evaluation
         call.setObjectExpression(rightExpression = transformRepeatedReference(rightExpression));
-        Expression safe = ternaryX(isNullX( rightExpression ), isNullX( leftExpression ), call);
+        Expression safe = ternaryX(new CompareToNullExpression(rightExpression,true), new CompareToNullExpression(leftExpression,in), call);
         safe.putNodeMetaData("classgen.callback", classgenCallback(call.getObjectExpression()));
         return staticCompilationTransformer.transform(safe);
     }
diff --git a/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy b/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
index 51fe8a4..2d79f8b 100644
--- a/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
+++ b/src/test/groovy/transform/stc/STCnAryExpressionTest.groovy
@@ -172,6 +172,46 @@ class STCnAryExpressionTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-6137, GROOVY-7473, GROOVY-10383
+    void testInOperatorShouldEvaluateOperandsOnce2() {
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            int getA() { i++ }
+            int getB() { j++ }
+
+            assert !(a !in b)
+            assert i == 1
+            assert j == 1
+        '''
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            def getA() { i++; null }
+            def getB() { j++ }
+
+            assert a !in b
+            assert i == 1
+            assert j == 1
+        '''
+        assertScript '''
+            import groovy.transform.Field
+
+            @Field int i = 0
+            @Field int j = 0
+            def getA() { i++ }
+            def getB() { j++; null }
+
+            assert a !in b
+            assert i == 1
+            assert j == 1
+        '''
+    }
+
     void testComparisonOperatorCheckWithIncompatibleTypesOkIfComparableNotImplemented() {
         shouldFailWithMessages '''
             [] < 1