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()
+ """
+ }
+}