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/01 17:55:43 UTC

[groovy] branch GROOVY_2_5_X updated (9deb54d -> 3811bf1)

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 9deb54d  fix test for JDK7
     new e8d473a  GROOVY-9807: limit receiver replacement for implicit-this in inner class
     new 19d3a60  GROOVY-10027: NamedParam: check against declared/inferred argument type
     new 50620d7  GROOVY-10037: add test case
     new e06f4cb  GROOVY-10106: trait field init may call trait method(s) so process first
     new ac2f471  GROOVY-10112: `IndexedProperty` shouldn't add setter for immutable field
     new e2437f6  GROOVY-10141: retain parse order of anon. inner types in module classes
     new 32e33fe  GROOVY-10164: make RootLoader(ClassLoader) public
     new 0b998ce  GROOVY-10197: namedArgs.containsKey(propertyName) isn't implicit-this
     new b47886f  GROOVY-10179: STC: for-in collection type: consider instanceof flow-type
     new ca2629a  GROOVY-10191: catch LinkageError during static inline
     new 3811bf1  GROOVY-10199: ASTTest: evaluate with compliation unit's transform loader

The 11 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:
 .../groovy/groovy/transform/IndexedProperty.java   |   3 +-
 .../groovy/transform/ASTTestTransformation.groovy  |  75 ++---
 .../apache/groovy/ast/tools/ExpressionUtils.java   |   4 +-
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   |   2 +-
 .../groovy/classgen/asm/InvocationWriter.java      | 366 ++++++++++++++++++---
 .../java/org/codehaus/groovy/tools/RootLoader.java |   4 +-
 .../transform/ImmutableASTTransformation.java      |   1 +
 .../IndexedPropertyASTTransformation.java          |   5 +-
 .../TupleConstructorASTTransformation.java         |  10 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   |  34 +-
 .../transform/trait/TraitASTTransformation.java    |  16 +-
 .../transform/trait/TraitReceiverTransformer.java  | 166 ++++------
 src/test/gls/innerClass/InnerClassTest.groovy      |  20 ++
 src/test/groovy/NamedParameterTest.groovy          |  80 ++++-
 .../bugs/{Groovy7989.groovy => Groovy10191.groovy} |  25 +-
 .../bugs/{Groovy7989.groovy => Groovy10199.groovy} |  21 +-
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |  34 ++
 src/test/groovy/transform/stc/LoopsSTCTest.groovy  |  66 +++-
 src/test/groovy/transform/stc/MiscSTCTest.groovy   |  24 +-
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   |  42 +++
 .../classgen/asm/sc/MiscStaticCompileTest.groovy   |   8 -
 .../classgen/asm/sc/bugs/Groovy6240Bug.groovy      |  69 ----
 .../transform/IndexedPropertyTransformTest.groovy  |  30 +-
 23 files changed, 750 insertions(+), 355 deletions(-)
 copy src/test/groovy/bugs/{Groovy7989.groovy => Groovy10191.groovy} (71%)
 copy src/test/groovy/bugs/{Groovy7989.groovy => Groovy10199.groovy} (69%)
 delete mode 100644 src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy

[groovy] 06/11: GROOVY-10141: retain parse order of anon. inner types in module 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 e2437f6157360c6b12ab12e4ffca6fe0f183e6b6
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Jun 16 15:14:02 2021 -0500

    GROOVY-10141: retain parse order of anon. inner types in module classes
    
    - InnerClassVisitor checks this$0 which isn't set up if C$1$1 before C$1
    
    Conflicts:
    	src/test/gls/innerClass/InnerClassTest.groovy
