diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/InferencingTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/InferencingTests.java index 6fb11b3446..2f44af7090 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/InferencingTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.builder/src/org/eclipse/jdt/core/groovy/tests/search/InferencingTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2017 the original author or authors. + * Copyright 2009-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -2281,4 +2281,61 @@ public void testLocalTypeAndDefaultImportCollision() { assertExprType(contents, "instance", "domain.Calendar"); assertExprType(contents, "cal", "domain.Calendar"); } + + @Test // https://github.com/groovy/groovy-eclipse/issues/405 + public void testMethodOverloadsAndImperfectArgumentMatching() { + createJavaUnit("MyEnum", "enum MyEnum { A, B }"); + + String contents = "class Issue405 {\n" + + " void meth(String s, MyEnum e) {\n" + + " def d1, d2\n" + + " switch (e) {\n" + + " case MyEnum.A:\n" + + " d1 = new Date()\n" + + " d2 = new Date()\n" + + " break\n" + + " case MyEnum.B:\n" + + " d1 = null\n" + + " d2 = null\n" + + " break\n" + + " }\n" + + " meth(s, d1, d2)\n" + + " }\n" + + " void meth(String s, Date d1, Date d2) {\n" + + " }\n" + + "}"; + int offset = contents.indexOf("meth(s"); + MethodNode m = assertDeclaration(contents, offset, offset + 4, "Issue405", "meth", DeclarationKind.METHOD); + assertEquals("Expected 'meth(String, Date, Date)' but was 'meth(String, MyEnum)'", 3, m.getParameters().length); + } + + @Test + public void testMethodOverloadsAndPerfectArgumentMatching() { + createJavaUnit("MyEnum", "enum MyEnum { A, B }"); + + String contents = "class Issue405 {\n" + + " void meth(String s, MyEnum e) {\n" + + " def d1, d2\n" + + " switch (e) {\n" + + " case MyEnum.A:\n" + + " d1 = new Date()\n" + + " d2 = new Date()\n" + + " break\n" + + " case MyEnum.B:\n" + + " d1 = null\n" + + " d2 = null\n" + + " break\n" + + " }\n" + + " meth(s, d1, d2)\n" + + " }\n" + + " void meth(String s, Date d1, Date d2) {\n" + + " }\n" + + " void meth(String s, Object o1, Object o2) {\n" + + " }\n" + + "}"; + int offset = contents.indexOf("meth(s"); + MethodNode m = assertDeclaration(contents, offset, offset + 4, "Issue405", "meth", DeclarationKind.METHOD); + assertTrue("Expected 'meth(String, Object, Object)' but was 'meth(String, MyEnum)' or 'meth(String, Date, Date)'", + m.getParameters().length == 3 && m.getParameters()[2].getType().getNameWithoutPackage().equals("Object")); + } } diff --git a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java index 0c019be6dd..084989b87d 100644 --- a/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java +++ b/base/org.eclipse.jdt.groovy.core/src/org/eclipse/jdt/groovy/search/SimpleTypeLookup.java @@ -1,5 +1,5 @@ /* - * Copyright 2009-2017 the original author or authors. + * Copyright 2009-2018 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -646,25 +646,22 @@ protected MethodNode findMethodDeclaration0(List candidates, List iterator = candidates.iterator(); iterator.hasNext();) { - MethodNode maybeMethod = iterator.next(); - Parameter[] parameters = maybeMethod.getParameters(); + // prefer retrieving the method with the same number of parameters as arguments + // if none exists, then arbitrarily choose the first; TODO: handle variadic methods + for (MethodNode candidate : candidates) { + Parameter[] parameters = candidate.getParameters(); if (parameters.length == 0 && arguments.isEmpty()) { - return maybeMethod.getOriginal(); + return candidate.getOriginal(); } if (parameters.length == arguments.size()) { Boolean suitable = isTypeCompatible(arguments, parameters); if (Boolean.TRUE.equals(suitable)) { - return maybeMethod.getOriginal(); + return candidate.getOriginal(); } - if (!Boolean.FALSE.equals(suitable)) { - closestMatch = maybeMethod.getOriginal(); - continue; // don't remove + if (!Boolean.FALSE.equals(suitable) || closestMatch.getParameters().length != arguments.size()) { + closestMatch = candidate.getOriginal(); } } - iterator.remove(); } return closestMatch; }