You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/02/24 19:37:28 UTC

[groovy] branch GROOVY_2_5_X updated (8f27d7f -> 3a459ed)

This is an automated email from the ASF dual-hosted git repository.

emilles pushed a change to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from 8f27d7f  GROOVY-10509: Bump log4j2 version to 2.12.4 (test dependency - fixed JDK7 version)
     new 99c7134  GROOVY-9385: add private field accessor for each mutated private field
     new f758591  GROOVY-9328: add outer class accessors to all outer classes
     new 29d454c  GROOVY-9327: handle STC for AIC in non-STC class but STC method
     new d9356fe  GROOVY-8707: SC: use makeSetProperty for compound assignment of property
     new 1e247be  GROOVY-7304: handle private field access from closure for ++x and x++
     new 3a459ed  GROOVY-6851, GROOVY-10104: SC: skip Verifier-generated methods

The 6 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 ...icTypesBinaryExpressionMultiTypeDispatcher.java |  33 +++++
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  53 +++++---
 .../transform/sc/StaticCompilationVisitor.java     | 113 ++++++++++-------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 126 +++++++++++--------
 src/test/gls/invocation/DefaultParamTest.groovy    |  23 ++++
 .../bugs/{Groovy8446.groovy => Groovy9327.groovy}  |  41 +++---
 .../stc/AnonymousInnerClassSTCTest.groovy          |   5 +-
 .../groovy/transform/stc/STCAssignmentTest.groovy  |  88 +++++++++++--
 .../asm/sc/AssignmentsStaticCompileTest.groovy     |  11 +-
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   |   8 --
 .../sc/FieldsAndPropertiesStaticCompileTest.groovy |  14 ++-
 .../asm/sc/MixedModeStaticCompilationTest.groovy   |  45 +++++--
 .../classgen/asm/sc/bugs/Groovy7276Bug.groovy      | 139 ++++++++++++++-------
 13 files changed, 489 insertions(+), 210 deletions(-)
 copy src/test/groovy/bugs/{Groovy8446.groovy => Groovy9327.groovy} (61%)

[groovy] 04/06: GROOVY-8707: SC: use makeSetProperty for compound assignment of property

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit d9356fe5952a65d1bba398742c049e4f5ab5e656
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 13 13:58:54 2020 -0600

    GROOVY-8707: SC: use makeSetProperty for compound assignment of property
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
---
 ...icTypesBinaryExpressionMultiTypeDispatcher.java | 33 ++++++++++++++++++++++
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 15 ++++++++++
 .../asm/sc/AssignmentsStaticCompileTest.groovy     | 11 ++++++--
 3 files changed, 57 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
index 7cbb3e6..e98d4a7 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesBinaryExpressionMultiTypeDispatcher.java
@@ -50,6 +50,7 @@ import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
 import org.codehaus.groovy.classgen.asm.WriterController;
 import org.codehaus.groovy.runtime.MetaClassHelper;
 import org.codehaus.groovy.syntax.Token;
+import org.codehaus.groovy.syntax.TokenUtil;
 import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.sc.StaticCompilationVisitor;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
@@ -131,6 +132,38 @@ public class StaticTypesBinaryExpressionMultiTypeDispatcher extends BinaryExpres
     }
 
     @Override
