GROOVY-5516: Calling .addAll with a List throws type checking error if list makes use of generic types
diff --git a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 7ebcd12..a2baf72 100644
--- a/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2434,7 +2434,9 @@
receiver.getGenericsTypes(),
type.getGenericsTypes());
if (methodGenericTypes.length == 1) {
- ClassNode nodeType = getWrapper(methodGenericTypes[0].getType());
+ // if it is a wildcard, we're only able, for now, to perform limited type checking
+ // todo: improve type checking, which probably means having a more interesting data structure too
+ ClassNode nodeType = methodGenericTypes[0].isWildcard()?OBJECT_TYPE:getWrapper(methodGenericTypes[0].getType());
GenericsType[] argumentGenericTypes = arguments[argNum].getGenericsTypes();
ClassNode actualType = argumentGenericTypes != null ? getWrapper(argumentGenericTypes[0].getType()) : nodeType;
if (!implementsInterfaceOrIsSubclassOf(actualType, nodeType)) {
@@ -2452,13 +2454,18 @@
componentType.getGenericsTypes());
if (methodGenericTypes.length == 1) {
ClassNode nodeType = getWrapper(methodGenericTypes[0].getType());
- ClassNode actualType = getWrapper(arguments[argNum].getComponentType());
- if (!implementsInterfaceOrIsSubclassOf(actualType, nodeType)) {
+ ClassNode argComponentType = arguments[argNum].getComponentType();
+ if (argComponentType==null) {
failure = true;
- // for proper error message
- GenericsType baseGT = methodGenericTypes[0];
- methodGenericTypes[0] = new GenericsType(baseGT.getType(), baseGT.getUpperBounds(), baseGT.getLowerBound());
- methodGenericTypes[0].setType(methodGenericTypes[0].getType().makeArray());
+ } else {
+ ClassNode actualType = getWrapper(argComponentType);
+ if (!implementsInterfaceOrIsSubclassOf(actualType, nodeType)) {
+ failure = true;
+ // for proper error message
+ GenericsType baseGT = methodGenericTypes[0];
+ methodGenericTypes[0] = new GenericsType(baseGT.getType(), baseGT.getUpperBounds(), baseGT.getLowerBound());
+ methodGenericTypes[0].setType(methodGenericTypes[0].getType().makeArray());
+ }
}
} else {
// not sure this is possible !
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index d2962b6..137b1ed 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -470,6 +470,22 @@
''', 'Cannot find matching method groovy.transform.stc.GenericsSTCTest$ClassA#bar'
}
+ // GROOVY-5516
+ void testAddAllWithCollectionShouldBeAllowed() {
+ assertScript '''
+ List<String> list = ['a','b','c']
+ Collection<String> e = list.findAll { it }
+ list.addAll(e)
+ '''
+ }
+ void testAddAllWithCollectionShouldNotBeAllowed() {
+ shouldFailWithMessages '''
+ List<String> list = ['a','b','c']
+ Collection<Integer> e = (Collection<Integer>) [1,2,3]
+ list.addAll(e)
+ ''', 'Cannot call java.util.List#addAll(java.lang.String) with arguments [java.util.Collection <Integer>]'
+ }
+
static class MyList extends LinkedList<String> {}
public static class ClassA<T> {