---
 .../org/codehaus/groovy/antlr/AntlrParserPlugin.java |  2 +-
 src/test/gls/innerClass/InnerClassTest.groovy        | 20 ++++++++++++++++++++
 2 files changed, 21 insertions(+), 1 deletion(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
index 94032a6..cff33b8 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
@@ -617,13 +617,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         ((InnerClassNode) classNode).setAnonymous(true);
         classNode.setEnclosingMethod(methodNode);
         configureAST(classNode, node);
+        output.addClass(classNode);
 
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
 
         AnonymousInnerClassCarrier ret = new AnonymousInnerClassCarrier();
         ret.innerClass = classNode;
-        output.addClass(classNode);
         classNode = oldNode;
         return ret;
     }
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 52a1c45..64bce3e 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -1309,6 +1309,26 @@ final class InnerClassTest {
         '''
     }
 
+    @Test // GROOVY-10141
+    void testInnerClassIn2xAIC() {
+        assertScript '''
+            class Outer {
+                class Inner {
+                }
+                def obj = new Object() {
+                    String toString() {
+                        new Object() {
+                            String toString() {
+                                new Inner()
+                            }
+                        }
+                    }
+                }
+            }
+            new Outer().obj.toString()
+        '''
+    }
+
     @Test // GROOVY-6831
     void testNestedPropertyHandling() {
         assertScript '''

[groovy] 08/11: GROOVY-10197: namedArgs.containsKey(propertyName) isn't implicit-this

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 0b998ce1306f3730813a96d8970d0e4563170c76
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Aug 13 13:09:47 2021 -0500

    GROOVY-10197: namedArgs.containsKey(propertyName) isn't implicit-this
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
---
 .../TupleConstructorASTTransformation.java         | 10 ++++-----
 src/test/groovy/transform/stc/MiscSTCTest.groovy   | 24 +++++++++++++++++++++-
 .../classgen/asm/sc/MiscStaticCompileTest.groovy   |  8 --------
 3 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
index a9271cf..2b70572 100644
--- a/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/TupleConstructorASTTransformation.java
@@ -37,6 +37,7 @@ import org.codehaus.groovy.ast.expr.BooleanExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.EmptyStatement;
@@ -337,11 +338,10 @@ public class TupleConstructorASTTransformation extends AbstractASTTransformation
         for (PropertyNode pNode : cNode.getProperties()) {
             if (pNode.isStatic()) continue;
 
-            // if namedArgs.containsKey(propertyName) setProperty(propertyName, namedArgs.get(propertyName));
-            Statement ifStatement = ifS(
-                    callX(namedArgs, "containsKey", constX(pNode.getName())),
-                    assignS(varX(pNode), propX(namedArgs, pNode.getName())));
-            block.addStatement(ifStatement);
+            // if (namedArgs.containsKey(propertyName)) propertyNode= namedArgs.propertyName;
+            MethodCallExpression containsProperty = callX(namedArgs, "containsKey", constX(pNode.getName()));
+            containsProperty.setImplicitThis(false); // GROOVY-10197
+            block.addStatement(ifS(containsProperty, assignS(varX(pNode), propX(namedArgs, pNode.getName()))));
         }
         block.addStatement(stmt(callX(CHECK_METHOD_TYPE, "checkPropNames", args(varX("this"), namedArgs))));
         return block;
diff --git a/src/test/groovy/transform/stc/MiscSTCTest.groovy b/src/test/groovy/transform/stc/MiscSTCTest.groovy
index 94be0de..9bde8b8 100644
--- a/src/test/groovy/transform/stc/MiscSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MiscSTCTest.groovy
@@ -172,7 +172,7 @@ class MiscSTCTest extends StaticTypeCheckingTestCase {
             1
         '''
     }
-    
+
     void testCompareEnumToNull() {
         assertScript '''
             enum MyEnum { a,b }
@@ -183,6 +183,28 @@ class MiscSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10197
+    void testEnumMethodOverride() {
+        assertScript '''
+            enum E {
+                CONST {
+                    int getValue() { 1 }
+                }
+                int getValue() { -1 }
+            }
+            assert E.CONST.value == 1
+        '''
+        assertScript '''
+            enum E {
+                CONST {
+                    final int value = 1
+                }
+                int getValue() { -1 }
+            }
+            assert E.CONST.value == 1
+        '''
+    }
+
     void testMethodReturnTypeInferenceShouldNotWorkBecauseNotSameSourceUnit() {
         shouldFailWithMessages '''
             import groovy.transform.stc.MiscSTCTest.MiscSTCTestSupport as A
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/MiscStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/MiscStaticCompileTest.groovy
index 4377ab0..ee2b851 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/MiscStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/MiscStaticCompileTest.groovy
@@ -31,17 +31,9 @@ class MiscStaticCompileTest extends MiscSTCTest implements StaticCompilationTest
             for(int i in 1..3){
               new File(dir, "testEachFileRecurse${i}.txt").createNewFile()
             }
-
             dir.eachFileRecurse(FileType.FILES) { File spec ->
             }
-
             dir.deleteDir()
         '''
     }
-
-    @Override
-    void testCompareEnumToNull() {
-        super.testCompareEnumToNull()
-    }
 }
-

[groovy] 01/11: GROOVY-9807: limit receiver replacement for implicit-this in inner class

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 e8d473a11563c32f16a8d43fec4fd418f1794b2c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Mar 10 16:59:48 2021 -0600

    GROOVY-9807: limit receiver replacement for implicit-this in inner class
    
    When user creates a method call expression, the default is for implicit
    this to be true and this has caused a number of problems for transforms
    when applied to inner class scenarios.  Only when the object expression
    is truly "this" should it be rewritten to "Outer.this" when referencing
    an outer class method.
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
---
 .../groovy/classgen/asm/InvocationWriter.java      | 366 ++++++++++++++++++---
 1 file changed, 316 insertions(+), 50 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
index d73066b..9d442e8 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/InvocationWriter.java
@@ -18,29 +18,69 @@
  */
 package org.codehaus.groovy.classgen.asm;
 
+import org.apache.groovy.ast.tools.ExpressionUtils;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ConstructorNode;
 import org.codehaus.groovy.ast.FieldNode;
-import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.GroovyCodeVisitor;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.ArrayExpression;
+import org.codehaus.groovy.ast.expr.AttributeExpression;
+import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.BitwiseNegationExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
 import org.codehaus.groovy.ast.expr.CastExpression;
 import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.ClosureListExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
+import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
 import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.FieldExpression;
+import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.ListExpression;
+import org.codehaus.groovy.ast.expr.MapEntryExpression;
+import org.codehaus.groovy.ast.expr.MapExpression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.MethodPointerExpression;
+import org.codehaus.groovy.ast.expr.NotExpression;
+import org.codehaus.groovy.ast.expr.PostfixExpression;
+import org.codehaus.groovy.ast.expr.PrefixExpression;
 import org.codehaus.groovy.ast.expr.PropertyExpression;
+import org.codehaus.groovy.ast.expr.RangeExpression;
 import org.codehaus.groovy.ast.expr.SpreadExpression;
+import org.codehaus.groovy.ast.expr.SpreadMapExpression;
 import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
+import org.codehaus.groovy.ast.expr.UnaryMinusExpression;
+import org.codehaus.groovy.ast.expr.UnaryPlusExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.AssertStatement;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.BreakStatement;
+import org.codehaus.groovy.ast.stmt.CaseStatement;
+import org.codehaus.groovy.ast.stmt.CatchStatement;
+import org.codehaus.groovy.ast.stmt.ContinueStatement;
+import org.codehaus.groovy.ast.stmt.DoWhileStatement;
+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.IfStatement;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.codehaus.groovy.ast.stmt.SwitchStatement;
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
+import org.codehaus.groovy.ast.stmt.ThrowStatement;
+import org.codehaus.groovy.ast.stmt.TryCatchStatement;
+import org.codehaus.groovy.ast.stmt.WhileStatement;
 import org.codehaus.groovy.ast.tools.WideningCategories;
 import org.codehaus.groovy.classgen.AsmClassGenerator;
-import org.codehaus.groovy.classgen.asm.OptimizingStatementWriter.StatementMeta;
+import org.codehaus.groovy.classgen.BytecodeExpression;
 import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
 import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
 import org.codehaus.groovy.runtime.typehandling.ShortTypeHandling;
@@ -103,7 +143,7 @@ public class InvocationWriter {
     static final MethodCaller selectConstructorAndTransformArguments = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "selectConstructorAndTransformArguments");
 
     private final WriterController controller;
-    
+
     public InvocationWriter(WriterController wc) {
         this.controller = wc;
     }
@@ -115,7 +155,7 @@ public class InvocationWriter {
         // message name
         Expression messageName = new CastExpression(ClassHelper.STRING_TYPE, call.getMethod());
         if (useSuper) {
-            ClassNode classNode = controller.isInClosure() ? controller.getOutermostClass() : controller.getClassNode(); // GROOVY-4035 
+            ClassNode classNode = controller.isInClosure() ? controller.getOutermostClass() : controller.getClassNode(); // GROOVY-4035
             ClassNode superClass = classNode.getSuperClass();
             makeCall(call, new ClassExpression(superClass),
                     objectExpression, messageName,
@@ -131,7 +171,7 @@ public class InvocationWriter {
             );
         }
     }
-    
+
     public void makeCall(
             Expression origin,
             Expression receiver, Expression message, Expression arguments,
@@ -157,6 +197,7 @@ public class InvocationWriter {
         if (target == null) return false;
 
         ClassNode declaringClass = target.getDeclaringClass();
+        ClassNode enclosingClass = controller.getClassNode();
         String methodName = target.getName();
         int opcode = INVOKEVIRTUAL;
         if (target.isStatic()) {
@@ -170,37 +211,33 @@ public class InvocationWriter {
         CompileStack compileStack = controller.getCompileStack();
         OperandStack operandStack = controller.getOperandStack();
         MethodVisitor mv = controller.getMethodVisitor();
-        ClassNode classNode = controller.getClassNode();
 
         // handle receiver
         int argumentsToRemove = 0;
-        if (opcode!=INVOKESTATIC) {
-            if (receiver!=null) {
-                // load receiver if not static invocation
-                // TODO: fix inner class case
+        if (opcode != INVOKESTATIC) {
+            argumentsToRemove += 1;
+            if (receiver != null) {
+                Expression objectExpression = receiver;
                 if (implicitThis
-                        && !classNode.isDerivedFrom(declaringClass)
-                        && !classNode.implementsInterface(declaringClass)
-                        && classNode instanceof InnerClassNode) {
-                    // we are calling an outer class method
+                        && enclosingClass.getOuterClass() != null
+                        && !enclosingClass.isDerivedFrom(declaringClass)
+                        && !enclosingClass.implementsInterface(declaringClass)) {
+                    // outer class method invocation
                     compileStack.pushImplicitThis(false);
                     if (controller.isInClosure()) {
-                        new VariableExpression("thisObject").visit(controller.getAcg());
-                    } else {
-                        Expression expr = new PropertyExpression(new ClassExpression(declaringClass), "this");
-                        expr.visit(controller.getAcg());
+                        objectExpression = new VariableExpression("thisObject");
+                    } else if (isThis(receiver)) {
+                        objectExpression = new PropertyExpression(new ClassExpression(declaringClass), "this");
                     }
                 } else {
                     compileStack.pushImplicitThis(implicitThis);
-                    receiver.visit(controller.getAcg());
                 }
+                objectExpression.visit(controller.getAcg());
                 operandStack.doGroovyCast(declaringClass);
                 compileStack.popImplicitThis();
-                argumentsToRemove++;
             } else {
                 mv.visitIntInsn(ALOAD, 0);
-                operandStack.push(classNode);
-                argumentsToRemove++;
+                operandStack.push(enclosingClass);
             }
         }
 
@@ -208,7 +245,7 @@ public class InvocationWriter {
         if (receiver == null) {
             receiverType = declaringClass;
         } else {
-            receiverType = controller.getTypeChooser().resolveType(receiver, classNode);
+            receiverType = controller.getTypeChooser().resolveType(receiver, enclosingClass);
             if (isClassClassNodeWrappingConcreteType(receiverType) && target.isStatic()) {
                 receiverType = receiverType.getGenericsTypes()[0].getType();
             }
@@ -252,12 +289,241 @@ public class InvocationWriter {
         return true;
     }
 
+    /**
+     * Supplements {@link ExpressionUtils#isThisExpression isThisExpression}
+     * with the ability to see into {@code CheckcastReceiverExpression}.
+     */
+    private static boolean isThis(final Expression expression) {
+        final boolean[] isThis = new boolean[1];
+        expression.visit(new GroovyCodeVisitor() {
+
+            @Override
+            public void visitVariableExpression(VariableExpression expression) {
+                isThis[0] = expression.isThisExpression();
+            }
+
+            // expressions:
+
+            @Override
+            public void visitArgumentlistExpression(ArgumentListExpression expression) {
+                visitTupleExpression(expression);
+            }
+
+            @Override
+            public void visitArrayExpression(ArrayExpression expression) {
+            }
+
+            @Override
+            public void visitAttributeExpression(AttributeExpression expression) {
+                visitPropertyExpression(expression);
+            }
+
+            @Override
+            public void visitBinaryExpression(BinaryExpression expression) {
+            }
+
+            @Override
+            public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
+            }
+
+            @Override
+            public void visitBooleanExpression(BooleanExpression expression) {
+            }
+
+            @Override
+            public void visitBytecodeExpression(BytecodeExpression expression) {
+            }
+
+            @Override
+            public void visitCastExpression(CastExpression expression) {
+            }
+
+            @Override
+            public void visitClassExpression(ClassExpression expression) {
+            }
+
+            @Override
+            public void visitClosureExpression(ClosureExpression expression) {
+            }
+
+            @Override
+            public void visitClosureListExpression(ClosureListExpression expression) {
+                visitListExpression(expression);
+            }
+
+            @Override
+            public void visitConstantExpression(ConstantExpression expression) {
+            }
+
+            @Override
+            public void visitConstructorCallExpression(ConstructorCallExpression expression) {
+            }
+
+            @Override
+            public void visitDeclarationExpression(DeclarationExpression expression) {
+                visitBinaryExpression(expression);
+            }
+
+            @Override
+            public void visitFieldExpression(FieldExpression expression) {
+            }
+
+            @Override
+            public void visitGStringExpression(GStringExpression expression) {
+            }
+
+            @Override
+            public void visitListExpression(ListExpression expression) {
+            }
+
+            @Override
+            public void visitMapExpression(MapExpression expression) {
+            }
+
+            @Override
+            public void visitMapEntryExpression(MapEntryExpression expression) {
+            }
+
+            @Override
+            public void visitMethodCallExpression(MethodCallExpression expression) {
+            }
+
+            @Override
+            public void visitMethodPointerExpression(MethodPointerExpression expression) {
+            }
+
+            @Override
+            public void visitNotExpression(NotExpression expression) {
+                visitBooleanExpression(expression);
+            }
+
+            @Override
+            public void visitPostfixExpression(PostfixExpression expression) {
+            }
+
+            @Override
+            public void visitPrefixExpression(PrefixExpression expression) {
+            }
+
+            @Override
+            public void visitPropertyExpression(PropertyExpression expression) {
+            }
+
+            @Override
+            public void visitRangeExpression(RangeExpression expression) {
+            }
+
+            @Override
+            public void visitShortTernaryExpression(ElvisOperatorExpression expression) {
+                visitTernaryExpression(expression);
+            }
+
+            @Override
+            public void visitSpreadExpression(SpreadExpression expression) {
+            }
+
+            @Override
+            public void visitSpreadMapExpression(SpreadMapExpression expression) {
+            }
+
+            @Override
+            public void visitStaticMethodCallExpression(StaticMethodCallExpression expression) {
+            }
+
+            @Override
+            public void visitTernaryExpression(TernaryExpression expression) {
+            }
+
+            @Override
+            public void visitTupleExpression(TupleExpression expression) {
+            }
+
+            @Override
+            public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
+            }
+
+            @Override
+            public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
+            }
+
+            // statements:
+
+            @Override
+            public void visitAssertStatement(AssertStatement statement) {
+            }
+
+            @Override
+            public void visitBlockStatement(BlockStatement statement) {
+            }
+
+            @Override
+            public void visitBreakStatement(BreakStatement statement) {
+            }
+
+            @Override
+            public void visitCaseStatement(CaseStatement statement) {
+            }
+
+            @Override
+            public void visitCatchStatement(CatchStatement statement) {
+            }
+
+            @Override
+            public void visitContinueStatement(ContinueStatement statement) {
+            }
+
+            @Override
+            public void visitDoWhileLoop(DoWhileStatement statement) {
+            }
+
+            public void visitEmptyStatement(EmptyStatement statement) {
+            }
+
+            @Override
+            public void visitExpressionStatement(ExpressionStatement statement) {
+            }
+
+            @Override
+            public void visitForLoop(ForStatement statement) {
+            }
+
+            @Override
+            public void visitIfElse(IfStatement statement) {
+            }
+
+            @Override
+            public void visitReturnStatement(ReturnStatement statement) {
+            }
+
+            @Override
+            public void visitSwitch(SwitchStatement statement) {
+            }
+
+            @Override
+            public void visitSynchronizedStatement(SynchronizedStatement statement) {
+            }
+
+            @Override
+            public void visitThrowStatement(ThrowStatement statement) {
+            }
+
+            @Override
+            public void visitTryCatchFinally(TryCatchStatement statement) {
+            }
+
+            @Override
+            public void visitWhileLoop(WhileStatement statement) {
+            }
+        });
+        return isThis[0];
+    }
+
     private boolean lastIsArray(List<Expression> argumentList, int pos) {
         Expression last = argumentList.get(pos);
         ClassNode type = controller.getTypeChooser().resolveType(last, controller.getClassNode());
         return type.isArray();
     }
-    
+
     // load arguments
     protected void loadArguments(List<Expression> argumentList, Parameter[] para) {
         if (para.length==0) return;
@@ -302,7 +568,7 @@ public class InvocationWriter {
     }
 
     protected boolean makeDirectCall(
-        Expression origin, Expression receiver, 
+        Expression origin, Expression receiver,
         Expression message, Expression arguments,
         MethodCallerMultiAdapter adapter,
         boolean implicitThis, boolean containsSpreadExpression
@@ -322,8 +588,8 @@ public class InvocationWriter {
                     args = new TupleExpression(receiver);
                 }
 
-                StatementMeta meta = null;
-                if (origin!=null) meta = origin.getNodeMetaData(StatementMeta.class);
+                OptimizingStatementWriter.StatementMeta meta = null;
+                if (origin!=null) meta = origin.getNodeMetaData(OptimizingStatementWriter.StatementMeta.class);
                 MethodNode mn = null;
                 if (meta!=null) mn = meta.target;
 
@@ -353,15 +619,15 @@ public class InvocationWriter {
 
             if (methodName != null) {
                 controller.getCallSiteWriter().makeCallSite(
-                        receiver, methodName, arguments, safe, implicitThis, 
-                        adapter == invokeMethodOnCurrent, 
+                        receiver, methodName, arguments, safe, implicitThis,
+                        adapter == invokeMethodOnCurrent,
                         adapter == invokeStaticMethod);
                 return true;
             }
         }
         return false;
     }
-    
+
     protected void makeUncachedCall(
             Expression origin, ClassExpression sender,
             Expression receiver, Expression message, Expression arguments,
@@ -372,7 +638,7 @@ public class InvocationWriter {
         OperandStack operandStack = controller.getOperandStack();
         CompileStack compileStack = controller.getCompileStack();
         AsmClassGenerator acg = controller.getAcg();
-        
+
         // ensure VariableArguments are read, not stored
         compileStack.pushLHS(false);
 
@@ -387,14 +653,14 @@ public class InvocationWriter {
         if (adapter == invokeMethodOnSuper && methodName != null) {
             controller.getSuperMethodNames().add(methodName);
         }
-        
+
         // receiver
         compileStack.pushImplicitThis(implicitThis);
         receiver.visit(acg);
         operandStack.box();
         compileStack.popImplicitThis();
-        
-        
+
+
         int operandsToRemove = 2;
         // message
         if (message != null) {
@@ -429,7 +695,7 @@ public class InvocationWriter {
         compileStack.popLHS();
         operandStack.replace(ClassHelper.OBJECT_TYPE,operandsToRemove);
     }
-    
+
     protected void makeCall(
             Expression origin, ClassExpression sender,
             Expression receiver, Expression message, Expression arguments,
@@ -548,7 +814,7 @@ public class InvocationWriter {
         if (controller.isStaticMethod()) return true;
         return controller.isStaticContext() && !call.isImplicitThis();
     }
-    
+
     private static boolean usesSuper(MethodCallExpression call) {
         Expression expression = call.getObjectExpression();
         if (expression instanceof VariableExpression) {
@@ -567,37 +833,37 @@ public class InvocationWriter {
                 InvocationWriter.invokeStaticMethod,
                 false, false, false);
     }
-    
+
     private boolean writeDirectConstructorCall(ConstructorCallExpression call) {
         if (!controller.isFastPath()) return false;
-        
-        StatementMeta meta = call.getNodeMetaData(StatementMeta.class);
+
+        OptimizingStatementWriter.StatementMeta meta = call.getNodeMetaData(OptimizingStatementWriter.StatementMeta.class);
         ConstructorNode cn = null;
         if (meta!=null) cn = (ConstructorNode) meta.target;
         if (cn==null) return false;
-        
+
         String ownerDescriptor = prepareConstructorCall(cn);
         TupleExpression args = makeArgumentList(call.getArguments());
         loadArguments(args.getExpressions(), cn.getParameters());
         finnishConstructorCall(cn, ownerDescriptor, args.getExpressions().size());
-        
+
         return true;
     }
-    
+
     protected String prepareConstructorCall(ConstructorNode cn) {
         String owner = BytecodeHelper.getClassInternalName(cn.getDeclaringClass());
         MethodVisitor mv = controller.getMethodVisitor();
-        
+
         mv.visitTypeInsn(NEW, owner);
         mv.visitInsn(DUP);
         return owner;
     }
-    
+
     protected void finnishConstructorCall(ConstructorNode cn, String ownerDescriptor, int argsToRemove) {
         String desc = BytecodeHelper.getMethodDescriptor(ClassHelper.VOID_TYPE, cn.getParameters());
         MethodVisitor mv = controller.getMethodVisitor();
         mv.visitMethodInsn(INVOKESPECIAL, ownerDescriptor, "<init>", desc, false);
-        
+
         controller.getOperandStack().remove(argsToRemove);
         controller.getOperandStack().push(cn.getDeclaringClass());
     }
@@ -618,7 +884,7 @@ public class InvocationWriter {
                 arguments, false, false, false,
                 false);
     }
-    
+
     public void writeInvokeConstructor(ConstructorCallExpression call) {
         if (writeDirectConstructorCall(call)) return;
         if (writeAICCall(call)) return;
@@ -629,13 +895,13 @@ public class InvocationWriter {
         if (!call.isUsingAnonymousInnerClass()) return false;
         ConstructorNode cn = call.getType().getDeclaredConstructors().get(0);
         OperandStack os = controller.getOperandStack();
-        
+
         String ownerDescriptor = prepareConstructorCall(cn);
-        
+
         List<Expression> args = makeArgumentList(call.getArguments()).getExpressions();
         Parameter[] params = cn.getParameters();
         // if a this appears as parameter here, then it should be
-        // not static, unless we are in a static method. But since 
+        // not static, unless we are in a static method. But since
         // ACG#visitVariableExpression does the opposite for this case, we
         // push here an explicit this. This should not have any negative effect
         // sine visiting a method call or property with implicit this will push
@@ -656,7 +922,7 @@ public class InvocationWriter {
         finnishConstructorCall(cn, ownerDescriptor, args.size());
         return true;
     }
-    
+
     private void loadVariableWithReference(VariableExpression var) {
         if (!var.isUseReferenceDirectly()) {
             var.visit(controller.getAcg());

[groovy] 04/11: GROOVY-10106: trait field init may call trait method(s) so process first

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 e06f4cb7d711db80c2a14142ec17e244bcc28438
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue May 25 11:37:03 2021 -0500

    GROOVY-10106: trait field init may call trait method(s) so process first
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
    	src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |   4 +-
 .../transform/trait/TraitASTTransformation.java    |  16 +-
 .../transform/trait/TraitReceiverTransformer.java  | 166 +++++++--------------
 src/test/groovy/transform/stc/BugsSTCTest.groovy   |  34 +++++
 4 files changed, 100 insertions(+), 120 deletions(-)

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 b262e7f..6fdcef8 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4010,13 +4010,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         expression.getBooleanExpression().visit(this);
         Expression trueExpression = expression.getTrueExpression();
         Expression falseExpression = expression.getFalseExpression();
+        ClassNode typeOfTrue = findCurrentInstanceOfClass(trueExpression, null);
         trueExpression.visit(this);
+        if (typeOfTrue == null)
+            typeOfTrue = getType(trueExpression);
         // pop if-then-else temporary type info
         typeCheckingContext.popTemporaryTypeInfo();
         falseExpression.visit(this);
         ClassNode resultType;
         ClassNode typeOfFalse = getType(falseExpression);
-        ClassNode typeOfTrue = getType(trueExpression);
         // handle instanceof cases
         if (hasInferredReturnType(falseExpression)) {
             typeOfFalse = falseExpression.getNodeMetaData(StaticTypesMarker.INFERRED_RETURN_TYPE);
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index 8ca1c18..02f4947 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -44,6 +44,7 @@ import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.Statement;
 import org.codehaus.groovy.ast.tools.GeneralUtils;
+import org.codehaus.groovy.ast.tools.GenericsUtils;
 import org.codehaus.groovy.classgen.GeneratorContext;
 import org.codehaus.groovy.classgen.VariableScopeVisitor;
 import org.codehaus.groovy.classgen.Verifier;
@@ -212,6 +213,11 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
             }
         }
 
+        // add fields
+        for (FieldNode field : fields) {
+            processField(field, initializer, staticInitializer, fieldHelper, helper, staticFieldHelper, cNode, fieldNames);
+        }
+
         // add methods
         List<MethodNode> methods = new ArrayList<MethodNode>(cNode.getMethods());
         List<MethodNode> nonPublicAPIMethods = new LinkedList<MethodNode>();
@@ -244,11 +250,6 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
             cNode.removeMethod(privateMethod);
         }
 
-        // add fields
-        for (FieldNode field : fields) {
-            processField(field, initializer, staticInitializer, fieldHelper, helper, staticFieldHelper, cNode, fieldNames);
-        }
-
         // copy statements from static and instance init blocks
         if (staticInitStatements != null) {
             BlockStatement toBlock = getBlockStatement(staticInitializer, staticInitializer.getCode());
@@ -632,10 +633,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         ClassNode type;
         if (isStatic) {
             // Class<TraitClass>
-            type = ClassHelper.CLASS_Type.getPlainNodeReference();
-            type.setGenericsTypes(new GenericsType[]{
-                    new GenericsType(rawType)
-            });
+            type = GenericsUtils.makeClassSafe0(ClassHelper.CLASS_Type, new GenericsType(rawType));
         } else {
             // TraitClass
             type = rawType;
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
index dfb3476..3d01b29 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
@@ -30,9 +30,6 @@ import org.codehaus.groovy.ast.PropertyNode;
 import org.codehaus.groovy.ast.Variable;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
 import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.DeclarationExpression;
@@ -41,23 +38,28 @@ import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.ast.expr.StaticMethodCallExpression;
-import org.codehaus.groovy.ast.expr.TernaryExpression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.syntax.SyntaxException;
 import org.codehaus.groovy.syntax.Token;
-import org.codehaus.groovy.syntax.Types;
 
 import java.lang.reflect.Modifier;
 import java.util.Collection;
-import java.util.List;
+
+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.classX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.isInstanceOfX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ternaryX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 
 /**
  * This expression transformer is used internally by the {@link org.codehaus.groovy.transform.trait.TraitASTTransformation
  * trait} AST transformation to change the receiver of a message on "this" into a static method call on the trait helper
- * class. <p></p>
- * In a nutshell, code like the following method definition in a trait:<p></p> <code>void foo() { this.bar() }</code> is
+ * class.
+ * <p>
+ * In a nutshell, code like the following method definition in a trait: <code>void foo() { this.bar() }</code> is
  * transformed into: <code>void foo() { TraitHelper$bar(this) }</code>
  *
  * @since 2.3.0
@@ -126,7 +128,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
                     boolean isStatic = Modifier.isStatic(accessedVariable.getModifiers());
                     Expression receiver = createFieldHelperReceiver();
                     if (isStatic) {
-                        receiver = createStaticReceiver(receiver);
+                        receiver = asClass(receiver);
                     }
                     FieldNode fn = accessedVariable instanceof FieldNode ? (FieldNode) accessedVariable : ((PropertyNode) accessedVariable).getField();
                     MethodCallExpression mce = new MethodCallExpression(receiver, Traits.helperGetterName(fn), ArgumentListExpression.EMPTY_ARGUMENTS);
@@ -140,7 +142,7 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
                     propertyExpression.getProperty().setSourcePosition(exp);
                     return propertyExpression;
                 }
-            } else if (accessedVariable instanceof DynamicVariable) {
+            } else if (accessedVariable instanceof DynamicVariable && !inClosure) { // GROOVY-9386
                 PropertyExpression propertyExpression = new PropertyExpression(
                         new VariableExpression(weaved), accessedVariable.getName());
                 propertyExpression.getProperty().setSourcePosition(exp);
@@ -275,18 +277,6 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
         }
     }
 
-    private TernaryExpression createStaticReceiver(final Expression receiver) {
-        return new TernaryExpression(
-                new BooleanExpression(new BinaryExpression(
-                        receiver,
-                        Token.newSymbol(Types.KEYWORD_INSTANCEOF, -1, -1),
-                        new ClassExpression(ClassHelper.CLASS_Type)
-                )),
-                receiver,
-                new MethodCallExpression(createFieldHelperReceiver(), "getClass", ArgumentListExpression.EMPTY_ARGUMENTS)
-        );
-    }
-
     private BinaryExpression createAssignmentToField(final Expression rightExpression,
                                                      final Token operation, final String fieldName) {
         return new BinaryExpression(
@@ -330,115 +320,71 @@ class TraitReceiverTransformer extends ClassCodeExpressionTransformer {
         } else {
             superCallArgs.addExpression(arguments);
         }
-        MethodCallExpression transformed = new MethodCallExpression(
+        MethodCallExpression newCall = callX(
                 weaved,
                 Traits.getSuperTraitMethodName(traitClass, method),
                 superCallArgs
         );
-        transformed.setSourcePosition(call);
-        transformed.setSafe(call.isSafe());
-        transformed.setSpreadSafe(call.isSpreadSafe());
-        transformed.setImplicitThis(false);
-        return transformed;
+        newCall.setImplicitThis(false);
+        newCall.setSafe(call.isSafe());
+        newCall.setSourcePosition(call);
+        newCall.setSpreadSafe(call.isSpreadSafe());
+        return newCall;
     }
 
-
     private Expression transformMethodCallOnThis(final MethodCallExpression call) {
         Expression method = call.getMethod();
         Expression arguments = call.getArguments();
+
         if (method instanceof ConstantExpression) {
-            String methodName = method.getText();
-            List<MethodNode> methods = traitClass.getMethods(methodName);
-            for (MethodNode methodNode : methods) {
-                if (methodName.equals(methodNode.getName()) && methodNode.isPrivate()) {
-                    if (inClosure) {
-                        return transformPrivateMethodCallOnThisInClosure(call, arguments, methodName);
+            String methodName = call.getMethodAsString();
+            for (MethodNode methodNode : traitClass.getMethods(methodName)) {
+                if (methodName.equals(methodNode.getName()) && (methodNode.isStatic() || methodNode.isPrivate())) {
+                    MethodCallExpression newCall;
+                    if (!inClosure && methodNode.isStatic()) { // GROOVY-10312: $self or $static$self.staticMethod(...)
+                        newCall = callX(varX(weaved), methodName, transform(arguments));
+                        newCall.setImplicitThis(false);
+                        newCall.setSafe(false);
+                    } else {
+                        ArgumentListExpression newArgs = createArgumentList(methodNode.isStatic() ? asClass(varX("this")) : weaved, arguments);
+                        newCall = callX(inClosure ? classX(traitHelperClass) : call.getObjectExpression(), methodName, newArgs);
+                        newCall.setImplicitThis(true);
+                        newCall.setSafe(call.isSafe());
                     }
-                    return transformPrivateMethodCallOnThis(call, arguments, methodName);
+                    newCall.setSpreadSafe(call.isSpreadSafe());
+                    newCall.setSourcePosition(call);
+                    return newCall;
                 }
             }
         }
 
-        if (inClosure) {
-            return transformMethodCallOnThisInClosure(call);
-        }
-
-        return transformMethodCallOnThisFallBack(call, method, arguments);
-
-    }
-
-    private Expression transformMethodCallOnThisFallBack(final MethodCallExpression call,
-                                                         final Expression method, final Expression arguments) {
-        MethodCallExpression transformed = new MethodCallExpression(
-                weaved,
-                method,
-                transform(arguments)
-        );
-        transformed.setSourcePosition(call);
-        transformed.setSafe(call.isSafe());
-        transformed.setSpreadSafe(call.isSpreadSafe());
-        transformed.setImplicitThis(false);
-        return transformed;
-    }
-
-    private Expression transformMethodCallOnThisInClosure(final MethodCallExpression call) {
-        MethodCallExpression transformed = new MethodCallExpression(
-                (Expression) call.getReceiver(),
-                call.getMethod(),
-                transform(call.getArguments())
-        );
-        transformed.setSourcePosition(call);
-        transformed.setSafe(call.isSafe());
-        transformed.setSpreadSafe(call.isSpreadSafe());
-        transformed.setImplicitThis(call.isImplicitThis());
-        return transformed;
-    }
-
-    private Expression transformPrivateMethodCallOnThis(final MethodCallExpression call,
-                                                        final Expression arguments, final String methodName) {
-        ArgumentListExpression newArgs = createArgumentList(arguments);
-        MethodCallExpression transformed = new MethodCallExpression(
-                new VariableExpression("this"),
-                methodName,
-                newArgs
-        );
-        transformed.setSourcePosition(call);
-        transformed.setSafe(call.isSafe());
-        transformed.setSpreadSafe(call.isSpreadSafe());
-        transformed.setImplicitThis(true);
-        return transformed;
-    }
-
-    private Expression transformPrivateMethodCallOnThisInClosure(final MethodCallExpression call,
-                                                                 final Expression arguments, final String methodName) {
-        ArgumentListExpression newArgs = createArgumentList(arguments);
-        MethodCallExpression transformed = new MethodCallExpression(
-                new ClassExpression(traitHelperClass),
-                methodName,
-                newArgs
-        );
-        transformed.setSourcePosition(call);
-        transformed.setSafe(call.isSafe());
-        transformed.setSpreadSafe(call.isSpreadSafe());
-        transformed.setImplicitThis(true);
-        return transformed;
-    }
-
-    private Expression createFieldHelperReceiver() {
-        return ClassHelper.CLASS_Type.equals(weaved.getOriginType()) ? weaved : new CastExpression(fieldHelper, weaved);
+        MethodCallExpression newCall = callX(inClosure ? call.getObjectExpression() : weaved, method, transform(arguments));
+        newCall.setImplicitThis(inClosure ? call.isImplicitThis() : false);
+        newCall.setSafe(call.isSafe());
+        newCall.setSourcePosition(call);
+        newCall.setSpreadSafe(call.isSpreadSafe());
+        return newCall;
     }
 
-    private ArgumentListExpression createArgumentList(final Expression origCallArgs) {
+    private ArgumentListExpression createArgumentList(final Expression self, final Expression arguments) {
         ArgumentListExpression newArgs = new ArgumentListExpression();
-        newArgs.addExpression(new VariableExpression(weaved));
-        if (origCallArgs instanceof TupleExpression) {
-            List<Expression> expressions = ((TupleExpression) origCallArgs).getExpressions();
-            for (Expression expression : expressions) {
-                newArgs.addExpression(transform(expression));
+        newArgs.addExpression(self);
+        if (arguments instanceof TupleExpression) {
+            for (Expression argument : (TupleExpression) arguments) {
+                newArgs.addExpression(transform(argument));
             }
         } else {
-            newArgs.addExpression(origCallArgs);
+            newArgs.addExpression(transform(arguments));
         }
         return newArgs;
     }
+
+    private static Expression asClass(final Expression e) {
+        ClassNode rawClass = ClassHelper.CLASS_Type.getPlainNodeReference();
+        return ternaryX(isInstanceOfX(e, rawClass), e, callX(e, "getClass"));
+    }
+
+    private Expression createFieldHelperReceiver() {
+        return weaved.getOriginType().equals(ClassHelper.CLASS_Type) ? weaved : castX(fieldHelper, weaved);
+    }
 }
diff --git a/src/test/groovy/transform/stc/BugsSTCTest.groovy b/src/test/groovy/transform/stc/BugsSTCTest.groovy
index 0f70397..6635e0b 100644
--- a/src/test/groovy/transform/stc/BugsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/BugsSTCTest.groovy
@@ -100,6 +100,40 @@ class BugsSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot find matching method <UnionType:C1+TT>#c2'
     }
 
+    // GROOVY-10106
+    void testCallStaticOrPrivateMethodInTraitFieldInitializer() {
+        ['private', 'static', 'private static'].each { mods ->
+            assertScript """
+                class C {
+                    String s
+                }
+                trait T {
+                    final C c = new C().tap {
+                        config(it)
+                    }
+                    $mods void config(C c) {
+                        c.s = 'x'
+                    }
+                }
+                class U implements T {
+                }
+                def c = new U().c
+                assert c.s == 'x'
+            """
+        }
+
+        shouldFailWithMessages '''
+            trait T {
+                def obj = new Object().tap {
+                    config(it)
+                }
+                static void config(String s) {
+                }
+            }
+        ''',
+        'Cannot find matching method T$Trait$Helper#config(java.lang.Class, java.lang.Object)'
+    }
+
     void testGroovy5444() {
         assertScript '''
                 def curr = { System.currentTimeMillis() }

[groovy] 07/11: GROOVY-10164: make RootLoader(ClassLoader) public

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 32e33fee3f09c5f4b1b8e9e5e37ce6c21bb2298c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 16 11:48:04 2021 -0500

    GROOVY-10164: make RootLoader(ClassLoader) public
---
 src/main/java/org/codehaus/groovy/tools/RootLoader.java | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/tools/RootLoader.java b/src/main/java/org/codehaus/groovy/tools/RootLoader.java
index 46e0d5f..dfd42ad 100644
--- a/src/main/java/org/codehaus/groovy/tools/RootLoader.java
+++ b/src/main/java/org/codehaus/groovy/tools/RootLoader.java
@@ -74,7 +74,7 @@ import java.util.Map;
  */
 public class RootLoader extends URLClassLoader {
     private static final URL[] EMPTY_URL_ARRAY = new URL[0];
-    private final Map<String, Class> customClasses = new HashMap<String, Class>();
+    private final Map<String, Class> customClasses = new HashMap<>();
     private static final String ORG_W3C_DOM_NODE = "org.w3c.dom.Node";
 
     /**
@@ -82,7 +82,7 @@ public class RootLoader extends URLClassLoader {
      *
      * @param parent the parent Loader
      */
-    private RootLoader(ClassLoader parent) {
+    public RootLoader(ClassLoader parent) {
         this(EMPTY_URL_ARRAY, parent);
     }
 

[groovy] 09/11: GROOVY-10179: STC: for-in collection type: consider instanceof flow-type

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 b47886f3bb40db4698ba25d202c0d3180d56792f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 23 14:24:04 2021 -0500

    GROOVY-10179: STC: for-in collection type: consider instanceof flow-type
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  7 ++-
 src/test/groovy/transform/stc/LoopsSTCTest.groovy  | 66 ++++++++++++++++++++-
 .../classgen/asm/sc/bugs/Groovy6240Bug.groovy      | 69 ----------------------
 3 files changed, 69 insertions(+), 73 deletions(-)

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 6fdcef8..013aea9 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1901,7 +1901,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             super.visitForLoop(forLoop);
         } else {
             collectionExpression.visit(this);
-            final ClassNode collectionType = getType(collectionExpression);
+            ClassNode collectionType;
+            if (collectionExpression instanceof VariableExpression && hasInferredReturnType(collectionExpression)) {
+                collectionType = getInferredReturnType(collectionExpression);
+            } else {
+                collectionType = getType(collectionExpression);
+            }
             ClassNode forLoopVariableType = forLoop.getVariableType();
             ClassNode componentType;
             if (Character_TYPE.equals(ClassHelper.getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) {
diff --git a/src/test/groovy/transform/stc/LoopsSTCTest.groovy b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
index 6a9bff6..2798cfb 100644
--- a/src/test/groovy/transform/stc/LoopsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/LoopsSTCTest.groovy
@@ -128,9 +128,9 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
     }
 
     // GROOVY-5587
-    void testMapEntryInForInLoop() {
+    void testForInLoopOnMap1() {
         assertScript '''
-            @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 lookup('forLoop').each {
                     assert it instanceof org.codehaus.groovy.ast.stmt.ForStatement
                     def collection = it.collectionExpression // MethodCallExpression
@@ -157,6 +157,67 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-6240
+    void testForInLoopOnMap2() {
+        assertScript '''
+            Map<String, Integer> map = [foo: 123, bar: 456]
+            for (entry in map) {
+                assert entry.key.reverse() in ['oof','rab']
+                assert entry.value * 2 in [246, 912]
+            }
+        '''
+    }
+
+    void testForInLoopOnMap3() {
+        assertScript '''
+            class MyMap extends LinkedHashMap<String,Integer> {
+            }
+            def map = new MyMap([foo: 123, bar: 456])
+            for (entry in map) {
+                assert entry.key.reverse() in ['oof','rab']
+                assert entry.value * 2 in [246, 912]
+            }
+        '''
+    }
+
+    // GROOVY-10179
+    void testForInLoopOnMap4() {
+        assertScript '''
+            void test(args) {
+                if (args instanceof Map) {
+                    for (e in args) {
+                        print "$e.key $e.value"
+                    }
+                }
+            }
+            test(a:1,b:2,c:3.14)
+        '''
+    }
+
+    // GROOVY-6123
+    void testForInLoopOnEnumeration() {
+        assertScript '''
+            Vector<String> v = new Vector<>()
+            v.add('ooo')
+            def en = v.elements()
+            for (e in en) {
+                assert e.toUpperCase() == 'OOO'
+            }
+            v.add('groovy')
+            en = v.elements()
+            for (e in en) {
+                assert e.toUpperCase() == 'OOO'
+                break
+            }
+
+            en = v.elements()
+            for (e in en) {
+                assert e.toUpperCase() in ['OOO','GROOVY']
+                if (e=='ooo') continue
+            }
+        '''
+    }
+
     void testShouldNotInferSoftReferenceAsComponentType() {
         assertScript '''import java.lang.reflect.Field
             import org.codehaus.groovy.ast.stmt.ForStatement
@@ -233,4 +294,3 @@ class LoopsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 }
-
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy
deleted file mode 100644
index f263a44..0000000
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy6240Bug.groovy
+++ /dev/null
@@ -1,69 +0,0 @@
-/*
- *  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 org.codehaus.groovy.classgen.asm.sc.bugs
-
-import groovy.transform.stc.StaticTypeCheckingTestCase
-import org.codehaus.groovy.classgen.asm.sc.StaticCompilationTestSupport
-
-class Groovy6240Bug extends StaticTypeCheckingTestCase implements StaticCompilationTestSupport {
-    void testGroovyAllowsIteratingOnMapDirectlyWithForEachLoop() {
-        assertScript '''
-            Map<String, Integer> map = [foo: 123, bar: 456]
-            for (entry in map) {
-                assert entry.key.reverse() in ['oof','rab']
-                assert entry.value * 2 in [246, 912]
-            }
-        '''
-    }
-
-    void testGroovyAllowsIteratingOnMapDirectlyWithForEachLoopCustomMapType() {
-        assertScript '''
-            class MyMap extends LinkedHashMap<String,Integer>{}
-            def map = new MyMap([foo: 123, bar: 456])
-            for (entry in map) {
-                assert entry.key.reverse() in ['oof','rab']
-                assert entry.value * 2 in [246, 912]
-            }
-        '''
-    }
-
-    // GROOVY-6123
-    void testGroovyAllowsIteratingOnEnumerationDirectlyWithForEachLoop() {
-        assertScript '''
-            Vector<String> v = new Vector<>()
-            v.add('ooo')
-            def en = v.elements()
-            for (e in en) {
-                assert e.toUpperCase() == 'OOO'
-            }
-            v.add('groovy')
-            en = v.elements()
-            for (e in en) {
-                assert e.toUpperCase() == 'OOO'
-                break
-            }
-
-            en = v.elements()
-            for (e in en) {
-                assert e.toUpperCase() in ['OOO','GROOVY']
-                if (e=='ooo') continue
-            }
-        '''
-    }
-}

[groovy] 02/11: GROOVY-10027: NamedParam: check against declared/inferred argument type

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 19d3a603ba04d4aa49095aec20b5b448b7189b96
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Apr 9 14:31:37 2021 -0500

    GROOVY-10027: NamedParam: check against declared/inferred argument type
    
    Conflicts:
    	src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 23 ++++---
 src/test/groovy/NamedParameterTest.groovy          | 80 ++++++++++++++++++----
 2 files changed, 80 insertions(+), 23 deletions(-)

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 3cea7e5..b262e7f 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2797,19 +2797,26 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
         if (!entries.keySet().contains(name)) {
             if (required) {
-                addStaticTypeError("required named arg '" + name + "' not found.", expression);
+                addStaticTypeError("required named param '" + name + "' not found.", expression);
             }
-        } else {
-            Expression supplied = entries.get(name);
-            if (isCompatibleType(expectedType, expectedType != null, supplied.getType())) {
-                addStaticTypeError("parameter for named arg '" + name + "' has type '" + prettyPrintType(supplied.getType()) +
-                        "' but expected '" + prettyPrintType(expectedType) + "'.", expression);
+        } else if (expectedType != null) {
+            ClassNode argumentType = getDeclaredOrInferredType(entries.get(name));
+            if (!isAssignableTo(argumentType, expectedType)) {
+                addStaticTypeError("argument for named param '" + name + "' has type '" + prettyPrintType(argumentType) + "' but expected '" + prettyPrintType(expectedType) + "'.", expression);
             }
         }
     }
 
-    private boolean isCompatibleType(ClassNode expectedType, boolean b, ClassNode type) {
-        return b && !isAssignableTo(type, expectedType);
+    private ClassNode getDeclaredOrInferredType(Expression expression) {
+        ClassNode declaredOrInferred;
+        // in case of "T t = new ExtendsOrImplementsT()", return T for the expression type
+        if (expression instanceof Variable && !((Variable) expression).isDynamicTyped()) {
+            declaredOrInferred = getOriginalDeclarationType(expression);
+        } else {
+            declaredOrInferred = getType(expression);
+        }
+        // apply instanceof constraints to either option
+        return getInferredTypeFromTempInfo(expression, declaredOrInferred);
     }
 
     /**
diff --git a/src/test/groovy/NamedParameterTest.groovy b/src/test/groovy/NamedParameterTest.groovy
index b0cc07b..5a5b96d 100644
--- a/src/test/groovy/NamedParameterTest.groovy
+++ b/src/test/groovy/NamedParameterTest.groovy
@@ -24,12 +24,12 @@ import groovy.transform.TypeChecked
 
 import static groovy.NamedParameterHelper.myJavaMethod
 
-class NamedParameterTest extends GroovyTestCase {
+final class NamedParameterTest extends GroovyTestCase {
 
     void testPassingNamedParametersToMethod() {
         someMethod(name:"gromit", eating:"nice cheese", times:2)
     }
-    
+
     protected void someMethod(args) {
         assert args.name == "gromit"
         assert args.eating == "nice cheese"
@@ -69,12 +69,15 @@ class NamedParameterTest extends GroovyTestCase {
             import groovy.transform.TypeChecked
             import static groovy.NamedParameterTest.myMethod
 
+            int getAnswer() { 42 }
+
             @TypeChecked
-            def method() {            
-                assert myMethod(foo: 'FOO', bar: 'BAR') == 'foo = FOO, bar = BAR'
-                assert myMethod(bar: 'BAR') == 'foo = null, bar = BAR'
-                assert myMethod(foo: 'FOO', bar: 45, 442) == 'foo = FOO, bar = 45, num = 442'
-                assert myMethod(foo: 'FOO', 542) == 'foo = FOO, bar = null, num = 542'
+            def method() {
+                assert myMethod(foo: 'FOO', bar: 'BAR')          == 'foo = FOO, bar = BAR'
+                assert myMethod(bar: 'BAR')                      == 'foo = null, bar = BAR'
+                assert myMethod(foo: 'FOO', bar: 45, 442)        == 'foo = FOO, bar = 45, num = 442'
+                assert myMethod(foo: 'FOO', 542)                 == 'foo = FOO, bar = null, num = 542'
+                assert myMethod(foo: 'string', bar: answer, 666) == 'foo = string, bar = 42, num = 666' // GROOVY-10027
             }
             method()
         '''
@@ -86,12 +89,12 @@ class NamedParameterTest extends GroovyTestCase {
             import static groovy.NamedParameterTest.myMethod
 
             @TypeChecked
-            def method() {            
+            def method() {
                 myMethod(foo: 'FOO')
             }
             method()
         '''
-        assert message.contains("required named arg 'bar' not found")
+        assert message.contains("required named param 'bar' not found")
     }
 
     void testUnknownName() {
@@ -100,7 +103,7 @@ class NamedParameterTest extends GroovyTestCase {
             import static groovy.NamedParameterTest.myMethod
 
             @TypeChecked
-            def method() {            
+            def method() {
                 myMethod(bar: 'BAR', baz: 'BAZ')
             }
             method()
@@ -108,20 +111,67 @@ class NamedParameterTest extends GroovyTestCase {
         assert message.contains("unexpected named arg: baz")
     }
 
-    void testInvalidType() {
+    // GROOVY-10027
+    void testFlowType() {
+        assertScript '''
+            import groovy.transform.TypeChecked
+            import static groovy.NamedParameterTest.myMethod
+
+            @TypeChecked
+            def method(arg) {
+                if (arg instanceof Integer) {
+                    myMethod(foo: 'x', bar: arg, 123)
+                }
+            }
+            assert method(42) == 'foo = x, bar = 42, num = 123'
+        '''
+    }
+
+    void testInvalidType1() {
         def message = shouldFail '''
             import groovy.transform.TypeChecked
             import static groovy.NamedParameterTest.myMethod
 
             @TypeChecked
-            def method() {            
-                myMethod(foo: 42, 42)
+            def method() {
+                myMethod(foo:42, -1)
+            }
+        '''
+        assert message.contains("argument for named param 'foo' has type 'int' but expected 'java.lang.String'")
+    }
+
+    void testInvalidType2() {
+        def message = shouldFail '''
+            import groovy.transform.TypeChecked
+            import static groovy.NamedParameterTest.myMethod
+
+            @TypeChecked
+            def method() {
+                int answer = 42
+                myMethod(foo:answer, -1)
+            }
+        '''
+        assert message.contains("argument for named param 'foo' has type 'int' but expected 'java.lang.String'")
+    }
+
+    // GROOVY-10027
+    void testInvalidType3() {
+        def message = shouldFail '''
+            import groovy.transform.TypeChecked
+            import static groovy.NamedParameterTest.myMethod
+
+            int getAnswer() { 42 }
+
+            @TypeChecked
+            def method() {
+                myMethod(foo:answer, -1)
             }
-            method()
         '''
-        assert message.contains("parameter for named arg 'foo' has type 'int' but expected 'java.lang.String'")
+        assert message.contains("argument for named param 'foo' has type 'int' but expected 'java.lang.String'")
     }
 
+    //--------------------------------------------------------------------------
+
     static String myMethod(@NamedParams([
             @NamedParam(value = "foo"),
             @NamedParam(value = "bar", type = String, required = true)

[groovy] 05/11: GROOVY-10112: `IndexedProperty` shouldn't add setter for immutable 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 ac2f471db14979d1510ef5018c26f7c934882246
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu May 27 15:48:40 2021 +1000

    GROOVY-10112: `IndexedProperty` shouldn't add setter for immutable field
---
 .../groovy/groovy/transform/IndexedProperty.java   |  3 ++-
 .../transform/ImmutableASTTransformation.java      |  1 +
 .../IndexedPropertyASTTransformation.java          |  5 ++--
 .../transform/IndexedPropertyTransformTest.groovy  | 30 +++++++++++++++++++---
 4 files changed, 32 insertions(+), 7 deletions(-)

diff --git a/src/main/groovy/groovy/transform/IndexedProperty.java b/src/main/groovy/groovy/transform/IndexedProperty.java
index 9ec47b4..d395ce4 100644
--- a/src/main/groovy/groovy/transform/IndexedProperty.java
+++ b/src/main/groovy/groovy/transform/IndexedProperty.java
@@ -28,7 +28,8 @@ import java.lang.annotation.Target;
 /**
  * Field annotation used with properties to provide an indexed getter and setter for the property.
  * Groovy provides nice GPath syntax support for accessing indexed properties but Java tools
- * or frameworks may expect the JavaBean style setters and getters.
+ * or frameworks may expect the JavaBean style getters and setters.
+ * Only the getter is produced when an immutable field can be determined.
  * <p>
  * <em>Example usage:</em> suppose you have a class with the following properties:
  * <pre>
diff --git a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
index b81046f..3f07cb4 100644
--- a/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/ImmutableASTTransformation.java
@@ -220,6 +220,7 @@ public class ImmutableASTTransformation extends AbstractASTTransformation implem
     private static void adjustPropertyForImmutability(PropertyNode pNode, List<PropertyNode> newNodes, PropertyHandler handler) {
         final FieldNode fNode = pNode.getField();
         fNode.setModifiers((pNode.getModifiers() & (~ACC_PUBLIC)) | ACC_FINAL | ACC_PRIVATE);
+        fNode.setNodeMetaData("_IMMUTABLE_BREADCRUMB", Boolean.TRUE);
         pNode.setSetterBlock(null);
         Statement getter = handler.createPropGetter(pNode);
         if (getter != null) {
diff --git a/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java b/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
index a448cca..4c372f1 100644
--- a/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/IndexedPropertyASTTransformation.java
@@ -68,12 +68,13 @@ public class IndexedPropertyASTTransformation extends AbstractASTTransformation
                 return;
             }
             ClassNode fType = fNode.getType();
+            boolean readOnly = Boolean.TRUE.equals(fNode.getNodeMetaData("_IMMUTABLE_BREADCRUMB"));
             if (fType.isArray()) {
-                addArraySetter(fNode);
                 addArrayGetter(fNode);
+                if (!readOnly) addArraySetter(fNode);
             } else if (fType.isDerivedFrom(LIST_TYPE)) {
-                addListSetter(fNode);
                 addListGetter(fNode);
+                if (!readOnly) addListSetter(fNode);
             } else {
                 addError("Error during " + MY_TYPE_NAME + " processing. Non-Indexable property '" + fNode.getName() +
                         "' found. Type must be array or list but found " + fType.getName(), fNode);
diff --git a/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy b/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
index df4f8ff..a6d0844 100644
--- a/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/IndexedPropertyTransformTest.groovy
@@ -24,7 +24,7 @@ package org.codehaus.groovy.transform
 class IndexedPropertyTransformTest extends GroovyShellTestCase {
 
     void testStandardCase() {
-        assertScript """
+        assertScript '''
             import groovy.transform.IndexedProperty
             class Demo {
                 @IndexedProperty List<Integer> foo
@@ -44,11 +44,11 @@ class IndexedPropertyTransformTest extends GroovyShellTestCase {
             d.baz = ['cat']
             d.setBaz(0, 'dog')
             assert d.getBaz(0) == 'dog'
-        """
+        '''
     }
 
     void testWithCompileStatic() {
-        assertScript """
+        assertScript '''
             import groovy.transform.IndexedProperty
             @groovy.transform.CompileStatic
             class Demo {
@@ -69,7 +69,29 @@ class IndexedPropertyTransformTest extends GroovyShellTestCase {
             d.baz = ['cat']
             d.setBaz(0, 'dog')
             assert d.getBaz(0) == 'dog'
-        """
+        '''
+    }
+
+    void testReadOnlyProperty() {
+        assertScript '''
+            import groovy.transform.*
+            import static groovy.test.GroovyAssert.shouldFail
+
+            class Demo1 {
+                @IndexedProperty List<Integer> foo
+            }
+            @Immutable
+            class Demo2 {
+                @IndexedProperty List<Integer> foo
+            }
+
+            assert Demo1.getMethod('getFoo', int)
+            assert Demo1.getMethod('setFoo', int, Integer)
+            assert Demo2.getMethod('getFoo', int)
+            shouldFail(NoSuchMethodException) {
+                Demo2.getMethod('setFoo', int, Integer)
+            }
+        '''
     }
 
 }
\ No newline at end of file

[groovy] 11/11: GROOVY-10199: ASTTest: evaluate with compliation unit's transform loader

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 3811bf13ea83fa6ce28b7ade9b21f46ab64a137f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 12 15:25:51 2021 -0500

    GROOVY-10199: ASTTest: evaluate with compliation unit's transform loader
    
    Conflicts:
    	src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
---
 .../groovy/transform/ASTTestTransformation.groovy  | 75 ++++++++++------------
 src/test/groovy/bugs/Groovy10199.groovy            | 35 ++++++++++
 2 files changed, 69 insertions(+), 41 deletions(-)

diff --git a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
index 6982b86..c855948 100644
--- a/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
+++ b/src/main/groovy/org/codehaus/groovy/transform/ASTTestTransformation.groovy
@@ -46,14 +46,15 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.classX
 import static org.codehaus.groovy.ast.tools.GeneralUtils.propX
 
 @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
-class ASTTestTransformation extends AbstractASTTransformation implements CompilationUnitAware {
-    private CompilationUnit compilationUnit
+class ASTTestTransformation implements ASTTransformation, CompilationUnitAware {
 
-    @SuppressWarnings('Instanceof')
+    CompilationUnit compilationUnit
+
+    @Override
     void visit(final ASTNode[] nodes, final SourceUnit source) {
         AnnotationNode annotationNode = nodes[0]
         def member = annotationNode.getMember('phase')
-        def phase = null
+        CompilePhase phase = null
         if (member) {
             if (member instanceof VariableExpression) {
                 phase = CompilePhase.valueOf(member.text)
@@ -69,35 +70,32 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
         if (!member && !annotationNode.getNodeMetaData(ASTTestTransformation)) {
             throw new SyntaxException('Missing test expression', annotationNode.lineNumber, annotationNode.columnNumber)
         }
-        // convert value into node metadata so that the expression doesn't mix up with other AST xforms like type checking
-        annotationNode.putNodeMetaData(ASTTestTransformation, member)
+        // convert value into node metadata so that the expression doesn't mix up with other AST xforms like STC
+        annotationNode.setNodeMetaData(ASTTestTransformation, member)
         annotationNode.members.remove('value')
 
         def pcallback = compilationUnit.progressCallback
         def callback = new CompilationUnit.ProgressCallback() {
-            Binding binding = new Binding([:].withDefault { null })
+            private final Binding binding = new Binding([:].withDefault { null })
 
             @Override
-            void call(final ProcessingUnit context, final int phaseRef) {
-                if (phase == null || phaseRef == phase.phaseNumber) {
+            void call(final ProcessingUnit context, final int phaseNumber) {
+                if (phase == null || phaseNumber == phase.phaseNumber) {
                     ClosureExpression testClosure = nodes[0].getNodeMetaData(ASTTestTransformation)
                     StringBuilder sb = new StringBuilder()
-                    for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i++) {
+                    for (int i = testClosure.lineNumber; i <= testClosure.lastLineNumber; i += 1) {
                         sb.append(source.source.getLine(i, new Janitor())).append('\n')
                     }
                     def testSource = sb[testClosure.columnNumber..<sb.length()]
                     testSource = testSource[0..<testSource.lastIndexOf('}')]
-                    CompilerConfiguration config = new CompilerConfiguration()
-                    def customizer = new ImportCustomizer()
-                    config.addCompilationCustomizers(customizer)
-                    binding['sourceUnit'] = source
+
                     binding['node'] = nodes[1]
-                    binding['lookup'] = new MethodClosure(LabelFinder, 'lookup').curry(nodes[1])
+                    binding['sourceUnit'] = source
                     binding['compilationUnit'] = compilationUnit
-                    binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseRef)
-
-                    GroovyShell shell = new GroovyShell(binding, config)
+                    binding['compilePhase'] = CompilePhase.fromPhaseNumber(phaseNumber)
+                    binding['lookup'] = new MethodClosure(LabelFinder, 'lookup').curry(nodes[1])
 
+                    def customizer = new ImportCustomizer()
                     source.AST.imports.each {
                         customizer.addImport(it.alias, it.type.name)
                     }
@@ -110,7 +108,11 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
                     source.AST.staticStarImports.each {
                         customizer.addStaticStars(it.value.className)
                     }
-                    shell.evaluate(testSource)
+
+                    def config = new CompilerConfiguration()
+                    config.addCompilationCustomizers(customizer)
+                    def loader = compilationUnit.transformLoader
+                    new GroovyShell(loader, binding, config).evaluate(testSource)
                 }
             }
         }
@@ -127,15 +129,11 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
         compilationUnit.progressCallback = callback
     }
 
-    void setCompilationUnit(final CompilationUnit unit) {
-        this.compilationUnit = unit
-    }
-
     private static class AssertionSourceDelegatingSourceUnit extends SourceUnit {
         private final ReaderSource delegate
 
-        AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration flags, final GroovyClassLoader loader, final ErrorCollector er) {
-            super(name, '', flags, loader, er)
+        AssertionSourceDelegatingSourceUnit(final String name, final ReaderSource source, final CompilerConfiguration config, final GroovyClassLoader loader, final ErrorCollector er) {
+            super(name, '', config, loader, er)
             delegate = source
         }
 
@@ -151,8 +149,7 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
                     if (column > 40) {
                         int start = column - 30 - 1
                         int end = (column + 10 > text.length() ? text.length() : column + 10 - 1)
-                        sample = '   ' + text[start..<end] + Utilities.eol() + '   ' +
-                                marker[start..<marker.length()]
+                        sample = '   ' + text[start..<end] + Utilities.eol() + '   ' + marker[start..<marker.length()]
                     } else {
                         sample = '   ' + text + Utilities.eol() + '   ' + marker
                     }
@@ -162,23 +159,21 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
             }
             sample
         }
-
     }
-    
-    private static class ProgressCallbackChain extends CompilationUnit.ProgressCallback {
 
-        private final List<CompilationUnit.ProgressCallback> chain = new LinkedList<CompilationUnit.ProgressCallback>()
+    private static class ProgressCallbackChain extends CompilationUnit.ProgressCallback {
+        private final List<CompilationUnit.ProgressCallback> chain = [] as LinkedList
 
-        ProgressCallbackChain(CompilationUnit.ProgressCallback... callbacks) {
-            if (callbacks!=null) {
+        ProgressCallbackChain(final CompilationUnit.ProgressCallback... callbacks) {
+            if (callbacks) {
                 callbacks.each { addCallback(it) }
             }
         }
 
-        void addCallback(CompilationUnit.ProgressCallback callback) {
+        void addCallback(final CompilationUnit.ProgressCallback callback) {
             chain << callback
         }
-        
+
         @Override
         void call(final ProcessingUnit context, final int phase) {
             chain*.call(context, phase)
@@ -187,14 +182,14 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
 
     static class LabelFinder extends ClassCodeVisitorSupport {
 
-        static List<Statement> lookup(MethodNode node, String label) {
+        static List<Statement> lookup(final MethodNode node, final String label) {
             LabelFinder finder = new LabelFinder(label, null)
             node.code.visit(finder)
 
             finder.targets
         }
 
-        static List<Statement> lookup(ClassNode node, String label) {
+        static List<Statement> lookup(final ClassNode node, final String label) {
             LabelFinder finder = new LabelFinder(label, null)
             node.methods*.code*.visit(finder)
             node.declaredConstructors*.code*.visit(finder)
@@ -204,8 +199,7 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
 
         private final String label
         private final SourceUnit unit
-
-        private final List<Statement> targets = new LinkedList<Statement>()
+        private final List<Statement> targets = [] as LinkedList
 
         LabelFinder(final String label, final SourceUnit unit) {
             this.label = label
@@ -220,12 +214,11 @@ class ASTTestTransformation extends AbstractASTTransformation implements Compila
         @Override
         protected void visitStatement(final Statement statement) {
             super.visitStatement(statement)
-            if (statement.statementLabel==label) targets << statement
+            if (label in statement.statementLabels) targets << statement
         }
 
         List<Statement> getTargets() {
             Collections.unmodifiableList(targets)
         }
     }
-
 }
diff --git a/src/test/groovy/bugs/Groovy10199.groovy b/src/test/groovy/bugs/Groovy10199.groovy
new file mode 100644
index 0000000..526f1ae
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy10199.groovy
@@ -0,0 +1,35 @@
+/*
+ *  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 org.junit.Test
+
+final class Groovy10199 {
+    @Test
+    void testTransformClasspath() {
+        def shell = new GroovyShell()
+        shell.classLoader.addClasspath('gradle/wrapper/gradle-wrapper.jar')
+        shell.evaluate '''
+            @groovy.transform.ASTTest(value={
+                org.gradle.wrapper.WrapperConfiguration // Cannot get property 'gradle' on null object
+            })
+            def var = null
+        '''
+    }
+}

[groovy] 10/11: GROOVY-10191: catch LinkageError during static inline

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 ca2629ac536ff69fba7ae1e985df2ba0afbca9ea
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Aug 12 15:53:22 2021 -0500

    GROOVY-10191: catch LinkageError during static inline
    
    (cherry picked from commit 18c9ab98ede3ca72856c03b127da41222ad9fc7e)
---
 .../apache/groovy/ast/tools/ExpressionUtils.java   |  4 +-
 src/test/groovy/bugs/Groovy10191.groovy            | 43 ++++++++++++++++++++++
 2 files changed, 45 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
index e7e162e..af20d2a 100644
--- a/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
+++ b/src/main/java/org/apache/groovy/ast/tools/ExpressionUtils.java
@@ -234,7 +234,7 @@ public final class ExpressionUtils {
                             ce3.setSourcePosition(exp);
                             return ce3;
                         }
-                    } catch(Exception e) {
+                    } catch (Exception | LinkageError e) {
                         // ignore, leave property expression in place and we'll report later
                     }
                 }
@@ -276,7 +276,7 @@ public final class ExpressionUtils {
                 Expression transformed = transformInlineConstants(e, attrType);
                 newList.addExpression(transformed);
                 if (transformed != e) changed = true;
-            } catch(Exception ignored) {
+            } catch (Exception ignored) {
                 newList.addExpression(e);
             }
         }
diff --git a/src/test/groovy/bugs/Groovy10191.groovy b/src/test/groovy/bugs/Groovy10191.groovy
new file mode 100644
index 0000000..96cab84
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy10191.groovy
@@ -0,0 +1,43 @@
+/*
+ *  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 org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy10191 {
+
+    static class Foo {
+        public static final BAR = 'baz'
+        static {
+            throw new NoSuchMethodError('simulate complex init')
+        }
+    }
+
+    @Test
+    void testStaticInlining() {
+        assertScript """
+            class C {
+                private static final x = ${getClass().getName()}.Foo.BAR
+            }
+            assert true
+        """
+    }
+}

[groovy] 03/11: GROOVY-10037: add test case

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 50620d7d41bf733d6fb2f951b810af7ea40c4060
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Feb 1 10:33:01 2022 -0600

    GROOVY-10037: add test case
---
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   | 42 ++++++++++++++++++++++
 1 file changed, 42 insertions(+)

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 21c67ac..72d8508 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -721,6 +721,48 @@ final class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilati
         '''
     }
 
+    // GROOVY-10037
+    void testPrivateSetterWithDollarPrefix() {
+        assertScript '''
+            class C {
+              private int priv
+              public int pub
+
+              private void set$priv(int val) {
+                priv = val
+              }
+
+              private int get$priv() {
+                priv
+              }
+
+              public void set$pub(int val) {
+                pub = val
+              }
+
+              public int get$pub() {
+                pub
+              }
+
+              void test() { int lv
+                $priv = 20 // XXXX
+                lv = $priv // okay
+                $pub = 40  // okay
+                lv = $pub  // okay
+              }
+            }
+
+            class D extends C {
+            }
+
+            def c = new C()
+            c.test()
+
+            def d = new D()
+            d.test()
+        '''
+    }
+
     void testSuperMethodCallInSkippedSection() {
         assertScript '''
             class Top {