+    protected void evaluateBinaryExpressionWithAssignment(final String method, final BinaryExpression expression) {
+        Expression leftExpression = expression.getLeftExpression();
+        if (leftExpression instanceof PropertyExpression) {
+            PropertyExpression pexp = (PropertyExpression) leftExpression;
+
+            BinaryExpression expressionWithoutAssignment = new BinaryExpression(
+                    leftExpression,
+                    Token.newSymbol(
+                            TokenUtil.removeAssignment(expression.getOperation().getType()),
+                            expression.getOperation().getStartLine(),
+                            expression.getOperation().getStartColumn()
+                    ),
+                    expression.getRightExpression()
+            );
+            expressionWithoutAssignment.copyNodeMetaData(expression);
+            expressionWithoutAssignment.setSourcePosition(expression);
+
+            if (makeSetProperty(
+                    pexp.getObjectExpression(),
+                    pexp.getProperty(),
+                    expressionWithoutAssignment,
+                    pexp.isSafe(),
+                    pexp.isSpreadSafe(),
+                    pexp.isImplicitThis(),
+                    pexp instanceof AttributeExpression)) {
+                return;
+            }
+        }
+        super.evaluateBinaryExpressionWithAssignment(method, expression);
+    }
+
+    @Override
     public void evaluateEqual(final BinaryExpression expression, final boolean defineVariable) {
         if (!defineVariable) {
             Expression leftExpression = expression.getLeftExpression();
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index 3649342..10ec5a7 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -138,6 +138,21 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         """
     }
 
+    void testPlusEqualsOnProperty() {
+        assertScript '''
+            class C {
+                int i
+
+                static main(args) {
+                    def c = new C()
+                    c.i = 5
+                    c.i += 10
+                    assert c.i == 15
+                }
+            }
+        '''
+    }
+
     // GROOVY-9385
     void testPlusEqualsOnPrivateField() {
         assertScript '''
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
index 24b2f73..538589f 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/AssignmentsStaticCompileTest.groovy
@@ -21,7 +21,14 @@ package org.codehaus.groovy.classgen.asm.sc
 import groovy.transform.stc.STCAssignmentTest
 
 /**
- * Unit tests for static type checking : assignments.
+ * Unit tests for static compilation : assignments.
  */
-class AssignmentsStaticCompileTest extends STCAssignmentTest implements StaticCompilationTestSupport {}
+final class AssignmentsStaticCompileTest extends STCAssignmentTest implements StaticCompilationTestSupport {
 
+    @Override // GROOVY-8707
+    void testPlusEqualsOnProperty() {
+        super.testPlusEqualsOnProperty()
+        String bytecode = astTrees['C'][1]
+        assert !bytecode.contains('ScriptBytecodeAdapter.setGroovyObjectProperty') : '"c.i += 10" should use setter, not dynamic property'
+    }
+}

[groovy] 01/06: GROOVY-9385: add private field accessor for each mutated private field

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 99c71343affedc03a7f21f1cbea81faec2881679
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Feb 5 15:24:57 2020 -0600

    GROOVY-9385: add private field accessor for each mutated private field
    
    (cherry picked from commit 4999bbcb5f41dbd604aad529130a8b3d16637fd4)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
    	src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
---
 .../transform/sc/StaticCompilationVisitor.java     | 41 ++++++++----
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 73 ++++++++++++++++++----
 .../sc/FieldsAndPropertiesStaticCompileTest.groovy | 14 +++--
 3 files changed, 99 insertions(+), 29 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index bca426e..18a4801 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -60,10 +60,10 @@ import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingVisitor;
-import org.codehaus.groovy.transform.stc.StaticTypesMarker;
 
 import java.util.ArrayList;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -79,11 +79,19 @@ import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.BINARY_EXP_TARGET;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.COMPONENT_TYPE;
+import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PRIVATE_BRIDGE_METHODS;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PRIVATE_FIELDS_ACCESSORS;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PRIVATE_FIELDS_MUTATORS;
+import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.PROPERTY_OWNER;
+import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.STATIC_COMPILE_NODE;
 import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DIRECT_METHOD_CALL_TARGET;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.DYNAMIC_RESOLUTION;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.INITIAL_EXPRESSION;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PV_FIELDS_ACCESS;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PV_FIELDS_MUTATION;
+import static org.codehaus.groovy.transform.stc.StaticTypesMarker.PV_METHODS_ACCESS;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 import static org.objectweb.asm.Opcodes.ACC_STATIC;
 import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
@@ -148,8 +156,8 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
 
     private void addDynamicOuterClassAccessorsCallback(final ClassNode outer) {
         if (outer != null && !isStaticallyCompiled(outer)
-                && outer.getNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK) == null) {
-            outer.putNodeMetaData(StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK, new CompilationUnit.PrimaryClassNodeOperation() {
+                && outer.getNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK) == null) {
+            outer.putNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK, new CompilationUnit.PrimaryClassNodeOperation() {
                 @Override
                 public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
                     if (classNode == outer) {
@@ -236,15 +244,24 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
      * Adds special accessors and mutators for private fields so that inner classes can get/set them
      */
     private static void addPrivateFieldsAccessors(ClassNode node) {
-        Set<ASTNode> accessedFields = (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_FIELDS_ACCESS);
-        Set<ASTNode> mutatedFields = (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_FIELDS_MUTATION);
-        if (accessedFields == null && mutatedFields == null) return;
         Map<String, MethodNode> privateFieldAccessors = (Map<String, MethodNode>) node.getNodeMetaData(PRIVATE_FIELDS_ACCESSORS);
         Map<String, MethodNode> privateFieldMutators = (Map<String, MethodNode>) node.getNodeMetaData(PRIVATE_FIELDS_MUTATORS);
         if (privateFieldAccessors != null || privateFieldMutators != null) {
             // already added
             return;
         }
+        Set<ASTNode> accessedFields = node.getNodeMetaData(PV_FIELDS_ACCESS);
+        Set<ASTNode> mutatedFields = node.getNodeMetaData(PV_FIELDS_MUTATION);
+        if (accessedFields == null && mutatedFields == null) return;
+        // GROOVY-9385: mutation includes access in case of compound assignment or pre/post-increment/decrement
+        if (mutatedFields != null) {
+            if (accessedFields != null) {
+                accessedFields = new HashSet<>(accessedFields); accessedFields.addAll(mutatedFields);
+            } else {
+                accessedFields = mutatedFields;
+            }
+        }
+
         int acc = -1;
         privateFieldAccessors = accessedFields != null ? new HashMap<String, MethodNode>() : null;
         privateFieldMutators = mutatedFields != null ? new HashMap<String, MethodNode>() : null;
@@ -292,7 +309,7 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
      * @param node an inner/outer class node for which to generate bridge methods
      */
     private static void addPrivateBridgeMethods(final ClassNode node) {
-        Set<ASTNode> accessedMethods = (Set<ASTNode>) node.getNodeMetaData(StaticTypesMarker.PV_METHODS_ACCESS);
+        Set<ASTNode> accessedMethods = (Set<ASTNode>) node.getNodeMetaData(PV_METHODS_ACCESS);
         if (accessedMethods==null) return;
         List<MethodNode> methods = new ArrayList<MethodNode>(node.getAllDeclaredMethods());
         methods.addAll(node.getDeclaredConstructors());
@@ -389,7 +406,7 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
         // add node metadata for default parameters because they are erased by the Verifier
         if (node.getParameters()!=null) {
             for (Parameter parameter : node.getParameters()) {
-                parameter.putNodeMetaData(StaticTypesMarker.INITIAL_EXPRESSION, parameter.getInitialExpression());
+                parameter.putNodeMetaData(INITIAL_EXPRESSION, parameter.getInitialExpression());
             }
         }
     }
@@ -534,8 +551,8 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
         boolean exists = super.existsProperty(pexp, checkForReadOnly, receiverMemoizer);
         if (exists) {
             objectExpressionType = rType.get();
-            if (objectExpression.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER) == null) {
-                objectExpression.putNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER, objectExpressionType);
+            if (objectExpression.getNodeMetaData(PROPERTY_OWNER) == null) {
+                objectExpression.putNodeMetaData(PROPERTY_OWNER, objectExpressionType);
             }
             if (StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf(objectExpressionType, ClassHelper.LIST_TYPE)) {
                 objectExpression.putNodeMetaData(COMPONENT_TYPE, inferComponentType(objectExpressionType, ClassHelper.int_TYPE));
@@ -547,9 +564,9 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
     @Override
     public void visitPropertyExpression(final PropertyExpression pexp) {
         super.visitPropertyExpression(pexp);
-        Object dynamic = pexp.getNodeMetaData(StaticTypesMarker.DYNAMIC_RESOLUTION);
+        Object dynamic = pexp.getNodeMetaData(DYNAMIC_RESOLUTION);
         if (dynamic != null) {
-            pexp.getObjectExpression().putNodeMetaData(StaticCompilationMetadataKeys.RECEIVER_OF_DYNAMIC_PROPERTY, dynamic);
+            pexp.getObjectExpression().putNodeMetaData(RECEIVER_OF_DYNAMIC_PROPERTY, dynamic);
         }
     }
 }
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index 7d63cb6..3649342 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -138,6 +138,54 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         """
     }
 
+    // GROOVY-9385
+    void testPlusEqualsOnPrivateField() {
+        assertScript '''
+            class C {
+                private int i
+
+                int test() {
+                    { ->
+                        i += 1
+                    }.call()
+                }
+            }
+            assert new C().test() == 1
+        '''
+    }
+
+    // GROOVY-9385
+    void testPrefixPlusPlusOnPrivateField() {
+        assertScript '''
+            class C {
+                private int i
+
+                int test() {
+                    { ->
+                        ++i
+                    }.call()
+                }
+            }
+            assert new C().test() == 1
+        '''
+    }
+
+    // GROOVY-9385
+    void testPostfixPlusPlusOnPrivateField() {
+        assertScript '''
+            class C {
+                private int i
+
+                int test() {
+                    { ->
+                        i++
+                    }.call()
+                }
+            }
+            assert new C().test() == 0
+        '''
+    }
+
     void testPossibleLooseOfPrecision() {
         shouldFailWithMessages '''
             long a = Long.MAX_VALUE
@@ -210,7 +258,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
             float f = (float) 1
         '''
     }
-    
+
     void testCompatibleTypeCast() {
         assertScript '''
         String s = 'Hello'
@@ -420,7 +468,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
             def c = (Character) null
         '''
     }
-    
+
     void testCastObjectToSubclass() {
         assertScript '''
             Object o = null
@@ -664,7 +712,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
             assert m().getClass() == BigDecimal
         '''
     }
-    
+
     void testBigIntegerAssignment() {
         assertScript '''
             BigInteger bigInt = 6666666666666666666666666666666666666
@@ -728,7 +776,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
             assert c.getClass() == BigDecimal
         '''
     }
-    
+
     //GROOVY-6435
     void testBigDecAndBigIntSubclass() {
         assertScript '''
@@ -902,7 +950,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
                 a = new B()
                 a.bbb()
             }
-            assert fooParameterAssignment(null) == 42            
+            assert fooParameterAssignment(null) == 42
         '''
     }
 
@@ -911,7 +959,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         def m() {
             def a  = 1
             Integer[] b = [a]
-        }            
+        }
         '''
     }
 
@@ -920,7 +968,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         def m() {
             def a = new int[5]
             int[][] b = [a]
-        }            
+        }
         '''
     }
 
