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 2019/01/31 10:37:17 UTC

[groovy] branch GROOVY_2_5_X updated (ad8c74b -> 9fd11f0)

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

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


    from ad8c74b  additional XML test tweaks (formatting and spelling)
     new 744abff  GROOVY-8272: Extending trait can't execute static method (closes #865)
     new 9fd11f0  GROOVY-8964: MissingMethodException when trying to resolve overload with variable arguments (closes #866)

The 2 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/ast/ClassNode.java    | 30 +++++++++++++++++++---
 .../transform/stc/TraitTypeCheckingExtension.java  | 27 ++++++++++++-------
 .../{Groovy5137Bug.groovy => Groovy8964Bug.groovy} | 28 ++++++++++----------
 .../traitx/TraitASTTransformationTest.groovy       | 25 ++++++++++++++++++
 4 files changed, 83 insertions(+), 27 deletions(-)
 copy src/test/groovy/bugs/{Groovy5137Bug.groovy => Groovy8964Bug.groovy} (62%)


[groovy] 01/02: GROOVY-8272: Extending trait can't execute static method (closes #865)

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

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

commit 744abffebc845b8590c39fab8a3adabcf5132785
Author: Paul King <pa...@asert.com.au>
AuthorDate: Tue Jan 29 15:57:09 2019 +1000

    GROOVY-8272: Extending trait can't execute static method (closes #865)
---
 .../transform/stc/TraitTypeCheckingExtension.java  | 27 ++++++++++++++--------
 .../traitx/TraitASTTransformationTest.groovy       | 25 ++++++++++++++++++++
 2 files changed, 43 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java b/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java
index 7922770..f364c1e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/TraitTypeCheckingExtension.java
@@ -29,6 +29,8 @@ import org.codehaus.groovy.ast.expr.VariableExpression;
 import org.codehaus.groovy.transform.trait.TraitASTTransformation;
 import org.codehaus.groovy.transform.trait.Traits;
 
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -77,15 +79,22 @@ public class TraitTypeCheckingExtension extends AbstractTypeCheckingExtension {
                     type = receiver;
                 }
                 if (Traits.isTrait(type) && !(type instanceof UnionTypeClassNode)) {
-                    ClassNode helper = Traits.findHelper(type);
-                    Parameter[] params = new Parameter[argumentTypes.length + 1];
-                    params[0] = new Parameter(ClassHelper.CLASS_Type.getPlainNodeReference(), "staticSelf");
-                    for (int i = 1; i < params.length; i++) {
-                        params[i] = new Parameter(argumentTypes[i-1], "p" + i);
-                    }
-                    MethodNode method = helper.getDeclaredMethod(name, params);
-                    if (method != null) {
-                        return Collections.singletonList(makeDynamic(call, method.getReturnType()));
+                    List<ClassNode> candidates = new ArrayList<ClassNode>();
+                    candidates.add(type);
+                    while (!candidates.isEmpty()) {
+                        ClassNode next = candidates.remove(0);
+                        ClassNode helper = Traits.findHelper(next);
+                        Parameter[] params = new Parameter[argumentTypes.length + 1];
+                        params[0] = new Parameter(ClassHelper.CLASS_Type.getPlainNodeReference(), "staticSelf");
+                        for (int i = 1; i < params.length; i++) {
+                            params[i] = new Parameter(argumentTypes[i-1], "p" + i);
+                        }
+                        MethodNode method = helper.getDeclaredMethod(name, params);
+                        if (method != null) {
+                            return Collections.singletonList(makeDynamic(call, method.getReturnType()));
+                        }
+                        // GROOVY-8272 support inherited static methods
+                        candidates.addAll(Arrays.asList(next.getInterfaces()));
                     }
                 }
             }
diff --git a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
index d4c27b3..ca785f0 100644
--- a/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/traitx/TraitASTTransformationTest.groovy
@@ -2688,4 +2688,29 @@ assert c.b() == 2
             assert new CustomProp() {}
         '''
     }
+
+    //GROOVY-8272
+    void testTraitAccessToInheritedStaticMethods() {
+        assertScript '''
+            import groovy.transform.CompileStatic
+
+            @CompileStatic
+            trait Foo {
+                static String go() {
+                    'Go!'
+                }
+            }
+
+            @CompileStatic
+            trait Bar extends Foo {
+                String doIt() {
+                    go().toUpperCase()
+                }
+            }
+
+            class Main implements Bar {}
+
+            assert new Main().doIt() == 'GO!'
+        '''
+    }
 }


[groovy] 02/02: GROOVY-8964: MissingMethodException when trying to resolve overload with variable arguments (closes #866)

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

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

commit 9fd11f0dde1642a214efeac33fc21fbe41151bc1
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Jan 30 13:30:25 2019 +1000

    GROOVY-8964: MissingMethodException when trying to resolve overload with variable arguments (closes #866)
---
 .../java/org/codehaus/groovy/ast/ClassNode.java    | 30 +++++++++++++--
 src/test/groovy/bugs/Groovy8964Bug.groovy          | 43 ++++++++++++++++++++++
 2 files changed, 69 insertions(+), 4 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassNode.java b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
index 1574d4d..5634417 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -1253,7 +1253,7 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
         ClassNode node = this;
         do {
             for (MethodNode method : getMethods(name)) {
-                if (method.getParameters().length == count && !method.isStatic()) {
+                if (hasCompatibleNumberOfArgs(method, count) && !method.isStatic()) {
                     return true;
                 }
             }
@@ -1278,10 +1278,10 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
         TupleExpression args = (TupleExpression) arguments;
         do {
             for (MethodNode method : node.getMethods(name)) {
-                if (method.getParameters().length == count) {
+                if (hasCompatibleNumberOfArgs(method, count)) {
                     boolean match = true;
                     for (int i = 0; i != count; ++i)
-                        if (!args.getType().isDerivedFrom(method.getParameters()[i].getType())) {
+                        if (!hasCompatibleType(args, method, i)) {
                             match = false;
                             break;
                         }
@@ -1297,7 +1297,8 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
 
                             match = true;
                             for (int i = 0; i != count; ++i)
-                                if (!res.getParameters()[i].getType().equals(method.getParameters()[i].getType())) {
+                                // prefer super method if it matches better
+                                if (!hasExactMatchingCompatibleType(res, method, i)) {
                                     match = false;
                                     break;
                                 }
@@ -1314,6 +1315,27 @@ public class ClassNode extends AnnotatedNode implements Opcodes {
         return res;
     }
 
+    private boolean hasExactMatchingCompatibleType(MethodNode current, MethodNode newCandidate, int i) {
+        int lastParamIndex = newCandidate.getParameters().length - 1;
+        return current.getParameters()[i].getType().equals(newCandidate.getParameters()[i].getType())
+                || (isPotentialVarArg(newCandidate, lastParamIndex) && i >= lastParamIndex && current.getParameters()[i].getType().equals(newCandidate.getParameters()[lastParamIndex].getType().componentType));
+    }
+
+    private boolean hasCompatibleType(TupleExpression args, MethodNode method, int i) {
+        int lastParamIndex = method.getParameters().length - 1;
+        return (i <= lastParamIndex && args.getExpression(i).getType().isDerivedFrom(method.getParameters()[i].getType()))
+                || (isPotentialVarArg(method, lastParamIndex) && i >= lastParamIndex  && args.getExpression(i).getType().isDerivedFrom(method.getParameters()[lastParamIndex].getType().componentType));
+    }
+
+    private boolean hasCompatibleNumberOfArgs(MethodNode method, int count) {
+        int lastParamIndex = method.getParameters().length - 1;
+        return method.getParameters().length == count || (isPotentialVarArg(method, lastParamIndex) && count >= lastParamIndex);
+    }
+
+    private boolean isPotentialVarArg(MethodNode newCandidate, int lastParamIndex) {
+        return lastParamIndex >= 0 && newCandidate.getParameters()[lastParamIndex].getType().isArray();
+    }
+
     /**
      * Returns true if the given method has a possibly matching static method with the given name and arguments.
      *
diff --git a/src/test/groovy/bugs/Groovy8964Bug.groovy b/src/test/groovy/bugs/Groovy8964Bug.groovy
new file mode 100644
index 0000000..47b5109
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8964Bug.groovy
@@ -0,0 +1,43 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+class Groovy8964Bug extends GroovyTestCase {
+    void testInstanceVarargMethodNotMaskedByStaticMethodWithSameNumberOfArgs() {
+        assertScript '''
+            class Example {
+
+                def method(String... args) {
+                    'vararg'
+                }
+
+                static method(List<String> args, File workDirectory, Appendable out, Appendable err) {
+                    'multi'
+                }
+
+                def execute() {
+                    method("a", "b", "c", "d")
+                }
+            }
+
+            Example ex = new Example()
+            assert ex.execute() == 'vararg'
+        '''
+    }
+}