diff --git a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java index 401cd44941..29d895b979 100644 --- a/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java +++ b/base-test/org.eclipse.jdt.groovy.core.tests.compiler/src/org/eclipse/jdt/groovy/core/tests/xform/TypeCheckedTests.java @@ -2011,4 +2011,62 @@ public void testTypeChecked9998b() { runConformTest(sources, "null"); } + + @Test + public void testTypeChecked10010() { + //@formatter:off + String[] sources = { + "Main.groovy", + "void m(List list) { }\n" + + "@groovy.transform.TypeChecked\n" + + "void test() {\n" + + " def bar = 123\n" + + " m([\"foo\",\"$bar\"])\n" + + " List list = [\"foo\",\"$bar\"]\n" + + "}\n", + }; + //@formatter:on + + runNegativeTest(sources, + "----------\n" + + "1. ERROR in Main.groovy (at line 5)\n" + + "\tm([\"foo\",\"$bar\"])\n" + + "\t^^^^^^^^^^^^^^^^^\n" + + "Groovy:[Static type checking] - You are trying to use a GString in place of a String in a type which explicitly declares accepting String. Make sure to call toString() on all GString values.\n" + + "----------\n" + + "2. ERROR in Main.groovy (at line 6)\n" + + "\tList list = [\"foo\",\"$bar\"]\n" + + "\t ^^^^^^^^^^^^^^\n" + + "Groovy:[Static type checking] - You are trying to use a GString in place of a String in a type which explicitly declares accepting String. Make sure to call toString() on all GString values.\n" + + "----------\n"); + } + + @Test + public void testTypeChecked10010a() { + //@formatter:off + String[] sources = { + "Main.groovy", + "void m(Map map) { }\n" + + "@groovy.transform.TypeChecked\n" + + "void test() {\n" + + " def bar = 123\n" + + " m([x:\"foo\",y:\"$bar\"])\n" + + " Map map = [x:\"foo\",y:\"$bar\"]\n" + + "}\n", + }; + //@formatter:on + + runNegativeTest(sources, + "----------\n" + + "1. ERROR in Main.groovy (at line 5)\n" + + "\tm([x:\"foo\",y:\"$bar\"])\n" + + "\t^^^^^^^^^^^^^^^^^^^^^\n" + + "Groovy:[Static type checking] - You are trying to use a GString in place of a String in a type which explicitly declares accepting String. Make sure to call toString() on all GString values.\n" + + "----------\n" + + "2. ERROR in Main.groovy (at line 6)\n" + + "\tMap map = [x:\"foo\",y:\"$bar\"]\n" + + "\t ^^^^^^^^^^^^^^^^^^\n" + + "Groovy:[Static type checking] - You are trying to use a GString in place of a String in a type which explicitly declares accepting String. Make sure to call toString() on all GString values.\n" + + "----------\n"); + } } diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/GenericsType.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/GenericsType.java index 8feb271bd5..e593dd2038 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/GenericsType.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/ast/GenericsType.java @@ -531,7 +531,11 @@ private boolean compareGenericsWithBound(final ClassNode classNode, final ClassN if (!match) break; } } + /* GRECLIPSE edit -- GROOVY-10010 return match; + */ + continue; + // GRECLIPSE end } else if (classNodePlaceholders.containsKey(name)) { redirectBoundType = classNodePlaceholders.get(name); } diff --git a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 715e2c8cb5..0f44f231d8 100644 --- a/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy25/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -6267,6 +6267,11 @@ protected boolean typeCheckMethodsWithGenericsOrFail(ClassNode receiver, ClassNo final Parameter parameter = parameters[i]; ClassNode type = parameter.getType(); ptypes[i] = fullyResolveType(type, classGTs); + // GRECLIPSE add -- GROOVY-10010 + if (i < arguments.length && hasGStringStringError(ptypes[i], arguments[i], location)) { + return false; + } + // GRECLIPSE end } addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" + toMethodParametersString(candidateMethod.getName(), ptypes) + diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/GenericsType.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/GenericsType.java index f5a6b35a11..e63c041c06 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/GenericsType.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/ast/GenericsType.java @@ -490,7 +490,11 @@ private static boolean compareGenericsWithBound(final ClassNode classNode, final if (!match) break; } } + /* GRECLIPSE edit -- GROOVY-10010 return match; + */ + continue; + // GRECLIPSE end } } match = redirectBoundType.isCompatibleWith(classNodeType.getType()); diff --git a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 9e0b6f4b73..0b6b4f742f 100644 --- a/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy30/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -6031,6 +6031,11 @@ protected boolean typeCheckMethodsWithGenericsOrFail(final ClassNode receiver, f ClassNode[] paramTypes = new ClassNode[parameters.length]; for (int i = 0, n = parameters.length; i < n; i += 1) { paramTypes[i] = fullyResolveType(parameters[i].getType(), classGTs); + // GRECLIPSE add -- GROOVY-10010 + if (i < arguments.length && hasGStringStringError(paramTypes[i], arguments[i], location)) { + return false; + } + // GRECLIPSE end } addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" + toMethodParametersString(candidateMethod.getName(), paramTypes) + " with arguments " + formatArgumentList(arguments), location); diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/GenericsType.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/GenericsType.java index 3c8e000fe9..1cf424a4c8 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/GenericsType.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/ast/GenericsType.java @@ -495,7 +495,11 @@ private static boolean compareGenericsWithBound(final ClassNode classNode, final if (!match) break; } } + /* GRECLIPSE edit -- GROOVY-10010 return match; + */ + continue; + // GRECLIPSE end } } match = redirectBoundType.isCompatibleWith(classNodeType.getType()); diff --git a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java index 7ab999ea52..fe30449413 100644 --- a/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java +++ b/base/org.codehaus.groovy40/src/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java @@ -5979,6 +5979,11 @@ protected boolean typeCheckMethodsWithGenericsOrFail(final ClassNode receiver, f ClassNode[] paramTypes = new ClassNode[parameters.length]; for (int i = 0, n = parameters.length; i < n; i += 1) { paramTypes[i] = fullyResolveType(parameters[i].getType(), classGTs); + // GRECLIPSE add -- GROOVY-10010 + if (i < arguments.length && hasGStringStringError(paramTypes[i], arguments[i], location)) { + return false; + } + // GRECLIPSE end } addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" + toMethodParametersString(candidateMethod.getName(), paramTypes) + " with arguments " + formatArgumentList(arguments), location);