@@ -930,7 +978,7 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
             def row = ["", "", ""]
             def (left, right) = [row[0], row[1]]
             left.toUpperCase()
-        }            
+        }
         '''
     }
 
@@ -996,9 +1044,9 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         assertScript '''
         interface A1{}
         interface A2 extends A1{}
-        
+
         class C1 implements A1{}
-        
+
         def m(A2 a2) {
             C1 c1 = (C1) a2
         }
@@ -1009,13 +1057,12 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         shouldFailWithMessages '''
         interface A1{}
         interface A2 extends A1{}
-        
+
         final class C1 implements A1{}
-        
+
         def m(A2 a2) {
             C1 c1 = (C1) a2
         }
         ''', "Inconvertible types: cannot cast A2 to C1"
     }
 }
-
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
index 247d7db..5e562e7 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/FieldsAndPropertiesStaticCompileTest.groovy
@@ -815,10 +815,16 @@ final class FieldsAndPropertiesStaticCompileTest extends FieldsAndPropertiesSTCT
                 new A().test()
             '''
         } finally {
-            assert !astTrees['A'][1].contains('pfaccess$00') // no mutator bridge method for 'accessed'
-            assert !astTrees['A'][1].contains('pfaccess$1') // no accessor bridge method for 'mutated'
-            assert astTrees['A$_closure1'][1].contains('INVOKESTATIC A.pfaccess$2 (LA;)Ljava/lang/String;')
-            assert astTrees['A$_closure1'][1].contains('INVOKESTATIC A.pfaccess$02 (LA;Ljava/lang/String;)Ljava/lang/String;')
+            def dump = astTrees['A'][1]
+            assert dump.contains('pfaccess$0') // accessor bridge method for 'accessed'
+            assert !dump.contains('pfaccess$00') // no mutator bridge method for 'accessed'
+            assert dump.contains('pfaccess$01') // mutator bridge method for 'mutated'
+            assert dump.contains('pfaccess$1') // accessor bridge method for 'mutated' -- GROOVY-9385
+            assert dump.contains('pfaccess$2') // accessor bridge method for 'accessedAndMutated'
+            assert dump.contains('pfaccess$02') // mutator bridge method for 'accessedAndMutated'
+            dump = astTrees['A$_closure1'][1]
+            assert dump.contains('INVOKESTATIC A.pfaccess$2 (LA;)Ljava/lang/String;')
+            assert dump.contains('INVOKESTATIC A.pfaccess$02 (LA;Ljava/lang/String;)Ljava/lang/String;')
         }
     }
 

[groovy] 02/06: GROOVY-9328: add outer class accessors to all outer classes

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit f7585917620f88c9cb0d80486c81d24e18ffd827
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Dec 10 12:06:42 2019 -0600

    GROOVY-9328: add outer class accessors to all outer classes
    
    (cherry picked from commit 2c06560a7bd7d8d716867e43e92e7a7eb9fa5e90)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
---
 .../transform/sc/StaticCompilationVisitor.java     | 24 ++++++------
 .../asm/sc/MixedModeStaticCompilationTest.groovy   | 45 ++++++++++++++++++----
 2 files changed, 50 insertions(+), 19 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index 18a4801..b90cd8d 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -55,7 +55,6 @@ import org.codehaus.groovy.classgen.asm.TypeChooser;
 import org.codehaus.groovy.classgen.asm.WriterControllerFactory;
 import org.codehaus.groovy.classgen.asm.sc.StaticCompilationMopWriter;
 import org.codehaus.groovy.classgen.asm.sc.StaticTypesTypeChooser;
-import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport;
@@ -155,17 +154,20 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
     }
 
     private void addDynamicOuterClassAccessorsCallback(final ClassNode outer) {
-        if (outer != null && !isStaticallyCompiled(outer)
-                && outer.getNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK) == null) {
-            outer.putNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK, new CompilationUnit.PrimaryClassNodeOperation() {
-                @Override
-                public void call(SourceUnit source, GeneratorContext context, ClassNode classNode) throws CompilationFailedException {
-                    if (classNode == outer) {
-                        addPrivateBridgeMethods(classNode);
-                        addPrivateFieldsAccessors(classNode);
+        if (outer != null) {
+            if (!isStaticallyCompiled(outer) && outer.getNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK) == null) {
+                outer.putNodeMetaData(DYNAMIC_OUTER_NODE_CALLBACK, new CompilationUnit.PrimaryClassNodeOperation() {
+                    @Override
+                    public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) {
+                        if (classNode == outer) {
+                            addPrivateBridgeMethods(classNode);
+                            addPrivateFieldsAccessors(classNode);
+                        }
                     }
-                }
-            });
+                });
+            }
+            // GROOVY-9328: apply to outer classes
+            addDynamicOuterClassAccessorsCallback(outer.getOuterClass());
         }
     }
 
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
index 36b9a9f..0de8d56 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/MixedModeStaticCompilationTest.groovy
@@ -21,14 +21,11 @@ package org.codehaus.groovy.classgen.asm.sc
 import groovy.transform.stc.StaticTypeCheckingTestCase
 import org.codehaus.groovy.control.customizers.ASTTransformationCustomizer
 
-class MixedModeStaticCompilationTest extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+final class MixedModeStaticCompilationTest extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+
     @Override
     protected void setUp() {
         super.setUp()
-        removeCustomizer()
-    }
-
-    private void removeCustomizer() {
         def customizers = config.compilationCustomizers
         customizers.removeAll { it instanceof ASTTransformationCustomizer }
     }
@@ -366,6 +363,21 @@ class MixedModeStaticCompilationTest extends StaticTypeCheckingTestCase implemen
             }
             assert new Test().strInSCInner() == 'hi'
         '''
