You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by su...@apache.org on 2021/03/31 00:23:58 UTC

[groovy] branch master updated: GROOVY-7106, GROOVY-7274, GROOVY-8909, GROOVY-9844: [] and [:] call args

This is an automated email from the ASF dual-hosted git repository.

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


The following commit(s) were added to refs/heads/master by this push:
     new c5fd01a  GROOVY-7106, GROOVY-7274, GROOVY-8909, GROOVY-9844: [] and [:] call args
c5fd01a is described below

commit c5fd01adbfe3f97c1defd12a18bf2096f970ecff
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Mar 28 14:06:00 2021 -0500

    GROOVY-7106, GROOVY-7274, GROOVY-8909, GROOVY-9844: [] and [:] call args
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 13 ++--
 .../transform/stc/StaticTypeCheckingVisitor.java   | 84 ++++++++++++++--------
 .../stc/ArraysAndCollectionsSTCTest.groovy         | 15 ++++
 .../transform/stc/ConstructorsSTCTest.groovy       | 58 +++++++++++----
 .../groovy/transform/stc/GenericsSTCTest.groovy    |  6 +-
 .../groovy/transform/stc/MethodCallsSTCTest.groovy | 41 +++++++++--
 .../transform/stc/STCExtensionMethodsTest.groovy   | 77 ++++++++++----------
 .../groovy/transform/BuilderTransformTest.groovy   |  4 +-
 8 files changed, 203 insertions(+), 95 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index 462f519..de491c4 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -57,6 +57,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.LinkedHashMap;
 import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
@@ -162,6 +163,7 @@ public abstract class StaticTypeCheckingSupport {
     protected static final ClassNode ArrayList_TYPE = makeWithoutCaching(ArrayList.class);
     protected static final ClassNode Collection_TYPE = makeWithoutCaching(Collection.class);
     protected static final ClassNode Deprecated_TYPE = makeWithoutCaching(Deprecated.class);
+    protected static final ClassNode LinkedHashMap_TYPE = makeWithoutCaching(LinkedHashMap.class);
     protected static final ClassNode LinkedHashSet_TYPE = makeWithoutCaching(LinkedHashSet.class);
 
     protected static final Map<ClassNode, Integer> NUMBER_TYPES = Maps.of(
@@ -1448,15 +1450,12 @@ public abstract class StaticTypeCheckingSupport {
         Set<GenericsTypeName> fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics);
 
         for (int i = 0, n = argumentTypes.length; i < n; i += 1) {
-            int pindex = min(i, parameters.length - 1);
-            ClassNode wrappedArgument = argumentTypes[i];
-            ClassNode type = parameters[pindex].getOriginType();
+            ClassNode argumentType = argumentTypes[i], parameterType = parameters[min(i, parameters.length - 1)].getOriginType();
+            failure |= inferenceCheck(fixedGenericsPlaceHolders, resolvedMethodGenerics, parameterType, argumentType, i >= parameters.length - 1);
 
-            failure = failure || inferenceCheck(fixedGenericsPlaceHolders, resolvedMethodGenerics, type, wrappedArgument, i >= parameters.length - 1);
-
-            // set real fixed generics for extension methods
-            if (isExtensionMethod && i == 0)
+            if (i == 0 && isExtensionMethod) { // set real fixed generics for extension methods
                 fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics);
+            }
         }
         return !failure;
     }
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 7b6bc43..b9fa745 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -133,7 +133,9 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.BiPredicate;
 import java.util.function.Supplier;
+import java.util.stream.IntStream;
 
 import static org.apache.groovy.util.BeanUtils.capitalize;
 import static org.apache.groovy.util.BeanUtils.decapitalize;
@@ -228,6 +230,7 @@ import static org.codehaus.groovy.syntax.Types.MOD_EQUAL;
 import static org.codehaus.groovy.syntax.Types.PLUS_PLUS;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.ArrayList_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Collection_TYPE;
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.LinkedHashMap_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.LinkedHashSet_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.Matcher_TYPE;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.NUMBER_OPS;
@@ -319,9 +322,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected static final MethodNode GET_THISOBJECT = CLOSURE_TYPE.getGetterMethod("getThisObject");
     protected static final ClassNode DELEGATES_TO = ClassHelper.make(DelegatesTo.class);
     protected static final ClassNode DELEGATES_TO_TARGET = ClassHelper.make(DelegatesTo.Target.class);
