groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From pa...@apache.org
Subject [groovy] 02/02: GROOVY-8964: MissingMethodException when trying to resolve overload with variable arguments (closes #866)
Date Thu, 31 Jan 2019 10:33:20 GMT
This is an automated email from the ASF dual-hosted git repository.

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

commit 755c943277ff6b801695be0d34b81b0d9d24bfea
Author: Paul King <paulk@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 64d5cff..3a8fc35 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassNode.java
@@ -1290,7 +1290,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;
                 }
             }
@@ -1315,10 +1315,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;
                         }
@@ -1334,7 +1334,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;
                                 }
@@ -1351,6 +1352,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'
+        '''
+    }
+}


Mime
View raw message