+
+        // GROOVY-9328
+        assertScript '''
+            class Test {
+                private String str() { 'hi' }
+
+                class Inner {
+                    @groovy.transform.CompileStatic
+                    String outerStr() { str() }
+                }
+
+                String strInSCInner() { new Inner().outerStr() }
+            }
+            assert new Test().strInSCInner() == 'hi'
+        '''
     }
 
     void testSCAICCanAccessPrivateFieldsOfNonSCOuterClass() {
@@ -391,9 +403,26 @@ class MixedModeStaticCompilationTest extends StaticTypeCheckingTestCase implemen
 
                 @groovy.transform.CompileStatic
                 String strInSCAIC() {
-                    new Object() {
-                        String outerStr() { str() }
-                    }.outerStr()
+                    def callable = new java.util.concurrent.Callable<String>() {
+                        @Override String call() { str() }
+                    }
+                    callable.call()
+                }
+            }
+            assert new Test().strInSCAIC() == 'hi'
+        '''
+
+        // GROOVY-9328
+        assertScript '''
+            class Test {
+                private String str() { 'hi' }
+
+                def strInSCAIC() {
+                    def callable = new java.util.concurrent.Callable<String>() {
+                        @groovy.transform.CompileStatic
+                        @Override String call() { str() }
+                    }
+                    callable.call()
                 }
             }
             assert new Test().strInSCAIC() == 'hi'

[groovy] 03/06: GROOVY-9327: handle STC for AIC in non-STC class but STC method

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 29d454c1bb065ffe3cb3bfe5cf1e790e559daec2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Dec 23 13:35:55 2019 -0600

    GROOVY-9327: handle STC for AIC in non-STC class but STC method
    
    (cherry picked from commit 44893abc65656fa45f468e970da2964fd181a0ef)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/sc/StaticCompilationVisitor.java     | 13 +++--
 .../transform/stc/StaticTypeCheckingVisitor.java   | 17 +++++-
 src/test/groovy/bugs/Groovy9327.groovy             | 60 ++++++++++++++++++++++
 .../stc/AnonymousInnerClassSTCTest.groovy          |  5 +-
 4 files changed, 89 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index b90cd8d..e48b3d7 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -437,11 +437,18 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
     public void visitConstructorCallExpression(final ConstructorCallExpression call) {
         super.visitConstructorCallExpression(call);
 
+        // GROOVY-9327: propagate compilation disposition to anon. inner class
+        if (call.isUsingAnonymousInnerClass() && call.getType().getNodeMetaData(StaticTypeCheckingVisitor.class) != null) {
+            ClassNode anonType = call.getType();
+            anonType.putNodeMetaData(STATIC_COMPILE_NODE, anonType.getEnclosingMethod().getNodeMetaData(STATIC_COMPILE_NODE));
+            anonType.putNodeMetaData(WriterControllerFactory.class, anonType.getOuterClass().getNodeMetaData(WriterControllerFactory.class));
+        }
+
         MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
-        if (target==null && call.getLineNumber()>0) {
+        if (target == null && call.getLineNumber() > 0) {
             addError("Target constructor for constructor call expression hasn't been set", call);
         } else {
-            if (target==null) {
+            if (target == null) {
                 // try to find a target
                 ArgumentListExpression argumentListExpression = InvocationWriter.makeArgumentList(call.getArguments());
                 List<Expression> expressions = argumentListExpression.getExpressions();
@@ -454,7 +461,7 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
                 target = constructor;
             }
         }
-        if (target!=null) {
+        if (target != null) {
             memorizeInitialExpressions(target);
         }
     }
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 695b69f..d16bdfe 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -430,7 +430,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected boolean shouldSkipClassNode(final ClassNode node) {
-        return isSkipMode(node);
+        return Boolean.TRUE.equals(node.getNodeMetaData(StaticTypeCheckingVisitor.class)) || isSkipMode(node);
     }
 
     public boolean isSkipMode(final AnnotatedNode node) {
@@ -2232,6 +2232,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     visitMethodCallArguments(receiver, argumentList, true, node);
                 }
             }
+
+            // GROOVY-9327: check for AIC in STC method with non-STC enclosing class
+            if (call.isUsingAnonymousInnerClass()) {
+                Set<MethodNode> methods = typeCheckingContext.methodsToBeVisited;
+                if (!methods.isEmpty()) { // indicates specific methods have STC
+                    typeCheckingContext.methodsToBeVisited = Collections.emptySet();
+
+                    ClassNode anonType = call.getType();
+                    visitClass(anonType); // visit anon. inner class inline with method
+                    anonType.putNodeMetaData(StaticTypeCheckingVisitor.class, Boolean.TRUE);
+
+                    typeCheckingContext.methodsToBeVisited = methods;
+                }
+            }
+
             extension.afterMethodCall(call);
         } finally {
             typeCheckingContext.popEnclosingConstructorCall();
diff --git a/src/test/groovy/bugs/Groovy9327.groovy b/src/test/groovy/bugs/Groovy9327.groovy
new file mode 100644
index 0000000..7112f3f
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9327.groovy
@@ -0,0 +1,60 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy9327 {
+
+    @Test
+    void testCheckedAIC() {
+        def err = shouldFail '''
+        @groovy.transform.TypeChecked
+        void test() {
+            def runner = new Runnable() {
+                @Override
+                void run() {
+                    unknownReference
+                }
+            }
+        }
+        '''
+        assert err.message.contains('The variable [unknownReference] is undeclared.')
+    }
+
+    @Test
+    void testCompiledAIC() {
+        def err = shouldFail '''
+        @groovy.transform.CompileStatic
+        void test() {
+            def runner = new Runnable() {
+                @Override
+                void run() {
+                    unknownReference
+                }
+            }
+        }
+        '''
+        assert err.message.contains('The variable [unknownReference] is undeclared.')
+    }
+}
diff --git a/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy b/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
index ab1bb2e..822a712 100644
--- a/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
+++ b/src/test/groovy/transform/stc/AnonymousInnerClassSTCTest.groovy
@@ -151,9 +151,10 @@ class AnonymousInnerClassSTCTest extends StaticTypeCheckingTestCase {
                   }
                 }
                 s.size()
-            }'''
+            }
+        '''
     }