-    protected static final ClassNode LINKEDHASHMAP_CLASSNODE = ClassHelper.make(LinkedHashMap.class);
     protected static final ClassNode CLOSUREPARAMS_CLASSNODE = ClassHelper.make(ClosureParams.class);
     protected static final ClassNode NAMED_PARAMS_CLASSNODE = ClassHelper.make(NamedParams.class);
+    @Deprecated protected static final ClassNode LINKEDHASHMAP_CLASSNODE = LinkedHashMap_TYPE;
     protected static final ClassNode ENUMERATION_TYPE = ClassHelper.make(Enumeration.class);
     protected static final ClassNode MAP_ENTRY_TYPE = ClassHelper.make(Map.Entry.class);
     protected static final ClassNode ITERABLE_TYPE = ClassHelper.ITERABLE_TYPE;
@@ -1279,6 +1282,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return !(ArrayList_TYPE.isDerivedFrom(leftType) || ArrayList_TYPE.implementsInterface(leftType)
                     || LinkedHashSet_TYPE.isDerivedFrom(leftType) || LinkedHashSet_TYPE.implementsInterface(leftType));
         }
+        if (rightExpression instanceof MapExpression) {
+            return !(LinkedHashMap_TYPE.isDerivedFrom(leftType) || LinkedHashMap_TYPE.implementsInterface(leftType));
+        }
         return false;
     }
 
