You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/04/24 14:12:36 UTC

[2/3] groovy git commit: GROOVY-8127: Access to Trait$Trait$Helper#$self is forbidden (closes #529)

GROOVY-8127: Access to Trait$Trait$Helper#$self is forbidden (closes #529)


Project: http://git-wip-us.apache.org/repos/asf/groovy/repo
Commit: http://git-wip-us.apache.org/repos/asf/groovy/commit/4835f80a
Tree: http://git-wip-us.apache.org/repos/asf/groovy/tree/4835f80a
Diff: http://git-wip-us.apache.org/repos/asf/groovy/diff/4835f80a

Branch: refs/heads/GROOVY_2_6_X
Commit: 4835f80a7c97711ea69539702449ef3b17bffc4e
Parents: 34eada6
Author: paulk <pa...@asert.com.au>
Authored: Mon Apr 24 18:02:34 2017 +1000
Committer: paulk <pa...@asert.com.au>
Committed: Tue Apr 25 00:12:21 2017 +1000

----------------------------------------------------------------------
 .../transform/trait/TraitASTTransformation.java | 22 ++++----
 .../groovy/transform/trait/TraitComposer.java   |  7 +--
 src/test/groovy/bugs/Groovy8127Bug.groovy       | 53 ++++++++++++++++++++
 3 files changed, 70 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/4835f80a/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java b/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
index 8222056..4ac7753 100644
--- a/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -73,9 +73,13 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
 import static org.codehaus.groovy.transform.trait.SuperCallTraitTransformer.UNRESOLVED_HELPER_CLASS;
 
 /**
- * Handles generation of code for the @Trait annotation. A class annotated with @Trait will generate, instead: <ul>
- * <li>an <i>interface</i> with the same name</li> <li>an utility inner class that will be used by the compiler to
- * handle the trait</li> </ul>
+ * Handles generation of code for the traits (trait keyword is equivalent to using the @Trait annotation).
+ * A class annotated with @Trait will generate, instead:
+ * <ul>
+ * <li>an <i>interface</i> with the same name</li>
+ * <li>a utility inner class that will be used by the compiler to implement the trait</li>
+ * <li>potentially a utility inner class to assist with implementing trait fields</li>
+ * </ul>
  *
  * @author Cedric Champeau
  */
@@ -415,21 +419,21 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         Expression initialExpression = field.getInitialExpression();
         MethodNode selectedMethod = field.isStatic()?staticInitializer:initializer;
         if (initialExpression != null) {
+            VariableExpression thisObject = new VariableExpression(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,
                         field.getOriginType(),
-                        Parameter.EMPTY_ARRAY,
+                        new Parameter[]{createSelfParameter(trait, field.isStatic())},
                         ClassNode.EMPTY_ARRAY,
-                        returnS(initialExpression)
+                        returnS(initCode.getExpression())
                 );
                 helper.addMethod(fieldInitializer);
             }
-            VariableExpression thisObject = new VariableExpression(selectedMethod.getParameters()[0]);
-            ExpressionStatement initCode = new ExpressionStatement(initialExpression);
-            processBody(thisObject, initCode, trait, helper, fieldHelper, knownFields);
             BlockStatement code = (BlockStatement) selectedMethod.getCode();
             MethodCallExpression mce;
             if (field.isStatic()) {
@@ -480,7 +484,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                 ACC_STATIC | ACC_PUBLIC | ACC_FINAL | ACC_SYNTHETIC,
                 field.getOriginType(),
                 fieldHelper,
-                field.isFinal() ? initialExpression : null
+                null
         );
         // copy annotations from field to dummy field
         List<AnnotationNode> copied = new LinkedList<AnnotationNode>();

http://git-wip-us.apache.org/repos/asf/groovy/blob/4835f80a/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java b/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
index 1025e61..b97f480 100644
--- a/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
+++ b/src/main/org/codehaus/groovy/transform/trait/TraitComposer.java
@@ -71,6 +71,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 
+import static org.codehaus.groovy.ast.tools.GeneralUtils.args;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.assignX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.returnS;
@@ -257,13 +258,13 @@ public abstract class TraitComposer {
                             List<AnnotationNode> copied = new LinkedList<AnnotationNode>();
                             List<AnnotationNode> notCopied = new LinkedList<AnnotationNode>();
                             GeneralUtils.copyAnnotatedNodeAnnotations(helperField, copied, notCopied);
-                            FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, (fieldMods & Opcodes.ACC_FINAL) == 0 ? null : helperField.getInitialExpression());
+                            FieldNode fieldNode = cNode.addField(fieldName, fieldMods, returnType, null);
                             fieldNode.addAnnotations(copied);
                             // getInitialExpression above will be null if not in same source unit
                             // so instead set within (static) initializer
-                            if (fieldNode.isFinal() && !(helperClassNode instanceof InnerClassNode)) {
+                            if (fieldNode.isFinal()) {
                                 String baseName = fieldNode.isStatic() ? Traits.STATIC_INIT_METHOD : Traits.INIT_METHOD;
-                                Expression mce = callX(helperClassNode, baseName + fieldNode.getName());
+                                Expression mce = callX(helperClassNode, baseName + fieldNode.getName(), args(varX("this")));
                                 Statement stmt = stmt(assignX(varX(fieldNode.getName(), fieldNode.getType()), mce));
                                 if (isStatic == 0) {
                                     cNode.addObjectInitializerStatements(stmt);

http://git-wip-us.apache.org/repos/asf/groovy/blob/4835f80a/src/test/groovy/bugs/Groovy8127Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy8127Bug.groovy b/src/test/groovy/bugs/Groovy8127Bug.groovy
new file mode 100644
index 0000000..842390e
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8127Bug.groovy
@@ -0,0 +1,53 @@
+/*
+ *  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 gls.CompilableTestSupport
+
+class Groovy8127Bug extends CompilableTestSupport {
+    void testTraitWithClosureReferencingField() {
+        assertScript """
+        trait BarTrait {
+            String result = ''
+            public final Runnable bar = { result = 'changeme' } as Runnable
+            void doRun() { bar.run() }
+        }
+
+        class Bar implements BarTrait {}
+
+        def b = new Bar()
+        b.doRun()
+        assert b.result == 'changeme'
+        """
+    }
+
+    void testTraitWithCompileStaticAndCoercedClosure() {
+        shouldCompile """
+        @groovy.transform.CompileStatic
+        trait FooTrait {
+            public final Runnable foo = { println new Date() } as Runnable
+            void doRun() { foo.run() }
+        }
+
+        class Foo implements FooTrait { }
+
+        new Foo().doRun()
+        """
+    }
+}