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 2017/04/07 13:30:52 UTC

[09/50] [abbrv] groovy git commit: groovy 7909 bug

groovy 7909 bug


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

Branch: refs/heads/parrot
Commit: 64d4f844ce60374749d5f5adb3d4075d7165acc4
Parents: 4382195
Author: zhangbo <zh...@nanchao.org>
Authored: Mon Sep 26 10:29:16 2016 +0800
Committer: paulk <pa...@asert.com.au>
Committed: Wed Mar 8 17:49:59 2017 +1000

----------------------------------------------------------------------
 .../trait/SuperCallTraitTransformer.java        | 83 ++++++++++++++------
 .../transform/trait/TraitASTTransformation.java | 23 +++++-
 src/test/groovy/bugs/Groovy7909Bug.groovy       | 58 ++++++++++++++
 3 files changed, 137 insertions(+), 27 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/groovy/blob/64d4f844/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
----------------------------------------------------------------------
diff --git a/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java b/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
index f3d35d8..2972c72 100644
--- a/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
+++ b/src/main/org/codehaus/groovy/transform/trait/SuperCallTraitTransformer.java
@@ -21,7 +21,9 @@ package org.codehaus.groovy.transform.trait;
 import groovy.lang.MetaProperty;
 import java.util.List;
 import org.codehaus.groovy.ast.ClassCodeExpressionTransformer;
+import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.InnerClassNode;
 import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
@@ -35,6 +37,11 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.syntax.Types;
 
+import static org.objectweb.asm.Opcodes.ACC_ABSTRACT;
+import static org.objectweb.asm.Opcodes.ACC_PUBLIC;
+import static org.objectweb.asm.Opcodes.ACC_STATIC;
+import static org.objectweb.asm.Opcodes.ACC_SYNTHETIC;
+
 /**
  * This transformer is used to transform calls to <code>SomeTrait.super.foo()</code> into the appropriate trait call.
  *
@@ -42,6 +49,7 @@ import org.codehaus.groovy.syntax.Types;
  * @since 2.3.0
  */
 class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
+    public static final String UNRESOLVED_HELPER_CLASS = "UNRESOLVED_HELPER_CLASS";
     private final SourceUnit unit;
 
     SuperCallTraitTransformer(final SourceUnit unit) {
@@ -111,36 +119,63 @@ class SuperCallTraitTransformer extends ClassCodeExpressionTransformer {
             Expression objectExpression = exp.getObjectExpression();
             ClassNode traitReceiver = ((PropertyExpression) objectExpression).getObjectExpression().getType();
 
-            TraitHelpersTuple helpers = Traits.findHelpers(traitReceiver);
-            // (SomeTrait.super).foo() --> SomeTrait$Helper.foo(this)
-            ClassExpression receiver = new ClassExpression(
-                    helpers.getHelper()
-            );
-            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));
+            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));
                 }
-            } else {
-                newArgs.addExpression(transform(arguments));
+                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;
             }
-            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;
         }
         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),
+                    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();
+        }
+    }
+
+    private boolean helperClassNotCreatedYet(final ClassNode traitReceiver) {
+        return !traitReceiver.redirect().getInnerClasses().hasNext()
+                && this.unit.getAST().getClasses().contains(traitReceiver.redirect());
+    }
     private boolean isTraitSuperPropertyExpression(Expression exp) {
         if (exp instanceof PropertyExpression) {
             PropertyExpression pexp = (PropertyExpression) exp;

http://git-wip-us.apache.org/repos/asf/groovy/blob/64d4f844/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 da71e9e..053ac42 100644
--- a/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
+++ b/src/main/org/codehaus/groovy/transform/trait/TraitASTTransformation.java
@@ -70,6 +70,8 @@ import java.util.Set;
 
 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
@@ -103,7 +105,21 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
             checkExtendsClause(cNode);
             generateMethodsWithDefaultArgs(cNode);
             replaceExtendsByImplements(cNode);
-            createHelperClass(cNode);
+            ClassNode helperClassNode = createHelperClass(cNode);
+            resolveHelperClassIfNecessary(helperClassNode);
+        }
+    }
+
+    private void resolveHelperClassIfNecessary(final ClassNode helperClassNode) {
+        if (helperClassNode == null) {
+            return;
+        }
+        for (ClassNode cNode : unit.getAST().getClasses()) {
+            ClassNode unresolvedHelperNode = cNode.getNodeMetaData(UNRESOLVED_HELPER_CLASS);
+            if (unresolvedHelperNode != null
+                    && unresolvedHelperNode.getName().equals(helperClassNode.getName())) {
+                unresolvedHelperNode.setRedirect(helperClassNode);
+            }
         }
     }
 
@@ -143,7 +159,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         }
     }
 
-    private void createHelperClass(final ClassNode cNode) {
+    private ClassNode createHelperClass(final ClassNode cNode) {
         ClassNode helper = new InnerClassNode(
                 cNode,
                 Traits.helperClassName(cNode),
@@ -190,7 +206,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
                 if (!methodNode.isSynthetic() && (methodNode.isProtected() || methodNode.getModifiers()==0)) {
                     unit.addError(new SyntaxException("Cannot have protected/package private method in a trait (" + cNode.getName() + "#" + methodNode.getTypeDescriptor() + ")",
                             methodNode.getLineNumber(), methodNode.getColumnNumber()));
-                    return;
+                    return null;
                 }
                 helper.addMethod(processMethod(cNode, helper, methodNode, fieldHelper, fieldNames));
                 if (methodNode.isPrivate() || methodNode.isStatic()) {
@@ -233,6 +249,7 @@ public class TraitASTTransformation extends AbstractASTTransformation implements
         if (fieldHelper!=null) {
             resolveScope(fieldHelper);
         }
+        return helper;
     }
 
     private static MethodNode createInitMethod(final boolean isStatic, final ClassNode cNode, final ClassNode helper) {

http://git-wip-us.apache.org/repos/asf/groovy/blob/64d4f844/src/test/groovy/bugs/Groovy7909Bug.groovy
----------------------------------------------------------------------
diff --git a/src/test/groovy/bugs/Groovy7909Bug.groovy b/src/test/groovy/bugs/Groovy7909Bug.groovy
new file mode 100644
index 0000000..b1e1f97
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7909Bug.groovy
@@ -0,0 +1,58 @@
+package groovy.bugs
+
+import gls.CompilableTestSupport
+
+class Groovy7909Bug extends CompilableTestSupport {
+    void testDynamicCompile(){
+        shouldCompile '''
+trait Three implements One, Two {
+    def postMake() {
+        One.super.postMake()
+        Two.super.postMake()
+        println "Three"
+    }
+}
+trait One {
+    def postMake() { println "One"}
+}
+trait Two {
+    def postMake() { println "Two"}
+}
+class Four implements Three {
+    def make() {
+        Three.super.postMake()
+        println "All done?"
+    }
+}
+Four f = new Four()
+f.make()
+    '''
+    }
+    void testStaticCompile(){
+        shouldCompile '''
+@groovy.transform.CompileStatic
+trait Three implements One, Two {
+    def postMake() {
+        One.super.postMake()
+        Two.super.postMake()
+        println "Three"
+    }
+}
+trait One {
+    def postMake() { println "One"}
+}
+trait Two {
+    def postMake() { println "Two"}
+}
+class Four implements Three {
+    def make() {
+        Three.super.postMake()
+        println "All done?"
+    }
+}
+Four f = new Four()
+f.make()
+    '''
+    }
+}
+