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