-    
+
     void testAICInAICInStaticMethod() {
         assertScript '''
             class A {

[groovy] 05/06: GROOVY-7304: handle private field access from closure for ++x and x++

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 1e247beccd3b6a0efc7f102c6bd35041487e5e1b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Feb 24 12:54:25 2022 -0600

    GROOVY-7304: handle private field access from closure for ++x and x++
    
    (cherry picked from commit b5c80ae6e66bb2add1722fb1256be490959a7696)
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
    	src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
---
 .../classgen/asm/sc/StaticTypesCallSiteWriter.java |  53 +++++---
 .../transform/sc/StaticCompilationVisitor.java     |  24 ++--
 .../transform/stc/StaticTypeCheckingVisitor.java   |  90 ++++++++-----
 .../classgen/asm/sc/bugs/Groovy7276Bug.groovy      | 139 ++++++++++++++-------
 4 files changed, 202 insertions(+), 104 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
index 472f9d6..cec4416 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/sc/StaticTypesCallSiteWriter.java
@@ -19,6 +19,7 @@
 package org.codehaus.groovy.classgen.asm.sc;
 
 import org.apache.groovy.ast.tools.ClassNodeUtils;
+import org.apache.groovy.ast.tools.ExpressionUtils;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.ASTNode;
 import org.codehaus.groovy.ast.ClassHelper;
@@ -46,6 +47,7 @@ import org.codehaus.groovy.classgen.asm.CompileStack;
 import org.codehaus.groovy.classgen.asm.MethodCallerMultiAdapter;
 import org.codehaus.groovy.classgen.asm.OperandStack;
 import org.codehaus.groovy.classgen.asm.TypeChooser;
+import org.codehaus.groovy.classgen.asm.VariableSlotLoader;
 import org.codehaus.groovy.runtime.InvokerHelper;
 import org.codehaus.groovy.runtime.MetaClassHelper;
 import org.codehaus.groovy.syntax.SyntaxException;
@@ -87,6 +89,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.chooseBestMethod;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.findDGMMethodsByNameAndArguments;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
@@ -795,17 +798,41 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
     }
 
     @Override
-    public void fallbackAttributeOrPropertySite(PropertyExpression expression, Expression objectExpression, String name, MethodCallerMultiAdapter adapter) {
-        if (name!=null &&
-            (adapter == AsmClassGenerator.setField || adapter == AsmClassGenerator.setGroovyObjectField)
-        ) {
-            TypeChooser typeChooser = controller.getTypeChooser();
+    public void fallbackAttributeOrPropertySite(final PropertyExpression expression, final Expression objectExpression, final String name, final MethodCallerMultiAdapter adapter) {
+        CompileStack compileStack = controller.getCompileStack();
+        OperandStack operandStack = controller.getOperandStack();
+
+        if (name != null && compileStack.isLHS()) {
             ClassNode classNode = controller.getClassNode();
-            ClassNode rType = typeChooser.resolveType(objectExpression, classNode);
-            if (controller.getCompileStack().isLHS()) {
-                if (setField(expression, objectExpression, rType, name)) return;
-            } else {
-                if (getField(expression, objectExpression, rType, name)) return;
+            ClassNode receiverType = controller.getTypeChooser().resolveType(objectExpression, classNode);
+            if (adapter == AsmClassGenerator.setField || adapter == AsmClassGenerator.setGroovyObjectField) {
+                if (setField(expression, objectExpression, receiverType, name)) return;
+            }
+            if (ExpressionUtils.isThisExpression(objectExpression)) {
+                FieldNode fieldNode = receiverType.getField(name);
+                if (fieldNode != null && fieldNode.isPrivate() && !receiverType.equals(classNode)
+                        && StaticInvocationWriter.isPrivateBridgeMethodsCallAllowed(receiverType, classNode)) {
+                    Map<String, MethodNode> mutators = receiverType.redirect().getNodeMetaData(StaticCompilationMetadataKeys.PRIVATE_FIELDS_MUTATORS);
+                    if (mutators != null) {
+                        MethodNode methodNode = mutators.get(name);
+                        if (methodNode != null) {
+                            ClassNode rhsType = operandStack.getTopOperand();
+                            int i = compileStack.defineTemporaryVariable("$rhsValue", rhsType, true);
+                            VariableSlotLoader rhsValue = new VariableSlotLoader(rhsType, i, operandStack);
+
+                            MethodCallExpression call = callX(objectExpression, methodNode.getName(), args(fieldNode.isStatic() ? nullX() : objectExpression, rhsValue));
+                            call.setImplicitThis(expression.isImplicitThis());
+                            call.setSpreadSafe(expression.isSpreadSafe());
+                            call.setSafe(expression.isSafe());
+                            call.setMethodTarget(methodNode);
+                            call.visit(controller.getAcg());
+
+                            compileStack.removeVar(i);
+                            operandStack.pop();
+                            return;
+                        }
+                    }
+                }
             }
         }
         super.fallbackAttributeOrPropertySite(expression, objectExpression, name, adapter);
@@ -864,12 +891,10 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
             mv.visitFieldInsn(PUTSTATIC, BytecodeHelper.getClassInternalName(receiverType), name, BytecodeHelper.getTypeDescription(fn.getType()));
         }
 
-        //mv.visitInsn(ACONST_NULL);
-        //stack.replace(OBJECT_TYPE);
         return true;
     }
 
-    private boolean getField(PropertyExpression expression, Expression receiver, ClassNode receiverType, String name) {
+    /*private boolean getField(final PropertyExpression expression, final Expression receiver, ClassNode receiverType, final String name) {
         boolean safe = expression.isSafe();
         boolean implicitThis = expression.isImplicitThis();
 
@@ -892,7 +917,7 @@ public class StaticTypesCallSiteWriter extends CallSiteWriter implements Opcodes
             return true;
         }
         return false;
-    }
+    }*/
 
     private void addPropertyAccessError(final Expression receiver, final String propertyName, final ClassNode receiverType) {
         String receiverName = (receiver instanceof ClassExpression ? receiver.getType() : receiverType).toString(false);
diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index e48b3d7..2cfca20 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -47,7 +47,6 @@ import org.codehaus.groovy.ast.stmt.EmptyStatement;
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.ForStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.tools.GeneralUtils;
 import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.classgen.asm.InvocationWriter;
 import org.codehaus.groovy.classgen.asm.MopWriter;
@@ -71,6 +70,12 @@ import java.util.Set;
 
 import static org.codehaus.groovy.ast.ClassHelper.Character_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.STRING_TYPE;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.attrX;
+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.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.addMethodGenerics;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.applyGenericsContextToPlaceHolders;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
@@ -274,27 +279,20 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
             if (generateAccessor) {
                 acc++;
                 Parameter param = new Parameter(node.getPlainNodeReference(), "$that");
-                Expression receiver = fieldNode.isStatic() ? new ClassExpression(node) : new VariableExpression(param);
-                Statement stmt = new ExpressionStatement(new PropertyExpression(
-                        receiver,
-                        fieldNode.getName()
-                ));
-                MethodNode accessor = node.addMethod("pfaccess$" + acc, access, fieldNode.getOriginType(), new Parameter[]{param}, ClassNode.EMPTY_ARRAY, stmt);
+                Expression receiver = fieldNode.isStatic() ? classX(node) : varX(param);
+                Statement body = returnS(attrX(receiver, constX(fieldNode.getName())));
+                MethodNode accessor = node.addMethod("pfaccess$" + acc, access, fieldNode.getOriginType(), new Parameter[]{param}, ClassNode.EMPTY_ARRAY, body);
                 accessor.setNodeMetaData(STATIC_COMPILE_NODE, Boolean.TRUE);
                 privateFieldAccessors.put(fieldNode.getName(), accessor);
             }
-
             if (generateMutator) {
                 // increment acc if it hasn't been incremented in the current iteration
                 if (!generateAccessor) acc++;
                 Parameter param = new Parameter(node.getPlainNodeReference(), "$that");
                 Expression receiver = fieldNode.isStatic() ? new ClassExpression(node) : new VariableExpression(param);
                 Parameter value = new Parameter(fieldNode.getOriginType(), "$value");
-                Statement stmt = GeneralUtils.assignS(
-                        new PropertyExpression(receiver, fieldNode.getName()),
-                        new VariableExpression(value)
-                );
-                MethodNode mutator = node.addMethod("pfaccess$0" + acc, access, fieldNode.getOriginType(), new Parameter[]{param, value}, ClassNode.EMPTY_ARRAY, stmt);
+                Statement body = assignS(attrX(receiver, constX(fieldNode.getName())), varX(value));
+                MethodNode mutator = node.addMethod("pfaccess$0" + acc, access, fieldNode.getOriginType(), new Parameter[]{param, value}, ClassNode.EMPTY_ARRAY, body);
                 mutator.setNodeMetaData(STATIC_COMPILE_NODE, Boolean.TRUE);
                 privateFieldMutators.put(fieldNode.getName(), mutator);
             }
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 d16bdfe..c203d35 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -102,6 +102,7 @@ import org.codehaus.groovy.runtime.MetaClassHelper;
 import org.codehaus.groovy.syntax.SyntaxException;
 import org.codehaus.groovy.syntax.Token;
 import org.codehaus.groovy.syntax.TokenUtil;
+import org.codehaus.groovy.syntax.Types;
 import org.codehaus.groovy.transform.StaticTypesTransformation;
 import org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys;
 import org.codehaus.groovy.transform.trait.Traits;
@@ -124,6 +125,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
@@ -176,6 +178,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 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.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
@@ -2017,7 +2020,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitPostfixExpression(final PostfixExpression expression) {
-        super.visitPostfixExpression(expression);
         Expression inner = expression.getExpression();
         int op = expression.getOperation().getType();
         visitPrefixOrPostifExpression(expression, inner, op);
@@ -2025,12 +2027,25 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitPrefixExpression(final PrefixExpression expression) {
-        super.visitPrefixExpression(expression);
         Expression inner = expression.getExpression();
         int type = expression.getOperation().getType();
         visitPrefixOrPostifExpression(expression, inner, type);
     }
 
+    private static Optional<Token> asAssignment(final int op) {
+        switch (op) {
+            case Types.PLUS_PLUS:
+            case Types.PREFIX_PLUS_PLUS:
+            case Types.POSTFIX_PLUS_PLUS:
+                return Optional.of(Token.newSymbol(Types.PLUS_EQUAL, -1, -1));
+            case Types.MINUS_MINUS:
+            case Types.PREFIX_MINUS_MINUS:
+            case Types.POSTFIX_MINUS_MINUS:
+                return Optional.of(Token.newSymbol(Types.MINUS_EQUAL, -1, -1));
+        }
+        return Optional.empty();
+    }
+
     private static ClassNode getMathWideningClassNode(final ClassNode type) {
         if (byte_TYPE.equals(type) || short_TYPE.equals(type) || int_TYPE.equals(type)) {
             return int_TYPE;
@@ -2043,44 +2058,59 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return type;
     }
 
-    private void visitPrefixOrPostifExpression(final Expression origin, final Expression innerExpression, final int operationType) {
-        boolean isPostfix = origin instanceof PostfixExpression;
-        ClassNode exprType = getType(innerExpression);
-        String name = operationType == PLUS_PLUS ? "next" : operationType == MINUS_MINUS ? "previous" : null;
-        if (isPrimitiveType(exprType) || isPrimitiveType(getUnwrapper(exprType))) {
-            if (operationType == PLUS_PLUS || operationType == MINUS_MINUS) {
-                if (!isPrimitiveType(exprType)) {
-                    MethodNode node = findMethodOrFail(varX("_dummy_", exprType), exprType, name);
+    private void visitPrefixOrPostifExpression(final Expression origin, final Expression operand, final int operator) {
+        Optional<Token> token = asAssignment(operator);
+        if (token.isPresent()) { // push "operand += 1" or "operand -= 1" onto stack for LHS checks
+            typeCheckingContext.pushEnclosingBinaryExpression(binX(operand, token.get(), constX(1)));
+        }
+        try {
+            operand.visit(this);
+            SetterInfo setterInfo = removeSetterInfo(operand);
+            if (setterInfo != null) {
+                BinaryExpression rewrite = typeCheckingContext.getEnclosingBinaryExpression();
+                rewrite.setSourcePosition(origin);
+                if (ensureValidSetter(rewrite, operand, rewrite.getRightExpression(), setterInfo)) {
+                    return;
+                }
+            }
+
+            ClassNode operandType = getType(operand);
+            boolean isPostfix = (origin instanceof PostfixExpression);
+            String name = (operator == PLUS_PLUS ? "next" : operator == MINUS_MINUS ? "previous" : null);
+
+            if (name != null && isNumberType(operandType)) {
+                if (!isPrimitiveType(operandType)) {
+                    MethodNode node = findMethodOrFail(varX("_dummy_", operandType), operandType, name);
                     if (node != null) {
                         storeTargetMethod(origin, node);
-                        storeType(origin,
-                                isPostfix ? exprType : getMathWideningClassNode(exprType));
+                        storeType(origin, isPostfix ? operandType : getMathWideningClassNode(operandType));
                         return;
                     }
                 }
-                storeType(origin, exprType);
+                storeType(origin, operandType);
                 return;
             }
-            addUnsupportedPreOrPostfixExpressionError(origin);
-            return;
-        } else if (implementsInterfaceOrIsSubclassOf(exprType, Number_TYPE) && (operationType == PLUS_PLUS || operationType == MINUS_MINUS)) {
-            // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
-            MethodNode node = findMethodOrFail(innerExpression, exprType, name);
+            if (name != null && operandType.isDerivedFrom(Number_TYPE)) {
+                // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
+                MethodNode node = findMethodOrFail(operand, operandType, name);
+                if (node != null) {
+                    storeTargetMethod(origin, node);
+                    storeType(origin, getMathWideningClassNode(operandType));
+                    return;
+                }
+            }
+            if (name == null) {
+                addUnsupportedPreOrPostfixExpressionError(origin);
+                return;
+            }
+
+            MethodNode node = findMethodOrFail(operand, operandType, name);
             if (node != null) {
                 storeTargetMethod(origin, node);
-                storeType(origin, getMathWideningClassNode(exprType));
-                return;
+                storeType(origin, isPostfix ? operandType : inferReturnTypeGenerics(operandType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
             }
-        }
-        // not a primitive type. We must find a method which is called next
-        if (name == null) {
-            addUnsupportedPreOrPostfixExpressionError(origin);
-            return;
-        }
-        MethodNode node = findMethodOrFail(innerExpression, exprType, name);
-        if (node != null) {
-            storeTargetMethod(origin, node);
-            storeType(origin, isPostfix ? exprType : inferReturnTypeGenerics(exprType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
+        } finally {
+            if (token.isPresent()) typeCheckingContext.popEnclosingBinaryExpression();
         }
     }
 
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276Bug.groovy
index 5f2e493..3a46bb7 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276Bug.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276Bug.groovy
@@ -16,79 +16,124 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
-
-
-
 package org.codehaus.groovy.classgen.asm.sc.bugs
 
 import groovy.transform.NotYetImplemented
 import groovy.transform.stc.StaticTypeCheckingTestCase
 import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
 
-class Groovy7276Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
-    void testShouldGoThroughPrivateBridgeAccessor() {
-            assertScript '''
+final class Groovy7276Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
+
+    void testShouldGoThroughPrivateBridgeMethod1() {
+        ['i', 'i++'].each {
+            assertScript """
                 class Foo {
-                    private i = 1
-                    def m() { new String().with {i}}
+                    private int i = 1
+                    int m() { new String().with { $it } }
                 }
                 assert new Foo().m() == 1
-                class Bar extends Foo {}
-                assert new Bar().m() == 1
-        '''
+            """
+        }
     }
 
-    void testShouldGoThroughPrivateBridgeMethod() {
-            assertScript '''
+    // GROOVY-7304
+    void testShouldGoThroughPrivateBridgeMethod2() {
+        ['i', 'i++'].each {
+            assertScript """
                 class Foo {
-                    private i = 1
-                    private def pvI() { i }
-                    def m() { new String().with {pvI()}}
+                    private int i = 1
+                    int m() { new String().with { $it } }
+                }
+                class Bar extends Foo {
                 }
-                assert new Foo().m() == 1
-                class Bar extends Foo {}
                 assert new Bar().m() == 1
-        '''
-    }
-
-    void testPrivateAccessInInnerClass() {
-        assertScript '''import groovy.transform.CompileStatic
-
-class Outer {
-    private static class Inner {
-
-        private Set<String> variablesToCheck = []
-
-        private void checkAssertions(String name) {
-            Runnable r = {
-                def candidates = variablesToCheck.findAll { it == name }
-            }
-            r.run()
+            """
         }
     }
 
-    static void test() {
-        new Inner().checkAssertions('name')
-    }
-}
-
-Outer.test()'''
+    void testShouldGoThroughPrivateBridgeMethod3() {
+        ['++i', 'i+=1', 'i=i+1'].each {
+            assertScript """
+                class Foo {
+                    private int i = 1
+                    int m() { new String().with { $it } }
+                }
+                assert new Foo().m() == 2
+            """
+        }
     }
 
-    @NotYetImplemented
     // GROOVY-7304
-    void testShouldGoThroughPrivateBridgeAccessorWithWriteAccess() {
-            assertScript '''
+    void testShouldGoThroughPrivateBridgeMethod4() {
+        ['++i', 'i+=1', 'i=i+1'].each {
+            assertScript """
                 class Foo {
                     private int i = 1
-                    def m() { new String().with {++i}}
+                    int m() { new String().with { $it } }
+                }
+                class Bar extends Foo {
                 }
-                assert new Foo().m() == 2
-                class Bar extends Foo {}
                 assert new Bar().m() == 2
+            """
+        }
+    }
+
+    void testShouldGoThroughPrivateBridgeMethod5() {
+        assertScript '''
+            class Foo {
+                private int i = 1
+                private int pvI() { return i }
+                int m() { new String().with { pvI() } }
+            }
+            assert new Foo().m() == 1
         '''
     }
 
+    void testShouldGoThroughPrivateBridgeMethod6() {
+        assertScript '''
+            class Foo {
+                private int i = 1
+                private int pvI() { return i }
+                int m() { new String().with { pvI() } }
+            }
+            class Bar extends Foo {
+            }
+            assert new Bar().m() == 1
+        '''
+    }
+
+    @NotYetImplemented // GROOVY-7304: bridge methods should also be statically compiled
+    void testShouldGoThroughPrivateBridgeMethod7() {
+        assertScript '''
+            @groovy.transform.CompileDynamic
+            class Foo {
+                private int i = 1
+                @groovy.transform.CompileStatic
+                int m() { new String().with { i++ } }
+            }
+            class Bar extends Foo {
+            }
+            assert new Bar().m() == 1
+        '''
+    }
 
+    void testPrivateAccessInInnerClass() {
+        assertScript '''
+            class Outer {
+                private static class Inner {
+                    private Set<String> variablesToCheck = []
+                    private void checkAssertions(String name) {
+                        Runnable r = {
+                            def candidates = variablesToCheck.findAll { it == name }
+                        }
+                        r.run()
+                    }
+                }
+                static void test() {
+                    new Inner().checkAssertions('name')
+                }
+            }
+            Outer.test()
+        '''
+    }
 }

[groovy] 06/06: GROOVY-6851, GROOVY-10104: SC: skip Verifier-generated methods

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

emilles pushed a commit to branch GROOVY_2_5_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 3a459edd9441fd646ba9d749c31073bccbbeab61
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue May 25 14:45:10 2021 -0500

    GROOVY-6851, GROOVY-10104: SC: skip Verifier-generated methods
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/sc/StaticCompilationVisitor.java     | 15 ++++++++------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 19 +-----------------
 src/test/gls/invocation/DefaultParamTest.groovy    | 23 ++++++++++++++++++++++
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   |  8 --------
 4 files changed, 33 insertions(+), 32 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
index 2cfca20..0337c40 100644
--- a/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/sc/StaticCompilationVisitor.java
@@ -81,6 +81,7 @@ import static org.codehaus.groovy.ast.tools.GenericsUtils.applyGenericsContextTo
 import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.extractSuperClassGenerics;
+import static org.codehaus.groovy.classgen.Verifier.DEFAULT_PARAMETER_GENERATED;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.BINARY_EXP_TARGET;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.COMPONENT_TYPE;
 import static org.codehaus.groovy.transform.sc.StaticCompilationMetadataKeys.DYNAMIC_OUTER_NODE_CALLBACK;
@@ -136,15 +137,17 @@ public class StaticCompilationVisitor extends StaticTypeCheckingVisitor {
         return TYPECHECKED_ANNOTATIONS;
     }
 
-    public static boolean isStaticallyCompiled(AnnotatedNode node) {
-        if (node.getNodeMetaData(STATIC_COMPILE_NODE) != null) {
+    public static boolean isStaticallyCompiled(final AnnotatedNode node) {
+        if (node != null && node.getNodeMetaData(STATIC_COMPILE_NODE) != null) {
             return Boolean.TRUE.equals(node.getNodeMetaData(STATIC_COMPILE_NODE));
         }
         if (node instanceof MethodNode) {
-            return isStaticallyCompiled(node.getDeclaringClass());
-        }
-        if (node instanceof InnerClassNode) {
-            return isStaticallyCompiled(((InnerClassNode)node).getOuterClass());
+            // GROOVY-6851, GROOVY-9151, GROOVY-10104
+            if (!Boolean.TRUE.equals(node.getNodeMetaData(DEFAULT_PARAMETER_GENERATED))) {
+                return isStaticallyCompiled(node.getDeclaringClass());
+            }
+        } else if (node instanceof ClassNode) {
+            return isStaticallyCompiled(((ClassNode) node).getOuterClass());
         }
         return false;
     }
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 c203d35..18efda4 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2558,11 +2558,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // method has already been visited by a static type checking visitor
             return;
         }
-        for (Parameter parameter : node.getParameters()) {
-            if (parameter.getInitialExpression() != null) {
-                parameter.getInitialExpression().visit(this);
-            }
-        }
         super.visitConstructor(node);
     }
 
@@ -2587,23 +2582,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         final boolean osc = typeCheckingContext.isInStaticContext;
         try {
             typeCheckingContext.isInStaticContext = node.isStatic();
+
             super.visitMethod(node);
-            for (Parameter parameter : node.getParameters()) {
-                if (parameter.getInitialExpression() != null) {
-                    parameter.getInitialExpression().visit(this);
-                }
-            }
-/*
-            ClassNode rtype = getInferredReturnType(node);
-            if (rtype == null) {
-                storeInferredReturnType(node, node.getReturnType());
-            }
-            addTypeCheckingInfoAnnotation(node);
-*/
         } finally {
             typeCheckingContext.isInStaticContext = osc;
         }
-
         typeCheckingContext.popErrorCollector();
         node.putNodeMetaData(ERROR_COLLECTOR, collector);
     }
diff --git a/src/test/gls/invocation/DefaultParamTest.groovy b/src/test/gls/invocation/DefaultParamTest.groovy
index 465af04..f8dca71 100644
--- a/src/test/gls/invocation/DefaultParamTest.groovy
+++ b/src/test/gls/invocation/DefaultParamTest.groovy
@@ -138,6 +138,29 @@ final class DefaultParamTest extends GroovyTestCase {
         '''
     }
 
+    // GROOVY-6851, GROOVY-9151, GROOVY-10104
+    void testMethodWithAllParametersDefaultedCS() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            String greet(Object o = 'world', String s = o.toString()) {
+                "hello $s"
+            }
+            assert greet() == 'hello world'
+        '''
+
+        assertScript '''
+            @groovy.transform.CompileStatic
+            class Main {
+                static main(args) {
+                    assert new Main().test().isEmpty()
+                }
+                Map test(Map<String, Object> m = new HashMap<>(Collections.emptyMap())) {
+                    return m
+                }
+            }
+        '''
+    }
+
     // GROOVY-9151
     void _FIXME_testConstructorWithAllParametersDefaulted() {
         assertScript '''
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index b6c9f7d..bb63f47 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -1246,15 +1246,7 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
     // GROOVY-6851
     void testShouldNotThrowNPEIfElvisOperatorIsUsedInDefaultArgumentValue() {
         assertScript '''
-            import org.codehaus.groovy.ast.expr.MethodCallExpression
-
             class GrailsHomeWorkspaceReader {
-                @ASTTest(phase=INSTRUCTION_SELECTION,value={
-                    def defaultValue = node.parameters[0].initialExpression
-                    assert defaultValue instanceof MethodCallExpression
-                    def target = defaultValue.getNodeMetaData(DIRECT_METHOD_CALL_TARGET)
-                    assert target != null
-                })
                 GrailsHomeWorkspaceReader(String grailsHome = System.getProperty('grails.home')) {
                 }
             }