You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2020/08/09 02:35:27 UTC

[groovy] branch GROOVY_3_0_X updated (196ce03 -> 55429fb)

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

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


    from 196ce03  additional cases for test
     new 9476cb6  minor refactor
     new d7e9cdc  minor refactor
     new 21f8299  GROOVY-9386: traits: do not transform dynamic variable within closure
     new 3d6ca61  GROOVY-9255: transform "TraitType.super.name" to getName()/isName() call
     new d40744a  GROOVY-9673: do not set method target on call expr in case of overloads
     new 6db4549  GROOVY-9256: process closure expressions for Trait.super.name transforms
     new 55429fb  minor refactor

The 7 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:
 .../java/org/codehaus/groovy/syntax/Types.java     |   3 +
 .../transform/trait/SuperCallTraitTransformer.java | 213 +++++++++++--------
 .../transform/trait/TraitASTTransformation.java    | 228 ++++++++++-----------
 .../transform/trait/TraitReceiverTransformer.java  |   2 +-
 .../traitx/TraitASTTransformationTest.groovy       | 218 +++++++++++++++++++-
 5 files changed, 458 insertions(+), 206 deletions(-)


[groovy] 05/07: GROOVY-9673: do not set method target on call expr in case of overloads

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

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

commit d40744a3585a31e90d5d9a05d962318a85a3a750
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 08:55:36 2020 -0500

    GROOVY-9673: do not set method target on call expr in case of overloads
    
    closes #1338
    
    (cherry picked from commit dd2aca619f6bc6e2757e30bb075868202e635d0a)
---
 .../transform/trait/SuperCallTraitTransformer.java |  1 -
 .../traitx/TraitASTTransformationTest.groovy       | 43 +++++++++++++++++++++-
 2 files changed, 42 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index ba57ecc..08fe8d2 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -107,7 +107,6 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
                             setterCall.getObjectExpression().setSourcePosition(leftExpression.getObjectExpression());
                             setterCall.getMethod().setSourcePosition(leftExpression.getProperty());
                             setterCall.setSpreadSafe(leftExpression.isSpreadSafe());
-                            setterCall.setMethodTarget(method);
                             setterCall.setImplicitThis(false);
                             return setterCall;
                         }
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 5a57531..2d412a6 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1108,8 +1108,49 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test // GROOVY-9673
+    void testTraitSuperPropertySetWithOverloads() {
+        assertScript '''
+            trait T {
+              def setX(Number n) {
+                'Number'
+              }
+              def setX(String s) {
+                'String'
+              }
+            }
+
+            class C implements T {
+              def test() {
+                T.super.x = 42
+              }
+            }
+
+            assert new C().test() == 'Number'
+        '''
+
+        assertScript '''
+            trait T {
+              def setX(Number n) {
+                'Number'
+              }
+              def setX(String s) {
+                'String'
+              }
+            }
+
+            class C implements T {
+              def test() {
+                T.super.x = 'x'
+              }
+            }
+
+            assert new C().test() == 'String'
+        '''
+    }
+
     @Test