@@ -1390,9 +1396,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
         List<MethodNode> constructorList = findMethod(node, "<init>", arguments);
         if (constructorList.isEmpty()) {
-            if (isBeingCompiled(node) && arguments.length == 1 && LINKEDHASHMAP_CLASSNODE.equals(arguments[0])) {
+            if (isBeingCompiled(node) && arguments.length == 1 && LinkedHashMap_TYPE.equals(arguments[0])) {
                 // there will be a default hash map constructor added later
-                ConstructorNode cn = new ConstructorNode(Opcodes.ACC_PUBLIC, new Parameter[]{new Parameter(LINKEDHASHMAP_CLASSNODE, "args")}, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
+                ConstructorNode cn = new ConstructorNode(Opcodes.ACC_PUBLIC, new Parameter[]{new Parameter(LinkedHashMap_TYPE, "args")}, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE);
                 return cn;
             } else {
                 addStaticTypeError("No matching constructor found: " + node + toMethodParametersString("<init>", arguments), source);
@@ -2646,7 +2652,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 mn = findMethod(currentReceiver.getType(), name, args);
                 if (!mn.isEmpty()) {
                     if (mn.size() == 1) {
-                        // GROOVY-8961, GROOVY-9734, GROOVY-9915
+                        // GROOVY-8909, GROOVY-8961, GROOVY-9734, GROOVY-9844, GROOVY-9915, etc.
                         resolvePlaceholdersFromImplicitTypeHints(args, argumentList, mn.get(0));
                         typeCheckMethodsWithGenericsOrFail(currentReceiver.getType(), args, mn.get(0), call);
                     }
@@ -3527,7 +3533,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                                 returnType = typeCheckingContext.getEnclosingClassNode();
                             }
                         }
-                        // GROOVY-8961, GROOVY-9734
+                        // GROOVY-7106, GROOVY-7274, GROOVY-8909, GROOVY-8961, GROOVY-9734, GROOVY-9844, et al.
                         resolvePlaceholdersFromImplicitTypeHints(args, argumentList, directMethodCallCandidate);
                         if (typeCheckMethodsWithGenericsOrFail(chosenReceiver.getType(), args, directMethodCallCandidate, call)) {
                             returnType = adjustWithTraits(directMethodCallCandidate, chosenReceiver.getType(), args, returnType);
@@ -4363,16 +4369,24 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
-            if (rightExpression instanceof ListExpression && !leftRedirect.equals(OBJECT_TYPE)) {
-                if (LIST_TYPE.equals(leftRedirect)
-                        || ITERABLE_TYPE.equals(leftRedirect)
-                        || Collection_TYPE.equals(leftRedirect)
-                        || ArrayList_TYPE.isDerivedFrom(leftRedirect)) { // GROOVY-6912
-                    return getLiteralResultType(left, right, ArrayList_TYPE); // GROOVY-7128
+            if (!leftRedirect.equals(OBJECT_TYPE)) {
+                if (rightExpression instanceof ListExpression) {
+                    if (LIST_TYPE.equals(leftRedirect)
+                            || ITERABLE_TYPE.equals(leftRedirect)
+                            || Collection_TYPE.equals(leftRedirect)
+                            || ArrayList_TYPE.isDerivedFrom(leftRedirect)) { // GROOVY-6912
+                        return getLiteralResultType(left, right, ArrayList_TYPE); // GROOVY-7128
+                    }
+                    if (SET_TYPE.equals(leftRedirect)
+                            || LinkedHashSet_TYPE.isDerivedFrom(leftRedirect)) { // GROOVY-6912
+                        return getLiteralResultType(left, right, LinkedHashSet_TYPE); // GROOVY-7128
+                    }
                 }
-                if (SET_TYPE.equals(leftRedirect)
-                        || LinkedHashSet_TYPE.isDerivedFrom(leftRedirect)) { // GROOVY-6912
-                    return getLiteralResultType(left, right, LinkedHashSet_TYPE); // GROOVY-7128
+                if (rightExpression instanceof MapExpression) {
+                    if (MAP_TYPE.equals(leftRedirect)
+                            || LinkedHashMap_TYPE.isDerivedFrom(leftRedirect)) {
+                        return getLiteralResultType(left, right, LinkedHashMap_TYPE); // GROOVY-7128, GROOVY-9844
+                    }
                 }
             }
 
@@ -4430,15 +4444,24 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * the literal may be composed of sub-types of {@code Type}. In these cases,
      * {@code ArrayList<Type>} is an appropriate result type for the expression.
      */
-    private ClassNode getLiteralResultType(final ClassNode targetType, final ClassNode sourceType, final ClassNode baseType) {
+    private static ClassNode getLiteralResultType(final ClassNode targetType, final ClassNode sourceType, final ClassNode baseType) {
         ClassNode resultType = sourceType.equals(baseType) ? sourceType
                 : GenericsUtils.parameterizeType(sourceType, baseType.getPlainNodeReference());
 
         if (targetType.getGenericsTypes() != null
                 && !GenericsUtils.buildWildcardType(targetType).isCompatibleWith(resultType)) {
+            BiPredicate<GenericsType, GenericsType> isEqualOrSuper = (target, source) -> {
+                if (target.isCompatibleWith(source.getType())) {
+                    return true;
+                }
+                if (!target.isPlaceholder() && !target.isWildcard()) {
+                    return GenericsUtils.buildWildcardType(getCombinedBoundType(target)).isCompatibleWith(source.getType());
+                }
+                return false;
+            };
+
             GenericsType[] lgt = targetType.getGenericsTypes(), rgt = resultType.getGenericsTypes();
-            if (!lgt[0].isPlaceholder() && !lgt[0].isWildcard() && GenericsUtils.buildWildcardType(
-                    getCombinedBoundType(lgt[0])).isCompatibleWith(getCombinedBoundType(rgt[0]))) {
+            if (IntStream.range(0, lgt.length).allMatch(i -> isEqualOrSuper.test(lgt[i], rgt[i]))) {
                 resultType = GenericsUtils.parameterizeType(targetType, baseType.getPlainNodeReference());
             }
         }
@@ -4446,7 +4469,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return resultType;
     }
 
-    private ClassNode getMathResultType(final int op, final ClassNode leftRedirect, final ClassNode rightRedirect, final String operationName) {
+    private static ClassNode getMathResultType(final int op, final ClassNode leftRedirect, final ClassNode rightRedirect, final String operationName) {
         if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) {
             if (isOperationInGroup(op)) {
                 if (isIntCategory(leftRedirect) && isIntCategory(rightRedirect)) return int_TYPE;
@@ -5145,7 +5168,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected ClassNode inferMapExpressionType(final MapExpression map) {
-        ClassNode mapType = LINKEDHASHMAP_CLASSNODE.getPlainNodeReference();
+        ClassNode mapType = LinkedHashMap_TYPE.getPlainNodeReference();
         List<MapEntryExpression> entryExpressions = map.getMapEntryExpressions();
         int nExpressions = entryExpressions.size();
         if (nExpressions == 0) return mapType;
@@ -5293,24 +5316,29 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * method target of "m", {@code T} could be resolved.
      */
     private static void resolvePlaceholdersFromImplicitTypeHints(final ClassNode[] actuals, final ArgumentListExpression argumentList, final MethodNode inferredMethod) {
-        for (int i = 0, n = actuals.length; i < n; i += 1) {
-            // check for method call with known target
+        int np = inferredMethod.getParameters().length;
+        for (int i = 0, n = actuals.length; np > 0 && i < n; i += 1) {
             Expression a = argumentList.getExpression(i);
+            Parameter p = inferredMethod.getParameters()[Math.min(i, np - 1)];
+
+            ClassNode at = actuals[i], pt = p.getOriginType();
+            if (i >= (np - 1) && pt.isArray() && !at.isArray()) pt = pt.getComponentType();
+
+            if (a instanceof ListExpression) {
+                actuals[i] = getLiteralResultType(pt, at, ArrayList_TYPE);
+            } else if (a instanceof MapExpression) {
+                actuals[i] = getLiteralResultType(pt, at, LinkedHashMap_TYPE);
+            }
+
+            // check for method call with known target
             if (!(a instanceof MethodCallExpression)) continue;
             if (((MethodCallExpression) a).isUsingGenerics()) continue;
             MethodNode aNode = a.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
             if (aNode == null || aNode.getGenericsTypes() == null) continue;
 
             // and unknown generics
-            ClassNode at = actuals[i];
             if (!GenericsUtils.hasUnresolvedGenerics(at)) continue;
 
-            int np = inferredMethod.getParameters().length;
-            Parameter p = inferredMethod.getParameters()[Math.min(i, np - 1)];
-
-            ClassNode pt = p.getOriginType();
-            if (i >= (np - 1) && pt.isArray() && !at.isArray()) pt = pt.getComponentType();
-
             // try to resolve placeholder(s) in argument type using parameter type
 
             Map<GenericsTypeName, GenericsType> linked = new HashMap<>();
diff --git a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
index fa96651..35ac761 100644
--- a/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ArraysAndCollectionsSTCTest.groovy
@@ -741,4 +741,19 @@ class ArraysAndCollectionsSTCTest extends StaticTypeCheckingTestCase {
             assert set.last() == 3
         '''
     }
+
+    void testMapWithTypeArgumentsInitializedByMapLiteral() {
+        ['CharSequence,Integer', 'String,Number', 'CharSequence,Number'].each { spec ->
+            assertScript """
+                Map<$spec> map = [a:1,b:2,c:3]
+                assert map.size() == 3
+                assert map['c'] == 3
+                assert 'x' !in map
+            """
+        }
+
+        shouldFailWithMessages '''
+            Map<String,Integer> map = [1:2]
+        ''', 'Cannot assign java.util.LinkedHashMap <java.lang.Integer, java.lang.Integer> to: java.util.Map <String, Integer>'
+    }
 }
diff --git a/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy b/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
index 6e785b8..ac7c141 100644
--- a/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ConstructorsSTCTest.groovy
@@ -18,6 +18,8 @@
  */
 package groovy.transform.stc
 
+import org.codehaus.groovy.runtime.typehandling.GroovyCastException
+
 /**
  * Unit tests for static type checking : constructors.
  */
@@ -121,34 +123,60 @@ class ConstructorsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testConstructMap() {
+    void testConstructFromValuedMap1() {
         assertScript '''
-            def a = [:]
-            assert a instanceof Map
-
-            Map b = [:]
-            assert b instanceof Map
-
-            Object c = [:]
-            assert c instanceof Map
-
-            HashMap d = [:]
-            assert d instanceof HashMap
+            class A {
+                int x
+                int y
+            }
+            A a = [x:100, y:200]
+            assert a.x == 100
+            assert a.y == 200
         '''
     }
 
-    void testConstructFromValuedMap() {
+    void testConstructFromValuedMap2() {
         assertScript '''
-            class A {
+            class A<B,C> {
                 int x
                 int y
             }
-            A a = [x:100, y:200]
+            A<Number,String> a = [x:100, y:200]
             assert a.x == 100
             assert a.y == 200
         '''
     }
 
+    void testMapLiteral() {
+        assertScript '''
+            def m = [:]
+            assert m instanceof Map
+        '''
+        assertScript '''
+            Map m = [:]
+            assert m instanceof Map
+        '''
+        assertScript '''
+            Object m = [:]
+            assert m instanceof Map
+        '''
+        assertScript '''
+            HashMap m = [:]
+            assert m instanceof HashMap
+        '''
+        assertScript '''
+            LinkedHashMap m = [:]
+            assert m instanceof LinkedHashMap
+        '''
+
+        shouldFail GroovyCastException, '''
+            EnumMap m = [:] // constructor fails on empty map
+        '''
+        shouldFail GroovyCastException, '''
+            SortedMap m = [:] // no constructor for interface
+        '''
+    }
+
     // GROOVY-9603
     void testDoNotConstructFromValuedMap() {
         assertScript '''
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 83f141f..638d14c 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1586,7 +1586,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 println arg1 == arg2
             }
             printEqual(1, ['foo'])
-        ''', '#printEqual(T, java.util.List <T>) with arguments [int, java.util.List <java.lang.String>]'
+        ''', '#printEqual(T, java.util.List <T>) with arguments [int, java.util.ArrayList <java.lang.String>]'
     }
 
     // GROOVY-9902
@@ -1854,7 +1854,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 static <T extends List<? extends CharSequence>> void bar(T a) {}
             }
             Foo.bar([new Object()])
-        ''', 'Cannot call <T extends java.util.List<? extends java.lang.CharSequence>> Foo#bar(T) with arguments [java.util.List <java.lang.Object>]'
+        ''', 'Cannot call <T extends java.util.List<? extends java.lang.CharSequence>> Foo#bar(T) with arguments [java.util.ArrayList <java.lang.Object>]'
     }
 
     void testOutOfBoundsBySuperGenericParameterType() {
@@ -1863,7 +1863,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
                 static <T extends List<? super CharSequence>> void bar(T a) {}
             }
             Foo.bar(['abc'])
-        ''', 'Cannot call <T extends java.util.List<? super java.lang.CharSequence>> Foo#bar(T) with arguments [java.util.List <java.lang.String>]'
+        ''', 'Cannot call <T extends java.util.List<? super java.lang.CharSequence>> Foo#bar(T) with arguments [java.util.ArrayList <java.lang.String>]'
     }
 
     void testOutOfBoundsByExtendsPlaceholderParameterType() {
diff --git a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
index c1bd7f0..f077def 100644
--- a/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/MethodCallsSTCTest.groovy
@@ -20,7 +20,6 @@ package groovy.transform.stc
 
 import org.codehaus.groovy.control.MultipleCompilationErrorsException
 import org.codehaus.groovy.control.customizers.ImportCustomizer
-import groovy.test.NotYetImplemented
 
 /**
  * Unit tests for static type checking : method calls.
@@ -207,11 +206,45 @@ class MethodCallsSTCTest extends StaticTypeCheckingTestCase {
         ''', 'Cannot call groovy.transform.stc.MethodCallsSTCTest$MyMethodCallTestClass2#identity(java.lang.Integer[]) with arguments [java.lang.String[]]'
     }
 
-    @NotYetImplemented // GROOVY-8909
+    // GROOVY-8909
     void testGenericMethodCall4() {
         assertScript '''
-            def m(List<Object> list) { }
-            m([1, 2, 3]) // List<Integer>
+            void m(List<Object> list) {
+                assert list.size() == 3
+            }
+            m([1,2,3])
+        '''
+        // no coercion like assignment
+        shouldFailWithMessages '''
+            void m(Set<Integer> set) {
+            }
+            m([1,2,3,3])
+        ''', 'm(java.util.List <java.lang.Integer>). Please check if the declared type is correct and if the method exists.'
+    }
+
+    // GROOVY-7106, GROOVY-7274, GROOVY-9844
+    void testGenericMethodCall5() {
+        assertScript '''
+            void m(Map<CharSequence,Number> map) {
+                assert map.size() == 3
+                assert map['a'] == 1
+                assert 'z' !in map
+            }
+            m([a:1,b:2,c:3])
+        '''
+
+        assertScript '''
+            void m(Map<String,Object> map) {
+            }
+            m([d:new Date(), i:1, s:""])
+        '''
+
+        assertScript '''
+            void m(Map<String,Object> map) {
+            }
+            ['x'].each {
+                m([(it): it.toLowerCase()])
+            }
         '''
     }
 
diff --git a/src/test/groovy/transform/stc/STCExtensionMethodsTest.groovy b/src/test/groovy/transform/stc/STCExtensionMethodsTest.groovy
index 169ab1c..fa538aa 100644
--- a/src/test/groovy/transform/stc/STCExtensionMethodsTest.groovy
+++ b/src/test/groovy/transform/stc/STCExtensionMethodsTest.groovy
@@ -18,60 +18,65 @@
  */
 package groovy.transform.stc
 
-import org.codehaus.groovy.runtime.m12n.ExtensionModuleHelperForTests
+import static org.codehaus.groovy.runtime.m12n.ExtensionModuleHelperForTests.doInFork
 
 /**
  * Unit tests for static type checking : extension methods.
  */
 class STCExtensionMethodsTest extends StaticTypeCheckingTestCase {
 
-    void testShouldFindExtensionMethod() {
+    void testStaticExtensionMethod() {
         assertScript '''
-            // reverseToUpperCase is an extension method specific to unit tests
-            def str = 'This is a string'
-            assert str.reverseToUpperCase() == str.toUpperCase().reverse()
             assert String.answer() == 42
         '''
     }
 
-    void testShouldFindExtensionMethodWithGrab() {
-        ExtensionModuleHelperForTests.doInFork('groovy.transform.stc.StaticTypeCheckingTestCase', '''
-        def impl = new MetaClassImpl(String)
-        impl.initialize()
-        String.metaClass = impl
-        ExtensionModuleRegistry registry = GroovySystem.metaClassRegistry.moduleRegistry
-        // ensure that the module isn't loaded
-        assert !registry.modules.any { it.name == 'Test module for Grab' && it.version == '1.3' }
-
-        // find jar resource
-        def jarURL = this.class.getResource("/jars")
-        assert jarURL
-
-        def resolver = "@GrabResolver(name='local',root='$jarURL')"
-
-        assertScript resolver + """
-        @Grab('module-test:module-test:1.4')
-        import org.codehaus.groovy.runtime.m12n.*
+    void testNonStaticExtensionMethod() {
+        assertScript '''
+            def str = 'This is a string'
+            // reverseToUpperCase is a usnit test extension method
+            assert str.reverseToUpperCase() == str.toUpperCase().reverse()
+        '''
+    }
 
-        // the following methods are added by the Grab test module
-        def str = 'This is a string'
-        assert str.reverseToUpperCase2() == str.toUpperCase().reverse()
-        // a static method added to String thanks to a @Grab extension
-        assert String.answer2() == 42
-        """
-        ''')
+    // GROOVY-7953
+    void testExtensionPropertyWithPrimitiveReceiver() {
+        assertScript '''
+            assert 4.even
+        '''
     }
 
     void testExtensionMethodWithGenericsAndPrimitiveReceiver() {
         assertScript '''
             assert 2d.groovy6496(2d) == 2d
-    '''
+        '''
     }
 
-    //GROOVY-7953
-    void testExtensionPropertyWithPrimitiveReceiver() {
-        assertScript '''
-            assert 4.even
+    void testShouldFindExtensionMethodWithGrab() {
+        doInFork 'groovy.transform.stc.StaticTypeCheckingTestCase', '''
+            def impl = new MetaClassImpl(String)
+            impl.initialize()
+            String.metaClass = impl
+            ExtensionModuleRegistry registry = GroovySystem.metaClassRegistry.moduleRegistry
+            // ensure that the module isn't loaded
+            assert !registry.modules.any { it.name == 'Test module for Grab' && it.version == '1.3' }
+
+            // find jar resource
+            def jarURL = this.class.getResource('/jars')
+            assert jarURL
+
+            def resolver = "@GrabResolver(name='local',root='$jarURL')"
+
+            assertScript resolver + """
+                @Grab('module-test:module-test:1.4')
+                import org.codehaus.groovy.runtime.m12n.*
+
+                // the following methods are added by the Grab test module
+                def str = 'This is a string'
+                assert str.reverseToUpperCase2() == str.toUpperCase().reverse()
+                // a static method added to String thanks to a @Grab extension
+                assert String.answer2() == 42
+            """
         '''
     }
-}
\ No newline at end of file
+}
diff --git a/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy b/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
index a200ff6..461fd45 100644
--- a/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
@@ -232,7 +232,7 @@ class BuilderTransformTest extends CompilableTestSupport {
                 CookBook.builder().recipes([35, 42]).build()
             }
         '''
-        assert message =~ /.*Cannot call.*recipes.*java.util.List\s?<java.lang.String>.*with arguments.*java.util.List\s?<java.lang.Integer>.*/
+        assert message =~ /.*Cannot call.*recipes.*java.util.List\s?<java.lang.String>.*with arguments.*java.util.(Array)?List\s?<java.lang.Integer>.*/
     }
 
     void testInitializerGenerics() {
@@ -261,7 +261,7 @@ class BuilderTransformTest extends CompilableTestSupport {
                 new CookBook(CookBook.createInitializer().recipes([35, 42]))
             }
         '''
-        assert message =~ /.*Cannot call.*recipes.*java.util.List\s?<java.lang.String>.*with arguments.*java.util.List\s?<java.lang.Integer>.*/
+        assert message =~ /.*Cannot call.*recipes.*java.util.List\s?<java.lang.String>.*with arguments.*java.util.(Array)?List\s?<java.lang.Integer>.*/
     }
 
     void testDefaultBuilderCustomNames() {