You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2021/08/17 16:48:49 UTC
[groovy] 02/04: GROOVY-10010: check GString element vs String
collection for method call
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch GROOVY_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit 1cf87b6a2055d809c0cea7c57804df53b26d716d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Apr 5 14:13:34 2021 -0500
GROOVY-10010: check GString element vs String collection for method call
---
.../java/org/codehaus/groovy/ast/GenericsType.java | 2 +-
.../transform/stc/StaticTypeCheckingVisitor.java | 4 ++
.../groovy/transform/stc/GenericsSTCTest.groovy | 80 +++++++++++++++-------
3 files changed, 61 insertions(+), 25 deletions(-)
diff --git a/src/main/java/org/codehaus/groovy/ast/GenericsType.java b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
index a1da7a6..ba8dc5d 100644
--- a/src/main/java/org/codehaus/groovy/ast/GenericsType.java
+++ b/src/main/java/org/codehaus/groovy/ast/GenericsType.java
@@ -445,7 +445,7 @@ public class GenericsType extends ASTNode {
if (!match) break;
}
}
- return match;
+ continue;
}
}
match = redirectBoundType.isCompatibleWith(classNodeType.getType());
diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 4172126..41256b3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -5567,6 +5567,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
ClassNode[] paramTypes = new ClassNode[parameters.length];
for (int i = 0, n = parameters.length; i < n; i += 1) {
paramTypes[i] = fullyResolveType(parameters[i].getType(), classGTs);
+ // GROOVY-10010: check for List<String> parameter and ["foo","$bar"] argument
+ if (i < arguments.length && hasGStringStringError(paramTypes[i], arguments[i], location)) {
+ return false;
+ }
}
addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" +
toMethodParametersString(candidateMethod.getName(), paramTypes) + " with arguments " + formatArgumentList(arguments), location);
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 3d47868..800ea5f 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -45,6 +45,13 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
''', 'Incompatible generic argument types. Cannot assign java.util.HashMap <String, Integer> to: java.util.Map <String, String>'
}
+ void testDeclaration4() {
+ // no generics checked after first wildcard
+ shouldFailWithMessages '''
+ Map<? extends CharSequence,String> obj = new HashMap<String,Integer>()
+ ''', 'Incompatible generic argument types. Cannot assign java.util.HashMap <String, Integer> to: java.util.Map <? extends java.lang.CharSequence, String>'
+ }
+
void testAddOnList() {
shouldFailWithMessages '''
List<String> list = []
@@ -816,34 +823,59 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
'''
}
- // GROOVY-5559
+ // GROOVY-5559, GROOVY-10010
void testGStringInListShouldNotBeConsideredAsAString() {
- assertScript '''import org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode as LUB
- def bar = 1
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
- assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
- })
- def list = ["foo", "$bar"]
+ String base = '''import org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode as LUB
+ def bar = 1
'''
- shouldFailWithMessages '''import org.codehaus.groovy.ast.tools.WideningCategories.LowestUpperBoundClassNode as LUB
- def bar = 1
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
- assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
- })
- List<String> list = ["foo", "$bar"]
- ''', 'You are trying to use a GString'
+ assertScript base + '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
+ assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
+ })
+ def list = ["foo", "$bar"]
+ '''
- shouldFailWithMessages '''
- def bar = 1
- @ASTTest(phase=INSTRUCTION_SELECTION, value={
- assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
- assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type == GSTRING_TYPE
- })
- List<String> list = ["$bar"] // single element means no LUB
- ''', 'You are trying to use a GString'
+ shouldFailWithMessages base + '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
+ assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type instanceof LUB
+ })
+ List<String> list = ["foo", "$bar"]
+ ''', 'You are trying to use a GString in place of a String'
+
+ shouldFailWithMessages base + '''
+ @ASTTest(phase=INSTRUCTION_SELECTION, value={
+ assert node.getNodeMetaData(INFERRED_TYPE) == LIST_TYPE
+ assert node.getNodeMetaData(INFERRED_TYPE).genericsTypes[0].type == GSTRING_TYPE // single element means no LUB
+ })
+ List<String> list = ["$bar"]
+ ''', 'You are trying to use a GString in place of a String'
+
+ shouldFailWithMessages base + '''
+ void m(List<String> list) {}
+ m(["foo", "$bar"])
+ ''', 'You are trying to use a GString in place of a String'
+ }
+
+ // GROOVY-5559, GROOVY-10010
+ void testGStringInMapShouldNotBeConsideredAsAString() {
+ String base = 'def bar = 123'
+
+ shouldFailWithMessages base + '''
+ Map<String,String> map = [x:"foo", y:"$bar"]
+ ''', 'You are trying to use a GString in place of a String'
+
+ shouldFailWithMessages base + '''
+ void m(Map<?,String> map) {}
+ m([x:"foo", y:"$bar"])
+ ''', 'You are trying to use a GString in place of a String'
+
+ shouldFailWithMessages base + '''
+ void m(Map<?,String> map) {}
+ m(x:"foo", y:"$bar")
+ ''', 'You are trying to use a GString in place of a String'
}
// GROOVY-5559: related behaviour