-    void testSuperCallInTraitExtendingAnotherTrait() {
+    void testTraitSuperCallWhenExtendingAnotherTrait() {
         assertScript '''
             trait Foo {
                 int foo() { 1 }


[groovy] 02/07: minor refactor

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

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

commit d7e9cdc24f1215ce83da0f1eb749efb73c973241
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 5 17:59:29 2020 -0500

    minor refactor
    
    (cherry picked from commit 7a4860efcf29bc82edcb35e4358248bba1407fb5)
---
 .../transform/trait/SuperCallTraitTransformer.java | 40 +++++++++-------------
 1 file changed, 17 insertions(+), 23 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index 76f5782..4eccccb 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -80,9 +80,9 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
                 PropertyExpression leftExpression = (PropertyExpression) bin.getLeftExpression();
                 ClassNode traitType = getTraitSuperTarget(leftExpression.getObjectExpression());
                 if (traitType != null) {
+                    ClassNode helperType = getHelper(traitType);
                     // TraitType.super.foo = ... -> TraitType$Helper.setFoo(this, ...)
 
-                    ClassNode helperType = getHelper(traitType);
                     String setterName = MetaProperty.getSetterName(leftExpression.getPropertyAsString());
                     for (MethodNode method : helperType.getMethods(setterName)) {
                         Parameter[] parameters = method.getParameters();
@@ -95,8 +95,8 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
                                             bin.getRightExpression()
                                     )
                             );
+                            setterCall.getObjectExpression().setSourcePosition(leftExpression.getObjectExpression());
                             setterCall.getMethod().setSourcePosition(leftExpression.getProperty());
-                            setterCall.getObjectExpression().setSourcePosition(traitType);
                             setterCall.setSpreadSafe(leftExpression.isSpreadSafe());
                             setterCall.setMethodTarget(method);
                             setterCall.setImplicitThis(false);
@@ -112,6 +112,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
     private Expression transformMethodCallExpression(final MethodCallExpression exp) {
         ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
         if (traitType != null) {
+            ClassNode helperType = getHelper(traitType);
             // TraitType.super.foo() -> TraitType$Helper.foo(this)
 
             ArgumentListExpression newArgs = new ArgumentListExpression();
@@ -126,11 +127,11 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
             }
 
             MethodCallExpression newCall = new MethodCallExpression(
-                    new ClassExpression(getHelper(traitType)),
+                    new ClassExpression(helperType),
                     transform(exp.getMethod()),
                     newArgs
             );
-            newCall.getObjectExpression().setSourcePosition(traitType);
+            newCall.getObjectExpression().setSourcePosition(((PropertyExpression) exp.getObjectExpression()).getObjectExpression());
             newCall.setSpreadSafe(exp.isSpreadSafe());
             newCall.setImplicitThis(false);
             return newCall;
@@ -138,31 +139,24 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         return super.transform(exp);
     }
 
-    private ClassNode getHelper(final ClassNode traitReceiver) {
-        if (helperClassNotCreatedYet(traitReceiver)) {
-            // GROOVY-7909: A Helper class in same compilation unit may have not been created when referenced
-            // Here create a symbol as a "placeholder" and it will be resolved later.
-            ClassNode ret = new InnerClassNode(
-                    traitReceiver,
-                    Traits.helperClassName(traitReceiver),
+    private ClassNode getHelper(final ClassNode traitType) {
+        // GROOVY-7909: A helper class in the same compilation unit may not have
+        // been created when referenced; create a placeholder to be resolved later.
+        if (!traitType.redirect().getInnerClasses().hasNext()
+                && getSourceUnit().getAST().getClasses().contains(traitType.redirect())) {
+            ClassNode helperType = new InnerClassNode(
+                    traitType,
+                    Traits.helperClassName(traitType),
                     ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_SYNTHETIC,
                     ClassHelper.OBJECT_TYPE,
                     ClassNode.EMPTY_ARRAY,
                     null
             ).getPlainNodeReference();
-
-            ret.setRedirect(null);
-            traitReceiver.redirect().setNodeMetaData(UNRESOLVED_HELPER_CLASS, ret);
-            return ret;
-        } else {
-            TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver);
-            return helpers.getHelper();
+            helperType.setRedirect(null);
+            traitType.redirect().setNodeMetaData(UNRESOLVED_HELPER_CLASS, helperType);
+            return helperType;
         }
-    }
-
-    private boolean helperClassNotCreatedYet(final ClassNode traitReceiver) {
-        return !traitReceiver.redirect().getInnerClasses().hasNext()
-                && getSourceUnit().getAST().getClasses().contains(traitReceiver.redirect());
+        return Traits.findHelper(traitType);
     }
 
     private ClassNode getTraitSuperTarget(final Expression exp) {


[groovy] 07/07: minor refactor

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

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

commit 55429fbfb37e409083fe776416c4af81aa689a8d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 10:50:37 2020 -0500

    minor refactor
    
    (cherry picked from commit 6eea0beb1386fe9e6bac39eda8fc27772ef48f1f)
---
 .../transform/trait/SuperCallTraitTransformer.java |   6 +-
 .../transform/trait/TraitASTTransformation.java    | 228 ++++++++++-----------
 .../traitx/TraitASTTransformationTest.groovy       | 116 ++++++-----
 3 files changed, 171 insertions(+), 179 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index edd1e12..e8f1c35 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -95,7 +95,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
                 ClassNode traitType = getTraitSuperTarget(leftExpression.getObjectExpression());
                 if (traitType != null) {
                     ClassNode helperType = getHelper(traitType);
-                    // TraitType.super.foo = ... -> TraitType$Helper.setFoo(this, ...)
+                    // TraitType.super.foo = ... -> TraitType$Trait$Helper.setFoo(this, ...)
 
                     String setterName = MetaProperty.getSetterName(leftExpression.getPropertyAsString());
                     for (MethodNode method : helperType.getMethods(setterName)) {
@@ -136,7 +136,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
             ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
             if (traitType != null) {
                 ClassNode helperType = getHelper(traitType);
-                // TraitType.super.foo -> TraitType$Helper.getFoo(this)
+                // TraitType.super.foo -> TraitType$Trait$Helper.getFoo(this)
 
                 Function<MethodNode, MethodCallExpression> xform = (methodNode) -> {
                     MethodCallExpression methodCall = new MethodCallExpression(
@@ -181,7 +181,7 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
         if (traitType != null) {
             ClassNode helperType = getHelper(traitType);
-            // TraitType.super.foo() -> TraitType$Helper.foo(this)
+            // TraitType.super.foo() -> TraitType$Trait$Helper.foo(this)
 
             ArgumentListExpression newArgs = new ArgumentListExpression();
             newArgs.addExpression(new VariableExpression("this"));
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 2daeae2..da8cf12 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -32,13 +32,8 @@ import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.PropertyNode;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.CastExpression;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.FieldExpression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.ast.stmt.BlockStatement;
@@ -53,13 +48,10 @@ import org.codehaus.groovy.control.CompilePhase;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.runtime.InvokerHelper;
 import org.codehaus.groovy.syntax.SyntaxException;
-import org.codehaus.groovy.syntax.Token;
-import org.codehaus.groovy.syntax.Types;
 import org.codehaus.groovy.transform.ASTTransformationCollectorCodeVisitor;
 import org.codehaus.groovy.transform.AbstractASTTransformation;
 import org.codehaus.groovy.transform.GroovyASTTransformation;
 
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.HashSet;
@@ -70,7 +62,19 @@ import java.util.Set;
 
 import static org.apache.groovy.ast.tools.AnnotatedNodeUtils.markAsGenerated;
 import static org.apache.groovy.ast.tools.MethodNodeUtils.getCodeAsBlock;
+import static org.apache.groovy.util.BeanUtils.capitalize;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+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.constX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.fieldX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.params;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
 import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRESOLVED_HELPER_CLASS;
 
 /**
@@ -85,21 +89,26 @@ import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRE
 @GroovyASTTransformation(phase = CompilePhase.SEMANTIC_ANALYSIS)
 public class TraitASTTransformation extends AbstractASTTransformation implements CompilationUnitAware {
 
-    public static final String DO_DYNAMIC = TraitReceiverTransformer.class+".doDynamic";
-    public static final String POST_TYPECHECKING_REPLACEMENT = TraitReceiverTransformer.class+".replacement";
+    public static final String DO_DYNAMIC = TraitReceiverTransformer.class + ".doDynamic";
+    public static final String POST_TYPECHECKING_REPLACEMENT = TraitReceiverTransformer.class + ".replacement";
 
     private static final ClassNode INVOKERHELPER_CLASSNODE = ClassHelper.make(InvokerHelper.class);
-
     private static final ClassNode OVERRIDE_CLASSNODE = ClassHelper.make(Override.class);
 
-    private SourceUnit unit;
+    private SourceUnit sourceUnit;
     private CompilationUnit compilationUnit;
 
-    public void visit(ASTNode[] nodes, SourceUnit source) {
+    @Override
+    public void setCompilationUnit(final CompilationUnit unit) {
+        this.compilationUnit = unit;
+    }
+
+    @Override
+    public void visit(final ASTNode[] nodes, final SourceUnit source) {
         AnnotatedNode parent = (AnnotatedNode) nodes[1];
         AnnotationNode anno = (AnnotationNode) nodes[0];
         if (!Traits.TRAIT_CLASSNODE.equals(anno.getClassNode())) return;
-        unit = source;
+        sourceUnit = source;
         init(nodes, source);
         if (parent instanceof ClassNode) {
             ClassNode cNode = (ClassNode) parent;
@@ -117,7 +126,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         if (helperClassNode == null) {
             return;
         }
-        for (ClassNode cNode : unit.getAST().getClasses()) {
+        for (ClassNode cNode : sourceUnit.getAST().getClasses()) {
             ClassNode unresolvedHelperNode = cNode.getNodeMetaData(UNRESOLVED_HELPER_CLASS);
             if (unresolvedHelperNode != null
                     && unresolvedHelperNode.getName().equals(helperClassNode.getName())) {
@@ -151,14 +160,13 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
 
     private void resolveScope(final ClassNode cNode) {
         // we need to resolve again!
-        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(unit);
+        VariableScopeVisitor scopeVisitor = new VariableScopeVisitor(sourceUnit);
         scopeVisitor.visitClass(cNode);
     }
 
     private void checkNoConstructor(final ClassNode cNode) {
         if (!cNode.getDeclaredConstructors().isEmpty()) {
-            addError("Error processing trait '" + cNode.getName() + "'. " +
-                    " Constructors are not allowed.", cNode);
+            addError("Error processing trait '" + cNode.getName() + "'. " + " Constructors are not allowed.", cNode);
         }
     }
 
@@ -182,8 +190,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         generatePropertyMethods(cNode);
 
         // prepare fields
-        List<FieldNode> fields = new ArrayList<FieldNode>();
-        Set<String> fieldNames = new HashSet<String>();
+        List<FieldNode> fields = new ArrayList<>();
+        Set<String> fieldNames = new HashSet<>();
         boolean hasStatic = false;
         for (FieldNode field : cNode.getFields()) {
             if (!"metaClass".equals(field.getName()) && (!field.isSynthetic() || field.getName().indexOf('$') < 0)) {
@@ -200,28 +208,28 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
             fieldHelper = new InnerClassNode(
                     cNode,
                     Traits.fieldHelperClassName(cNode),
-                    ACC_STATIC | ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC,
+                    ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_SYNTHETIC,
                     ClassHelper.OBJECT_TYPE
             );
             if (hasStatic) {
                 staticFieldHelper = new InnerClassNode(
                         cNode,
                         Traits.staticFieldHelperClassName(cNode),
-                        ACC_STATIC | ACC_PUBLIC | ACC_INTERFACE | ACC_ABSTRACT | ACC_SYNTHETIC,
+                        ACC_PUBLIC | ACC_STATIC | ACC_ABSTRACT | ACC_INTERFACE | ACC_SYNTHETIC,
                         ClassHelper.OBJECT_TYPE
                 );
             }
         }
 
         // add methods
-        List<MethodNode> methods = new ArrayList<MethodNode>(cNode.getMethods());
-        List<MethodNode> nonPublicAPIMethods = new LinkedList<MethodNode>();
+        List<MethodNode> methods = new ArrayList<>(cNode.getMethods());
+        List<MethodNode> nonPublicAPIMethods = new LinkedList<>();
         List<Statement> staticInitStatements = null;
         for (final MethodNode methodNode : methods) {
             boolean declared = methodNode.getDeclaringClass() == cNode;
             if (declared) {
                 if (!methodNode.isSynthetic() && (methodNode.isProtected() || (!methodNode.isPrivate() && !methodNode.isPublic()))) {
-                    unit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")",
+                    sourceUnit.addError(new SyntaxException("Cannot have protected/package-private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")",
                             methodNode.getLineNumber(), methodNode.getColumnNumber()));
                     return null;
                 }
@@ -262,7 +270,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         BlockStatement toBlock = getBlockStatement(initializer, toCode);
         for (Statement next : initStatements) {
             Parameter selfParam = createSelfParameter(cNode, false);
-            toBlock.addStatement(processBody(new VariableExpression(selfParam), next, cNode, helper, fieldHelper, fieldNames));
+            toBlock.addStatement(processBody(varX(selfParam), next, cNode, helper, fieldHelper, fieldNames));
         }
         initStatements.clear();
 
@@ -273,7 +281,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         copyClassAnnotations(cNode, helper);
         markAsGenerated(cNode, helper);
 
-        fields = new ArrayList<FieldNode>(cNode.getFields()); // reuse the full list of fields
+        fields = new ArrayList<>(cNode.getFields()); // reuse the full list of fields
         for (FieldNode field : fields) {
             cNode.removeField(field.getName());
         }
@@ -281,11 +289,11 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         // visit AST xforms
         registerASTTransformations(helper);
 
-        unit.getAST().addClass(helper);
+        sourceUnit.getAST().addClass(helper);
         if (fieldHelper != null) {
-            unit.getAST().addClass(fieldHelper);
+            sourceUnit.getAST().addClass(fieldHelper);
             if (staticFieldHelper != null) {
-                unit.getAST().addClass(staticFieldHelper);
+                sourceUnit.getAST().addClass(staticFieldHelper);
             }
         }
 
@@ -300,22 +308,21 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         return helper;
     }
 
-    private BlockStatement getBlockStatement(MethodNode targetMethod, Statement code) {
-        BlockStatement toBlock;
+    private BlockStatement getBlockStatement(final MethodNode targetMethod, final Statement code) {
+        BlockStatement blockStmt;
         if (code instanceof BlockStatement) {
-            toBlock = (BlockStatement) code;
+            blockStmt = (BlockStatement) code;
         } else {
-            toBlock = new BlockStatement();
-            toBlock.addStatement(code);
-            targetMethod.setCode(toBlock);
+            blockStmt = block(code);
+            targetMethod.setCode(blockStmt);
         }
-        return toBlock;
+        return blockStmt;
     }
 
     private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) {
         MethodNode initializer = new MethodNode(
-                isStatic?Traits.STATIC_INIT_METHOD:Traits.INIT_METHOD,
-                ACC_STATIC | ACC_PUBLIC | ACC_SYNTHETIC,
+                isStatic ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD,
+                ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
                 ClassHelper.VOID_TYPE,
                 new Parameter[]{createSelfParameter(cNode, isStatic)},
                 ClassNode.EMPTY_ARRAY,
@@ -333,7 +340,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
 
     private void registerASTTransformations(final ClassNode helper) {
         {
-            GroovyClassVisitor visitor = new ASTTransformationCollectorCodeVisitor(unit, compilationUnit.getTransformLoader());
+            GroovyClassVisitor visitor = new ASTTransformationCollectorCodeVisitor(sourceUnit, compilationUnit.getTransformLoader());
             visitor.visitClass(helper);
         }
         // Perform an additional phase which has to be done *after* type checking
@@ -346,7 +353,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     }
 
     /**
-     * Copies annotation from the trait to the helper, excluding the trait annotation itself
+     * Copies annotation from the trait to the helper, excluding the trait annotation itself.
+     *
      * @param cNode the trait class node
      * @param helper the helper class node
      */
@@ -360,11 +368,10 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     }
 
     private void checkInnerClasses(final ClassNode cNode) {
-        Iterator<InnerClassNode> it = cNode.getInnerClasses();
-        while (it.hasNext()) {
+        for (Iterator<InnerClassNode> it = cNode.getInnerClasses(); it.hasNext(); ) {
             InnerClassNode origin = it.next();
             if ((origin.getModifiers() & ACC_STATIC) == 0) {
-                unit.addError(new SyntaxException("Cannot have non-static inner class inside a trait ("+origin.getName()+")", origin.getLineNumber(), origin.getColumnNumber()));
+                sourceUnit.addError(new SyntaxException("Cannot have non-static inner class inside a trait ("+origin.getName()+")", origin.getLineNumber(), origin.getColumnNumber()));
             }
         }
     }
@@ -376,87 +383,65 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     }
 
     /**
-     * Mostly copied from the {@link Verifier} class but does *not* generate bytecode
-     *
-     * @param cNode
-     * @param node
+     * Mostly copied from the {@link Verifier} class but does *not* generate bytecode.
      */
-    private static void processProperty(final ClassNode cNode, PropertyNode node) {
+    private static void processProperty(final ClassNode cNode, final PropertyNode node) {
         String name = node.getName();
         FieldNode field = node.getField();
-        int propNodeModifiers = node.getModifiers();
-
-        String getterName = "get" + Verifier.capitalize(name);
-        String setterName = "set" + Verifier.capitalize(name);
+        int propNodeModifiers = node.getModifiers() & 0x1F; // GROOVY-3726
 
-        // GROOVY-3726: clear volatile, transient modifiers so that they don't get applied to methods
-        if ((propNodeModifiers & Modifier.VOLATILE) != 0) {
-            propNodeModifiers = propNodeModifiers - Modifier.VOLATILE;
-        }
-        if ((propNodeModifiers & Modifier.TRANSIENT) != 0) {
-            propNodeModifiers = propNodeModifiers - Modifier.TRANSIENT;
-        }
+        String getterName = GeneralUtils.getGetterName(node);
+        String setterName = GeneralUtils.getSetterName(name);
 
         Statement getterBlock = node.getGetterBlock();
         if (getterBlock == null) {
             MethodNode getter = cNode.getGetterMethod(getterName);
-            if (getter == null && ClassHelper.boolean_TYPE == node.getType()) {
-                String secondGetterName = "is" + Verifier.capitalize(name);
-                getter = cNode.getGetterMethod(secondGetterName);
+            if (getter == null && node.getType().equals(ClassHelper.boolean_TYPE)) {
+                getter = cNode.getGetterMethod("is" + capitalize(name));
             }
             if (!node.isPrivate() && methodNeedsReplacement(cNode, getter)) {
-                getterBlock = new ExpressionStatement(new FieldExpression(field));
+                getterBlock = stmt(fieldX(field));
             }
         }
         Statement setterBlock = node.getSetterBlock();
         if (setterBlock == null) {
             // 2nd arg false below: though not usual, allow setter with non-void return type
             MethodNode setter = cNode.getSetterMethod(setterName, false);
-            if (!node.isPrivate() &&
-                    (propNodeModifiers & ACC_FINAL) == 0 &&
-                    methodNeedsReplacement(cNode, setter)) {
-                setterBlock = new ExpressionStatement(
-                        new BinaryExpression(
-                                new FieldExpression(field),
-                                Token.newSymbol(Types.EQUAL, 0, 0),
-                                new VariableExpression("value")
-                        )
-                );
+            if (!node.isPrivate() && (propNodeModifiers & ACC_FINAL) == 0
+                    && methodNeedsReplacement(cNode, setter)) {
+                setterBlock = assignS(fieldX(field), varX(name));
             }
         }
 
         if (getterBlock != null) {
-            MethodNode getter =
-                    new MethodNode(getterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
+            MethodNode getter = new MethodNode(getterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
             getter.setSynthetic(true);
             cNode.addMethod(getter);
 
-            if (ClassHelper.boolean_TYPE == node.getType() || ClassHelper.Boolean_TYPE == node.getType()) {
-                String secondGetterName = "is" + Verifier.capitalize(name);
-                MethodNode secondGetter =
-                        new MethodNode(secondGetterName, propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
+            if (node.getType().equals(ClassHelper.boolean_TYPE) || node.getType().equals(ClassHelper.Boolean_TYPE)) {
+                MethodNode secondGetter = new MethodNode("is" + capitalize(name), propNodeModifiers, node.getType(), Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, getterBlock);
                 secondGetter.setSynthetic(true);
                 cNode.addMethod(secondGetter);
             }
         }
         if (setterBlock != null) {
-            Parameter[] setterParameterTypes = {new Parameter(node.getType(), "value")};
             VariableExpression var = (VariableExpression) ((BinaryExpression) ((ExpressionStatement) setterBlock).getExpression()).getRightExpression();
-            var.setAccessedVariable(setterParameterTypes[0]);
-            MethodNode setter =
-                    new MethodNode(setterName, propNodeModifiers, ClassHelper.VOID_TYPE, setterParameterTypes, ClassNode.EMPTY_ARRAY, setterBlock);
+            Parameter setterParameter = new Parameter(node.getType(), name);
+            var.setAccessedVariable(setterParameter);
+
+            MethodNode setter = new MethodNode(setterName, propNodeModifiers, ClassHelper.VOID_TYPE, params(setterParameter), ClassNode.EMPTY_ARRAY, setterBlock);
             setter.setSynthetic(true);
             cNode.addMethod(setter);
         }
     }
 
-    private static boolean methodNeedsReplacement(ClassNode classNode, MethodNode m) {
+    private static boolean methodNeedsReplacement(final ClassNode cNode, final MethodNode mNode) {
         // no method found, we need to replace
-        if (m == null) return true;
+        if (mNode == null) return true;
         // method is in current class, nothing to be done
-        if (m.getDeclaringClass() == classNode) return false;
+        if (mNode.getDeclaringClass() == cNode) return false;
         // do not overwrite final
-        if ((m.getModifiers() & ACC_FINAL) != 0) return false;
+        if ((mNode.getModifiers() & ACC_FINAL) != 0) return false;
         return true;
     }
 
@@ -464,23 +449,23 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                               final ClassNode fieldHelper, final ClassNode helper, final ClassNode staticFieldHelper, final ClassNode trait,
                               final Set<String> knownFields) {
         if (field.isProtected()) {
-            unit.addError(new SyntaxException("Cannot have protected field in a trait (" + trait.getName() + "#" + field.getName() + ")",
+            sourceUnit.addError(new SyntaxException("Cannot have protected field in a trait (" + trait.getName() + "#" + field.getName() + ")",
                     field.getLineNumber(), field.getColumnNumber()));
             return;
         }
 
         Expression initialExpression = field.getInitialExpression();
-        MethodNode selectedMethod = field.isStatic()?staticInitializer:initializer;
+        MethodNode selectedMethod = field.isStatic() ? staticInitializer : initializer;
         ClassNode target = field.isStatic() && staticFieldHelper != null ? staticFieldHelper : fieldHelper;
         if (initialExpression != null) {
-            VariableExpression thisObject = new VariableExpression(selectedMethod.getParameters()[0]);
+            VariableExpression thisObject = varX(selectedMethod.getParameters()[0]);
             ExpressionStatement initCode = new ExpressionStatement(initialExpression);
             processBody(thisObject, initCode, trait, helper, fieldHelper, knownFields);
             if (field.isFinal()) {
                 String baseName = field.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
                 MethodNode fieldInitializer = new MethodNode(
                         baseName + Traits.remappedFieldName(trait, field.getName()),
-                        ACC_STATIC | ACC_PUBLIC | ACC_SYNTHETIC,
+                        ACC_PUBLIC | ACC_STATIC | ACC_SYNTHETIC,
                         field.getOriginType(),
                         new Parameter[]{createSelfParameter(trait, field.isStatic())},
                         ClassNode.EMPTY_ARRAY,
@@ -494,25 +479,25 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                     if (staticFieldHelper != null) {
                         target = staticFieldHelper;
                     }
-                    mce = new MethodCallExpression(
-                            new ClassExpression(INVOKERHELPER_CLASSNODE),
+                    mce = callX(
+                            classX(INVOKERHELPER_CLASSNODE),
                             "invokeStaticMethod",
-                            new ArgumentListExpression(
+                            args(
                                     thisObject,
-                                    new ConstantExpression(Traits.helperSetterName(field)),
+                                    constX(Traits.helperSetterName(field)),
                                     initCode.getExpression()
                             )
                     );
                 } else {
-                    mce = new MethodCallExpression(
-                            new CastExpression(createReceiverType(field.isStatic(), fieldHelper), thisObject),
+                    mce = callX(
+                            castX(createReceiverType(field.isStatic(), fieldHelper), thisObject),
                             Traits.helperSetterName(field),
-                            new CastExpression(field.getOriginType(),initCode.getExpression())
+                            castX(field.getOriginType(), initCode.getExpression())
                     );
                 }
                 mce.setImplicitThis(false);
                 mce.setSourcePosition(initialExpression);
-                code.addStatement(new ExpressionStatement(mce));
+                code.addStatement(stmt(mce));
             }
         }
         // define setter/getter helper methods (setter added even for final fields for legacy compatibility)
@@ -539,38 +524,38 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         String dummyFieldName = String.format("$0x%04x", mods) + Traits.remappedFieldName(field.getOwner(), field.getName());
         FieldNode dummyField = new FieldNode(
                 dummyFieldName,
-                ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
+                ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
                 field.getOriginType(),
                 fieldHelper,
                 null
         );
         // copy annotations from field to dummy field
-        List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
-        List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
+        List<AnnotationNode> copied = new LinkedList<>();
+        List<AnnotationNode> notCopied = new LinkedList<>();
         GeneralUtils.copyAnnotatedNodeAnnotations(field, copied, notCopied);
         dummyField.addAnnotations(copied);
         fieldHelper.addField(dummyField);
 
         // retain legacy field (will be given lower precedence than above)
         dummyFieldName = (field.isStatic() ? Traits.STATIC_FIELD_PREFIX : Traits.FIELD_PREFIX) +
-                (field.isPublic()? Traits.PUBLIC_FIELD_PREFIX : Traits.PRIVATE_FIELD_PREFIX)+
+                (field.isPublic() ? Traits.PUBLIC_FIELD_PREFIX : Traits.PRIVATE_FIELD_PREFIX) +
                 Traits.remappedFieldName(field.getOwner(), field.getName());
         dummyField = new FieldNode(
                 dummyFieldName,
-                ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
+                ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_SYNTHETIC,
                 field.getOriginType(),
                 fieldHelper,
                 null
         );
         // copy annotations from field to legacy dummy field
-        copied = new LinkedList<AnnotationNode>();
-        notCopied = new LinkedList<AnnotationNode>();
+        copied = new LinkedList<>();
+        notCopied = new LinkedList<>();
         GeneralUtils.copyAnnotatedNodeAnnotations(field, copied, notCopied);
         dummyField.addAnnotations(copied);
         fieldHelper.addField(dummyField);
     }
 
-    private MethodNode processMethod(ClassNode traitClass, ClassNode traitHelperClass, MethodNode methodNode, ClassNode fieldHelper, Collection<String> knownFields) {
+    private MethodNode processMethod(final ClassNode traitClass, final ClassNode traitHelperClass, final MethodNode methodNode, final ClassNode fieldHelper, final Collection<String> knownFields) {
         Parameter[] initialParams = methodNode.getParameters();
         Parameter[] newParams = new Parameter[initialParams.length + 1];
         newParams[0] = createSelfParameter(traitClass, methodNode.isStatic());
@@ -582,7 +567,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                 methodNode.getReturnType(),
                 newParams,
                 methodNode.getExceptions(),
-                processBody(new VariableExpression(newParams[0]), methodNode.getCode(), traitClass, traitHelperClass, fieldHelper, knownFields)
+                processBody(varX(newParams[0]), methodNode.getCode(), traitClass, traitHelperClass, fieldHelper, knownFields)
         );
         mNode.setSourcePosition(methodNode);
         mNode.addAnnotations(filterAnnotations(methodNode.getAnnotations()));
@@ -600,8 +585,8 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         return mNode;
     }
 
-    private static List<AnnotationNode> filterAnnotations(List<AnnotationNode> annotations) {
-        List<AnnotationNode> result = new ArrayList<AnnotationNode>(annotations.size());
+    private static List<AnnotationNode> filterAnnotations(final List<AnnotationNode> annotations) {
+        List<AnnotationNode> result = new ArrayList<>(annotations.size());
         for (AnnotationNode annotation : annotations) {
             if (!OVERRIDE_CLASSNODE.equals(annotation.getClassNode())) {
                 result.add(annotation);
@@ -614,7 +599,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     private static Parameter createSelfParameter(final ClassNode traitClass, boolean isStatic) {
         final ClassNode rawType = traitClass.getPlainNodeReference();
         ClassNode type = createReceiverType(isStatic, rawType);
-        return new Parameter(type, isStatic?Traits.STATIC_THIS_OBJECT:Traits.THIS_OBJECT);
+        return new Parameter(type, isStatic ? Traits.STATIC_THIS_OBJECT : Traits.THIS_OBJECT);
     }
 
     private static ClassNode createReceiverType(final boolean isStatic, final ClassNode rawType) {
@@ -632,20 +617,18 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         return type;
     }
 
-    private Statement processBody(VariableExpression thisObject, Statement code, ClassNode trait, ClassNode traitHelper, ClassNode fieldHelper, Collection<String> knownFields) {
+    private Statement processBody(final VariableExpression thisObject, final Statement code, final ClassNode trait, final ClassNode traitHelper, final ClassNode fieldHelper, final Collection<String> knownFields) {
         if (code == null) return null;
-        NAryOperationRewriter operationRewriter = new NAryOperationRewriter(unit, knownFields);
+        NAryOperationRewriter operationRewriter = new NAryOperationRewriter(sourceUnit, knownFields);
         code.visit(operationRewriter);
-        SuperCallTraitTransformer superTrn = new SuperCallTraitTransformer(unit);
+        SuperCallTraitTransformer superTrn = new SuperCallTraitTransformer(sourceUnit);
         code.visit(superTrn);
-        TraitReceiverTransformer trn = new TraitReceiverTransformer(thisObject, unit, trait, traitHelper, fieldHelper, knownFields);
+        TraitReceiverTransformer trn = new TraitReceiverTransformer(thisObject, sourceUnit, trait, traitHelper, fieldHelper, knownFields);
         code.visit(trn);
         return code;
     }
 
-    public void setCompilationUnit(final CompilationUnit unit) {
-        this.compilationUnit = unit;
-    }
+    //--------------------------------------------------------------------------
 
     private static class DefaultArgsMethodsAdder extends Verifier {
 
@@ -659,7 +642,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
     private static class PostTypeCheckingExpressionReplacer extends ClassCodeExpressionTransformer {
         private final SourceUnit sourceUnit;
 
-        private PostTypeCheckingExpressionReplacer(final SourceUnit sourceUnit) {
+        PostTypeCheckingExpressionReplacer(final SourceUnit sourceUnit) {
             this.sourceUnit = sourceUnit;
         }
 
@@ -671,13 +654,12 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         @Override
         public Expression transform(final Expression exp) {
             if (exp != null) {
-                Expression replacement = exp.getNodeMetaData(TraitASTTransformation.POST_TYPECHECKING_REPLACEMENT);
-                if (replacement!=null) {
+                Expression replacement = exp.getNodeMetaData(POST_TYPECHECKING_REPLACEMENT);
+                if (replacement != null) {
                     return replacement;
                 }
             }
             return super.transform(exp);
         }
     }
-
 }
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index dfd956a..45a91b1 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1019,48 +1019,48 @@ final class TraitASTTransformationTest {
     void testTraitSuperPropertyGet() {
         assertScript '''
             trait T {
-              def x = 'value'
+                def x = 'value'
             }
             class C implements T {
-              def test() {
-                T.super.x
-              }
+                def test() {
+                    T.super.x
+                }
             }
             assert new C().test() == 'value'
         '''
 
         assertScript '''
             trait T {
-              boolean x = true
+                boolean x = true
             }
             class C implements T {
-              def test() {
-                T.super.x
-              }
+                def test() {
+                    T.super.x
+                }
             }
             assert new C().test() == true
         '''
 
         assertScript '''
             trait T {
-              def getX() { 'value' }
+                def getX() { 'value' }
             }
             class C implements T {
-              def test() {
-                T.super.x
-              }
+                def test() {
+                    T.super.x
+                }
             }
             assert new C().test() == 'value'
         '''
 
         assertScript '''
             trait T {
-              boolean isX() { true }
+                boolean isX() { true }
             }
             class C implements T {
-              def test() {
-                T.super.x
-              }
+                def test() {
+                    T.super.x
+                }
             }
             assert new C().test() == true
         '''
@@ -1070,40 +1070,54 @@ final class TraitASTTransformationTest {
     void testTraitSuperPropertySet() {
         assertScript '''
             trait T {
-              def x
+                def x
             }
             class C implements T {
-              def test() {
-                T.super.x = 'value'
-                return x
-              }
+                def test() {
+                    T.super.x = 'value'
+                    return x
+                }
+            }
+            assert new C().test() == 'value'
+        '''
+
+        def err = shouldFail '''
+            trait T {
+                final x = 'const'
+            }
+            class C implements T {
+                def test() {
+                    T.super.x = 'value'
+                    return x
+                }
             }
             assert new C().test() == 'value'
         '''
+        assert err =~ /No such property: super for class: T/
 
         // TODO: add support for compound assignment
         shouldFail MissingPropertyException, '''
             trait T {
-              def x = 'value'
+                def x = 'value'
             }
             class C implements T {
-              def test() {
-                T.super.x -= ~/e\b/
-                T.super.x += 'able'
-                return x
-              }
+                def test() {
+                    T.super.x -= ~/e\b/
+                    T.super.x += 'able'
+                    return x
+                }
             }
             assert new C().test() == 'valuable'
         '''
 
         assertScript '''
             trait T {
-              def setX(value) { 'retval' }
+                def setX(value) { 'retval' }
             }
             class C implements T {
-              def test() {
-                T.super.x = 'value'
-              }
+                def test() {
+                    T.super.x = 'value'
+                }
             }
             assert new C().test() == 'retval'
         '''
@@ -1113,39 +1127,35 @@ final class TraitASTTransformationTest {
     void testTraitSuperPropertySetWithOverloads() {
         assertScript '''
             trait T {
-              def setX(Number n) {
-                'Number'
-              }
-              def setX(String s) {
-                'String'
-              }
+                def setX(Number n) {
+                    'Number'
+                }
+                def setX(String s) {
+                    'String'
+                }
             }
-
             class C implements T {
-              def test() {
-                T.super.x = 42
-              }
+                def test() {
+                    T.super.x = 42
+                }
             }
-
             assert new C().test() == 'Number'
         '''
 
         assertScript '''
             trait T {
-              def setX(Number n) {
-                'Number'
-              }
-              def setX(String s) {
-                'String'
-              }
+                def setX(Number n) {
+                    'Number'
+                }
+                def setX(String s) {
+                    'String'
+                }
             }
-
             class C implements T {
-              def test() {
-                T.super.x = 'x'
-              }
+                def test() {
+                    T.super.x = 'x'
+                }
             }
-
             assert new C().test() == 'String'
         '''
     }


[groovy] 06/07: GROOVY-9256: process closure expressions for Trait.super.name transforms

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

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

commit 6db454996eeac39f4a54bf23d74e89ca73c0bf0e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 10:47:18 2020 -0500

    GROOVY-9256: process closure expressions for Trait.super.name transforms
    
    closes #1341
    
    (cherry picked from commit 983f7263408084b0948ec253de5d7cbd038e0554)
---
 .../transform/trait/SuperCallTraitTransformer.java | 14 +++++++++
 .../traitx/TraitASTTransformationTest.groovy       | 33 ++++++++++++++++++++++
 2 files changed, 47 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index 08fe8d2..edd1e12 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -28,11 +28,13 @@ import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BinaryExpression;
 import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
 import org.codehaus.groovy.ast.expr.Expression;
 import org.codehaus.groovy.ast.expr.MethodCallExpression;
 import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.ast.expr.TupleExpression;
 import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.tools.ClosureUtils;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.syntax.Types;
 
@@ -68,6 +70,9 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         if (exp instanceof BinaryExpression) {
             return transformBinaryExpression((BinaryExpression) exp);
         }
+        if (exp instanceof ClosureExpression) {
+            return transformClosureExpression((ClosureExpression) exp);
+        }
         if (exp instanceof PropertyExpression) {
             return transformPropertyExpression((PropertyExpression) exp);
         }
@@ -117,6 +122,15 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         return trn;
     }
 
+    private Expression transformClosureExpression(final ClosureExpression exp) {
+        for (Parameter prm : ClosureUtils.getParametersSafe(exp)) {
+            Expression ini = transform(prm.getInitialExpression());
+            prm.setInitialExpression(ini);
+        }
+        visitClassCodeContainer(exp.getCode());
+        return super.transform(exp);
+    }
+
     private Expression transformPropertyExpression(final PropertyExpression exp) {
         if (exp.getNodeMetaData("assign.target") == null) {
             ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 2d412a6..dfd956a 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -399,6 +399,7 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test
     void testTraitOnEnum() {
         assertScript '''
             trait WithBar { int bar }
@@ -1183,6 +1184,37 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test // GROOVY-9256
+    void testTraitSuperCallWithinClosure() {
+        assertScript '''
+            trait T {
+              int getX() { 42 }
+            }
+            class C implements T {
+              def test() {
+                { ->
+                  T.super.getX()
+                }()
+              }
+            }
+            assert new C().test() == 42
+        '''
+
+        assertScript '''
+            trait T {
+              int getX() { 42 }
+            }
+            class C implements T {
+              def test() {
+                { p = T.super.getX() ->
+                  return p
+                }()
+              }
+            }
+            assert new C().test() == 42
+        '''
+    }
+
     @Test
     void testTraitShouldNotTakeOverSuperClassMethod() {
         assertScript '''
@@ -1835,6 +1867,7 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test
     void testIncrementPropertyOfTraitUsingPlusPlus() {
         def err = shouldFail '''
             trait Level {


[groovy] 01/07: minor refactor

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

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

commit 9476cb6e489c46ad9ffff462feb0c088abf642c3
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Aug 5 16:49:08 2020 -0500

    minor refactor
    
    (cherry picked from commit 3aad26c5cff180872111258074b5383bff9a7a0b)
---
 .../transform/trait/SuperCallTraitTransformer.java | 119 ++++++++++-----------
 1 file changed, 54 insertions(+), 65 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index 7e6e090..76f5782 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -36,8 +36,6 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.syntax.Types;
 
-import java.util.List;
-
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 import static org.objectweb.asm.Opcodes.ACC_STATIC;
@@ -49,7 +47,9 @@ import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
  * @since 2.3.0
  */
 class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
+
     static final String UNRESOLVED_HELPER_CLASS = "UNRESOLVED_HELPER_CLASS";
+
     private final SourceUnit unit;
 
     SuperCallTraitTransformer(final SourceUnit unit) {
@@ -63,12 +63,12 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
 
     @Override
     public Expression transform(final Expression exp) {
-        if (exp instanceof MethodCallExpression) {
-            return transformMethodCallExpression((MethodCallExpression)exp);
-        }
         if (exp instanceof BinaryExpression) {
             return transformBinaryExpression((BinaryExpression) exp);
         }
+        if (exp instanceof MethodCallExpression) {
+            return transformMethodCallExpression((MethodCallExpression) exp);
+        }
         return super.transform(exp);
     }
 
@@ -76,38 +76,33 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         Expression trn = super.transform(exp);
         if (trn instanceof BinaryExpression) {
             BinaryExpression bin = (BinaryExpression) trn;
-            Expression leftExpression = bin.getLeftExpression();
-            if (bin.getOperation().getType() == Types.EQUAL && leftExpression instanceof PropertyExpression) {
-                ClassNode traitReceiver = null;
-                PropertyExpression leftPropertyExpression = (PropertyExpression) leftExpression;
-                if (isTraitSuperPropertyExpression(leftPropertyExpression.getObjectExpression())) {
-                    PropertyExpression pexp = (PropertyExpression) leftPropertyExpression.getObjectExpression();
-                    traitReceiver = pexp.getObjectExpression().getType();
-                }
-                if (traitReceiver!=null) {
-                    // A.super.foo = ...
-                    TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver);
-                    ClassNode helper = helpers.getHelper();
-                    String setterName = MetaProperty.getSetterName(leftPropertyExpression.getPropertyAsString());
-                    List<MethodNode> methods = helper.getMethods(setterName);
-                    for (MethodNode method : methods) {
+            if (bin.getOperation().getType() == Types.ASSIGN && bin.getLeftExpression() instanceof PropertyExpression) {
+                PropertyExpression leftExpression = (PropertyExpression) bin.getLeftExpression();
+                ClassNode traitType = getTraitSuperTarget(leftExpression.getObjectExpression());
+                if (traitType != null) {
+                    // TraitType.super.foo = ... -> TraitType$Helper.setFoo(this, ...)
+
+                    ClassNode helperType = getHelper(traitType);
+                    String setterName = MetaProperty.getSetterName(leftExpression.getPropertyAsString());
+                    for (MethodNode method : helperType.getMethods(setterName)) {
                         Parameter[] parameters = method.getParameters();
-                        if (parameters.length==2 && parameters[0].getType().equals(traitReceiver)) {
-                            ArgumentListExpression args = new ArgumentListExpression(
-                                    new VariableExpression("this"),
-                                    transform(exp.getRightExpression())
-                            );
+                        if (parameters.length == 2 && parameters[0].getType().equals(traitType)) {
                             MethodCallExpression setterCall = new MethodCallExpression(
-                                    new ClassExpression(helper),
+                                    new ClassExpression(helperType),
                                     setterName,
-                                    args
+                                    new ArgumentListExpression(
+                                            new VariableExpression("this"),
+                                            bin.getRightExpression()
+                                    )
                             );
+                            setterCall.getMethod().setSourcePosition(leftExpression.getProperty());
+                            setterCall.getObjectExpression().setSourcePosition(traitType);
+                            setterCall.setSpreadSafe(leftExpression.isSpreadSafe());
                             setterCall.setMethodTarget(method);
                             setterCall.setImplicitThis(false);
                             return setterCall;
                         }
                     }
-                    return bin;
                 }
             }
         }
@@ -115,44 +110,37 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
     }
 
     private Expression transformMethodCallExpression(final MethodCallExpression exp) {
-        if (isTraitSuperPropertyExpression(exp.getObjectExpression())) {
-            Expression objectExpression = exp.getObjectExpression();
-            ClassNode traitReceiver = ((PropertyExpression) objectExpression).getObjectExpression().getType();
-
-            if (traitReceiver != null) {
-                // (SomeTrait.super).foo() --> SomeTrait$Helper.foo(this)
-                ClassExpression receiver = new ClassExpression(
-                        getHelper(traitReceiver)
-                );
-                ArgumentListExpression newArgs = new ArgumentListExpression();
-                Expression arguments = exp.getArguments();
-                newArgs.addExpression(new VariableExpression("this"));
-                if (arguments instanceof TupleExpression) {
-                    List<Expression> expressions = ((TupleExpression) arguments).getExpressions();
-                    for (Expression expression : expressions) {
-                        newArgs.addExpression(transform(expression));
-                    }
-                } else {
-                    newArgs.addExpression(transform(arguments));
+        ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
+        if (traitType != null) {
+            // TraitType.super.foo() -> TraitType$Helper.foo(this)
+
+            ArgumentListExpression newArgs = new ArgumentListExpression();
+            newArgs.addExpression(new VariableExpression("this"));
+            Expression arguments = exp.getArguments();
+            if (arguments instanceof TupleExpression) {
+                for (Expression expression : (TupleExpression) arguments) {
+                    newArgs.addExpression(transform(expression));
                 }
-                MethodCallExpression result = new MethodCallExpression(
-                        receiver,
-                        transform(exp.getMethod()),
-                        newArgs
-                );
-                result.setImplicitThis(false);
-                result.setSpreadSafe(exp.isSpreadSafe());
-                result.setSafe(exp.isSafe());
-                result.setSourcePosition(exp);
-                return result;
+            } else {
+                newArgs.addExpression(transform(arguments));
             }
+
+            MethodCallExpression newCall = new MethodCallExpression(
+                    new ClassExpression(getHelper(traitType)),
+                    transform(exp.getMethod()),
+                    newArgs
+            );
+            newCall.getObjectExpression().setSourcePosition(traitType);
+            newCall.setSpreadSafe(exp.isSpreadSafe());
+            newCall.setImplicitThis(false);
+            return newCall;
         }
         return super.transform(exp);
     }
 
     private ClassNode getHelper(final ClassNode traitReceiver) {
         if (helperClassNotCreatedYet(traitReceiver)) {
-            // GROOVY-7909 A Helper class in same compilation unit may have not been created when referenced
+            // GROOVY-7909: A Helper class in same compilation unit may have not been created when referenced
             // Here create a symbol as a "placeholder" and it will be resolved later.
             ClassNode ret = new InnerClassNode(
                     traitReceiver,
@@ -174,19 +162,20 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
 
     private boolean helperClassNotCreatedYet(final ClassNode traitReceiver) {
         return !traitReceiver.redirect().getInnerClasses().hasNext()
-                && this.unit.getAST().getClasses().contains(traitReceiver.redirect());
+                && getSourceUnit().getAST().getClasses().contains(traitReceiver.redirect());
     }
-    private boolean isTraitSuperPropertyExpression(Expression exp) {
+
+    private ClassNode getTraitSuperTarget(final Expression exp) {
         if (exp instanceof PropertyExpression) {
             PropertyExpression pexp = (PropertyExpression) exp;
-            Expression objectExpression = pexp.getObjectExpression();
-            if (objectExpression instanceof ClassExpression) {
-                ClassNode type = objectExpression.getType();
+            Expression objExp = pexp.getObjectExpression();
+            if (objExp instanceof ClassExpression) {
+                ClassNode type = objExp.getType();
                 if (Traits.isTrait(type) && "super".equals(pexp.getPropertyAsString())) {
-                    return true;
+                    return type;
                 }
             }
         }
-        return false;
+        return null;
     }
 }


[groovy] 04/07: GROOVY-9255: transform "TraitType.super.name" to getName()/isName() call

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

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

commit 3d6ca61e889a9051a2205167c49fb0ecf0827c3f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 08:40:27 2020 -0500

    GROOVY-9255: transform "TraitType.super.name" to getName()/isName() call
    
    "TraitType.super.name = ..." was already handled; binary expression is
    transformed before subbing "TraitType$Helper.setName(this, ...)", so be
    careful not to transform LHS (assign target) to accessor call.
    
    closes #1340
    
    (cherry picked from commit ffb83225b5be7c7f567b6fed91b23612b2bcc185)
---
 .../java/org/codehaus/groovy/syntax/Types.java     |  3 +
 .../transform/trait/SuperCallTraitTransformer.java | 55 +++++++++++++
 .../traitx/TraitASTTransformationTest.groovy       | 94 ++++++++++++++++++++++
 3 files changed, 152 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/syntax/Types.java b/src/main/java/org/codehaus/groovy/syntax/Types.java
index 0464dc6..4cf90c4 100644
--- a/src/main/java/org/codehaus/groovy/syntax/Types.java
+++ b/src/main/java/org/codehaus/groovy/syntax/Types.java
@@ -368,6 +368,9 @@ public class Types {
     //---------------------------------------------------------------------------
     // TYPE HIERARCHIES
 
+    /**
+     * @since 3.0.0
+     */
     public static boolean isAssignment(int type) {
         return ofType(type, ASSIGNMENT_OPERATOR);
     }
diff --git a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index 4eccccb..ba57ecc 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -36,6 +36,8 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.syntax.Types;
 
+import java.util.function.Function;
+
 import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
 import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
 import static org.objectweb.asm.Opcodes.ACC_STATIC;
@@ -66,6 +68,9 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         if (exp instanceof BinaryExpression) {
             return transformBinaryExpression((BinaryExpression) exp);
         }
+        if (exp instanceof PropertyExpression) {
+            return transformPropertyExpression((PropertyExpression) exp);
+        }
         if (exp instanceof MethodCallExpression) {
             return transformMethodCallExpression((MethodCallExpression) exp);
         }
@@ -73,6 +78,10 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
     }
 
     private Expression transformBinaryExpression(final BinaryExpression exp) {
+        if (Types.isAssignment(exp.getOperation().getType()))
+            // prevent transform of assignment target to accessor method call
+            exp.getLeftExpression().putNodeMetaData("assign.target", exp.getOperation());
+
         Expression trn = super.transform(exp);
         if (trn instanceof BinaryExpression) {
             BinaryExpression bin = (BinaryExpression) trn;
@@ -109,6 +118,52 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
         return trn;
     }
 
+    private Expression transformPropertyExpression(final PropertyExpression exp) {
+        if (exp.getNodeMetaData("assign.target") == null) {
+            ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
+            if (traitType != null) {
+                ClassNode helperType = getHelper(traitType);
+                // TraitType.super.foo -> TraitType$Helper.getFoo(this)
+
+                Function<MethodNode, MethodCallExpression> xform = (methodNode) -> {
+                    MethodCallExpression methodCall = new MethodCallExpression(
+                            new ClassExpression(helperType),
+                            methodNode.getName(),
+                            new ArgumentListExpression(
+                                    new VariableExpression("this")
+                            )
+                    );
+                    methodCall.getObjectExpression().setSourcePosition(((PropertyExpression) exp.getObjectExpression()).getObjectExpression());
+                    methodCall.getMethod().setSourcePosition(exp.getProperty());
+                    methodCall.setSpreadSafe(exp.isSpreadSafe());
+                    methodCall.setMethodTarget(methodNode);
+                    methodCall.setImplicitThis(false);
+                    return methodCall;
+                };
+
+                String getterName = MetaProperty.getGetterName(exp.getPropertyAsString(), null);
+                for (MethodNode method : helperType.getMethods(getterName)) {
+                    if (method.isStatic() && method.getParameters().length == 1
+                            && method.getParameters()[0].getType().equals(traitType)
+                            && !method.getReturnType().equals(ClassHelper.VOID_TYPE)) {
+                        return xform.apply(method);
+                    }
+                }
+
+                String isserName = "is" + getterName.substring(3);
+                for (MethodNode method : helperType.getMethods(isserName)) {
+                    if (method.isStatic() && method.getParameters().length == 1
+                            && method.getParameters()[0].getType().equals(traitType)
+                            && method.getReturnType().equals(ClassHelper.boolean_TYPE)) {
+                        return xform.apply(method);
+                    }
+                }
+            }
+        }
+        exp.removeNodeMetaData("assign.target");
+        return super.transform(exp);
+    }
+
     private Expression transformMethodCallExpression(final MethodCallExpression exp) {
         ClassNode traitType = getTraitSuperTarget(exp.getObjectExpression());
         if (traitType != null) {
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 81d6fd0..5a57531 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -1014,6 +1014,100 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test // GROOVY-9255
+    void testTraitSuperPropertyGet() {
+        assertScript '''
+            trait T {
+              def x = 'value'
+            }
+            class C implements T {
+              def test() {
+                T.super.x
+              }
+            }
+            assert new C().test() == 'value'
+        '''
+
+        assertScript '''
+            trait T {
+              boolean x = true
+            }
+            class C implements T {
+              def test() {
+                T.super.x
+              }
+            }
+            assert new C().test() == true
+        '''
+
+        assertScript '''
+            trait T {
+              def getX() { 'value' }
+            }
+            class C implements T {
+              def test() {
+                T.super.x
+              }
+            }
+            assert new C().test() == 'value'
+        '''
+
+        assertScript '''
+            trait T {
+              boolean isX() { true }
+            }
+            class C implements T {
+              def test() {
+                T.super.x
+              }
+            }
+            assert new C().test() == true
+        '''
+    }
+
+    @Test
+    void testTraitSuperPropertySet() {
+        assertScript '''
+            trait T {
+              def x
+            }
+            class C implements T {
+              def test() {
+                T.super.x = 'value'
+                return x
+              }
+            }
+            assert new C().test() == 'value'
+        '''
+
+        // TODO: add support for compound assignment
+        shouldFail MissingPropertyException, '''
+            trait T {
+              def x = 'value'
+            }
+            class C implements T {
+              def test() {
+                T.super.x -= ~/e\b/
+                T.super.x += 'able'
+                return x
+              }
+            }
+            assert new C().test() == 'valuable'
+        '''
+
+        assertScript '''
+            trait T {
+              def setX(value) { 'retval' }
+            }
+            class C implements T {
+              def test() {
+                T.super.x = 'value'
+              }
+            }
+            assert new C().test() == 'retval'
+        '''
+    }
+
     @Test
     void testSuperCallInTraitExtendingAnotherTrait() {
         assertScript '''


[groovy] 03/07: GROOVY-9386: traits: do not transform dynamic variable within closure

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

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

commit 21f8299e28c6fac6a552d4ab423844473bad82e1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Aug 8 08:39:26 2020 -0500

    GROOVY-9386: traits: do not transform dynamic variable within closure
    
    closes #1334
    
    (cherry picked from commit 03ef95584a356bb8c514f38c3b4d16eb4772a643)
---
 .../transform/trait/TraitReceiverTransformer.java  |  2 +-
 .../traitx/TraitASTTransformationTest.groovy       | 38 ++++++++++++++++++++++
 2 files changed, 39 insertions(+), 1 deletion(-)

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 04b2cc0..ebb8947 100644
--- a/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
+++ b/src/main/java/org/codehaus/groovy/transform/trait/TraitReceiverTransformer.java
@@ -149,7 +149,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 = propX(varX(weaved), vexp.getName());
                 propertyExpression.getProperty().setSourcePosition(exp);
                 return propertyExpression;
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index 11cf72c..81d6fd0 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -2849,6 +2849,44 @@ final class TraitASTTransformationTest {
         '''
     }
 
+    @Test // GROOVY-9386
+    void testTraitPropertyInitializedByTap() {
+        assertScript '''
+            class P {
+                int prop
+            }
+            trait T {
+                P pogo = new P().tap {
+                    prop = 42 // MissingPropertyException: No such property: prop for class: C
+                }
+            }
+            class C implements T {
+            }
+
+            def pogo = new C().pogo
+            assert pogo.prop == 42
+        '''
+    }
+
+    @Test // GROOVY-9386
+    void testTraitPropertyInitializedByWith() {
+        assertScript '''
+            class P {
+                int prop
+            }
+            trait T {
+                P pogo = new P().with {
+                    prop = 42 // MissingPropertyException: No such property: prop for class: C
+                    return it
+                }
+            }
+            class C implements T {
+            }
+            def pogo = new C().pogo
+            assert pogo.prop == 42
+        '''
+    }
+
     @Test // GROOVY-9660
     void testAsGenericsParam() {
         assertScript '''