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 2022/07/26 14:22:09 UTC

[groovy] branch GROOVY_4_0_X updated (73e9c9f07d -> f0c3dd5f03)

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

emilles pushed a change to branch GROOVY_4_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git


    from 73e9c9f07d Bump version on GROOVY_4_0_X branch
     new 8cc615e6da GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`
     new 5145aa4ae8 GROOVY-10271, GROOVY-10272: STC: process closure in ternary expression
     new 9508db373f GROOVY-10688: STC: common generics resolver for assign and elvis/ternary
     new a38856efa3 GROOVY-10698: STC: apply explicit/implicit type arguments to parameters
     new f0c3dd5f03 GROOVY-10674: add test case

The 5 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 src/main/groovy/groovy/grape/GrapeIvy.groovy       |   6 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   | 110 ++++++++++++---------
 src/test/groovy/grape/GrabResolverTest.groovy      |   4 +-
 .../groovy/transform/stc/ClosuresSTCTest.groovy    |   6 +-
 .../groovy/transform/stc/GenericsSTCTest.groovy    |  53 ++++++++++
 .../groovy/transform/stc/STCAssignmentTest.groovy  |  35 +++++--
 .../transform/stc/TernaryOperatorSTCTest.groovy    |  26 ++++-
 .../groovy/macro/matcher/ASTMatcher.groovy         |  52 +++++-----
 8 files changed, 197 insertions(+), 95 deletions(-)


[groovy] 04/05: GROOVY-10698: STC: apply explicit/implicit type arguments to parameters

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit a38856efa3f67d674e10aa278b83bb921ffe055d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jul 24 11:52:36 2022 -0500

    GROOVY-10698: STC: apply explicit/implicit type arguments to parameters
---
 .../transform/stc/StaticTypeCheckingVisitor.java       |  9 +++++----
 src/test/groovy/transform/stc/GenericsSTCTest.groovy   | 18 ++++++++++++++++++
 2 files changed, 23 insertions(+), 4 deletions(-)

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 0ac085a786..473a1ccb55 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -2275,9 +2275,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                             && parameters.length == argumentTypes.length - 1) {
                         ctor = typeCheckMapConstructor(call, receiver, arguments);
                     } else {
-                        if (asBoolean(receiver.getGenericsTypes())) { // GROOVY-10283, GROOVY-10316, GROOVY-10482, GROOVY-10624
-                            Map<GenericsTypeName, GenericsType> context = extractPlaceHolders(receiver, ctor.getDeclaringClass());
-                            parameters = Arrays.stream(parameters).map(p -> new Parameter(applyGenericsContext(context, p.getType()), p.getName())).toArray(Parameter[]::new);
+                        GenericsType[] typeParameters = ctor.getDeclaringClass().getGenericsTypes();
+                        if (typeParameters != null) { // GROOVY-10283, GROOVY-10316, GROOVY-10482, GROOVY-10624, GROOVY-10698
+                            Map<GenericsTypeName, GenericsType> context = extractGenericsConnectionsFromArguments(typeParameters, parameters, argumentList, receiver.getGenericsTypes());
+                            if (!context.isEmpty()) parameters = Arrays.stream(parameters).map(p -> new Parameter(applyGenericsContext(context, p.getType()), p.getName())).toArray(Parameter[]::new);
                         }
                         resolvePlaceholdersFromImplicitTypeHints(argumentTypes, argumentList, parameters);
                         typeCheckMethodsWithGenericsOrFail(receiver, argumentTypes, ctor, call);
@@ -5362,7 +5363,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private Map<GenericsTypeName, GenericsType> extractGenericsConnectionsFromArguments(final GenericsType[] methodGenericTypes, final Parameter[] parameters, final Expression arguments, final GenericsType[] explicitTypeHints) {
         Map<GenericsTypeName, GenericsType> resolvedPlaceholders = new HashMap<>();
 
-        if (explicitTypeHints != null) { // resolve type parameters from type arguments
+        if (asBoolean(explicitTypeHints)) { // resolve type parameters from type arguments
             int n = methodGenericTypes.length;
             if (n == explicitTypeHints.length) {
                 for (int i = 0; i < n; i += 1) {
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index ee17a5d5f3..843abf5947 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1470,6 +1470,24 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10698
+    void testDiamondInferrenceFromConstructor34() {
+        assertScript '''
+            class A<T> {
+                A(T t, B<T> b_of_t) {
+                }
+            }
+            class B<U> {
+            }
+
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                def type = node.getNodeMetaData(INFERRED_TYPE)
+                assert type.toString(false) == 'A<java.lang.String>'
+            })
+            def x = new A<>('witness', new B<>()) // Cannot call A#<init>(Object,B<Object>) with arguments [String, B<T>]
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''


[groovy] 05/05: GROOVY-10674: add test case

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit f0c3dd5f03b92644a9b260bc4e56000cfeb4169c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Jul 24 11:53:48 2022 -0500

    GROOVY-10674: add test case
---
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 35 ++++++++++++++++++++++
 1 file changed, 35 insertions(+)

diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index 843abf5947..35e8642d02 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1488,6 +1488,41 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10674
+    void testDiamondInferrenceFromConstructor35() {
+        assertScript '''
+            class Foo<BB extends Bar<Byte>, X extends BB> {
+                X x
+                Foo(X x) {
+                    this.x = x
+                }
+            }
+            class Bar<T extends Number> {
+            }
+
+            class Baz {
+                static Foo<Bar<Byte>, ? super Bar<Byte>> foo = new Foo<>(new Bar<>())
+            }
+            new Baz()
+        '''
+
+        assertScript '''
+            class Foo<BBQ extends Bar<Byte, ? extends Byte>, X extends BBQ> {
+                X x
+                Foo(X x) {
+                    this.x = x
+                }
+            }
+            class Bar<T extends Number, S extends T> {
+            }
+
+            class Baz {
+                Foo<Bar<Byte,Byte>, ? super Bar<Byte,Byte>> foo = new Foo<>(new Bar<>())
+            }
+            new Baz()
+        '''
+    }
+
     // GROOVY-10280
     void testTypeArgumentPropagation() {
         assertScript '''


[groovy] 02/05: GROOVY-10271, GROOVY-10272: STC: process closure in ternary expression

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 5145aa4ae8d5ee9c0e04e16d3c0b8dcbad5e591f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 19 12:28:46 2022 -0500

    GROOVY-10271, GROOVY-10272: STC: process closure in ternary expression
    
    4_0_X backport
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 23 +++++++++++++++++-----
 .../transform/stc/TernaryOperatorSTCTest.groovy    |  6 +++---
 2 files changed, 21 insertions(+), 8 deletions(-)

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 7569f9683e..a38c74f094 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4205,12 +4205,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
         Expression trueExpression = expression.getTrueExpression();
         ClassNode typeOfTrue = findCurrentInstanceOfClass(trueExpression, null);
-        trueExpression.visit(this);
-        if (typeOfTrue == null) typeOfTrue = getType(trueExpression);
+        typeOfTrue = Optional.ofNullable(typeOfTrue).orElse(visitValueExpression(trueExpression));
         typeCheckingContext.popTemporaryTypeInfo(); // instanceof doesn't apply to false branch
         Expression falseExpression = expression.getFalseExpression();
-        falseExpression.visit(this);
-        ClassNode typeOfFalse = getType(falseExpression);
+        ClassNode typeOfFalse = visitValueExpression(falseExpression);
 
         ClassNode resultType;
         if (isNullConstant(trueExpression) && isNullConstant(falseExpression)) { // GROOVY-5523
@@ -4230,6 +4228,18 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         popAssignmentTracking(oldTracker);
     }
 
+    /**
+     * @param expr true or false branch of ternary expression
+     * @return the inferred type of {@code expr}
+     */
+    private ClassNode visitValueExpression(final Expression expr) {
+        if (expr instanceof ClosureExpression) {
+            applyTargetType(checkForTargetType(expr, null), expr);
+        }
+        expr.visit(this);
+        return getType(expr);
+    }
+
     /**
      * @param expr true or false branch of ternary expression
      * @param type the inferred type of {@code expr}
@@ -4255,11 +4265,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
              targetType = enclosingMethod.getReturnType();
         }
 
+        if (expr instanceof ClosureExpression) { // GROOVY-10271, GROOVY-10272
+            return isSAMType(targetType) ? targetType : sourceType;
+        }
+
         if (expr instanceof ConstructorCallExpression) { // GROOVY-9972, GROOVY-9983
             // GROOVY-10114: type parameter(s) could be inferred from call arguments
             if (targetType == null) targetType = sourceType.getPlainNodeReference();
             inferDiamondType((ConstructorCallExpression) expr, targetType);
-            return sourceType;
         }
 
         if (targetType == null) return sourceType;
diff --git a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
index 3b975d2c4c..61deb89ff1 100644
--- a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
@@ -166,7 +166,7 @@ class TernaryOperatorSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    @NotYetImplemented // GROOVY-10271
+    // GROOVY-10271
     void testFunctionalInterfaceTarget1() {
         for (flag in ['true', 'false']) {
             assertScript """import java.util.function.Supplier
@@ -179,7 +179,7 @@ class TernaryOperatorSTCTest extends StaticTypeCheckingTestCase {
         }
     }
 
-    @NotYetImplemented // GROOVY-10272
+    // GROOVY-10272
     void testFunctionalInterfaceTarget2() {
         assertScript '''
             import java.util.function.Function
@@ -235,7 +235,7 @@ class TernaryOperatorSTCTest extends StaticTypeCheckingTestCase {
     }
 
     // GROOVY-10358
-    void testCommonInterface() {
+    void testCommonInterface1() {
         assertScript '''
             interface I {
                 int m(int i)


[groovy] 01/05: GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 8cc615e6dad818ca19246c6cfddbd72cb3db8fe2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun May 15 13:27:39 2022 -0500

    GROOVY-10356, GROOVY-10623: STC: inferred variable type following `null`
---
 src/main/groovy/groovy/grape/GrapeIvy.groovy       |  6 +--
 .../transform/stc/StaticTypeCheckingVisitor.java   |  2 +
 src/test/groovy/grape/GrabResolverTest.groovy      |  4 +-
 .../groovy/transform/stc/ClosuresSTCTest.groovy    |  6 +--
 .../groovy/transform/stc/STCAssignmentTest.groovy  | 35 ++++++++++-----
 .../groovy/macro/matcher/ASTMatcher.groovy         | 52 +++++++++++-----------
 6 files changed, 60 insertions(+), 45 deletions(-)

diff --git a/src/main/groovy/groovy/grape/GrapeIvy.groovy b/src/main/groovy/groovy/grape/GrapeIvy.groovy
index 4afe525472..bfc00258f1 100644
--- a/src/main/groovy/groovy/grape/GrapeIvy.groovy
+++ b/src/main/groovy/groovy/grape/GrapeIvy.groovy
@@ -457,11 +457,11 @@ class GrapeIvy implements GrapeEngine {
         if (report.getDownloadSize() && reportDownloads) {
             System.err.println("Downloaded ${report.getDownloadSize() >> 10} Kbytes in ${report.getDownloadTime()}ms:\n  ${report.getAllArtifactsReports()*.toString().join('\n  ')}")
         }
-        md = report.getModuleDescriptor()
 
         if (!args.preserveFiles) {
-            cacheManager.getResolvedIvyFileInCache(md.getModuleRevisionId()).delete()
-            cacheManager.getResolvedIvyPropertiesInCache(md.getModuleRevisionId()).delete()
+            def revision = report.getModuleDescriptor().getModuleRevisionId()
+            cacheManager.getResolvedIvyPropertiesInCache(revision).delete()
+            cacheManager.getResolvedIvyFileInCache(revision).delete()
         }
 
         report
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 8981a9350a..7569f9683e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4341,6 +4341,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // instead of storing an "unknown" type, reset the type information
             // by determining the declaration type of the expression
             cn = getOriginalDeclarationType(exp);
+            // GROOVY-10356, GROOVY-10623: "def"
+            if (isDynamicTyped(cn)) return;
         }
         if (cn != null && isPrimitiveType(cn)) {
             if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) {
diff --git a/src/test/groovy/grape/GrabResolverTest.groovy b/src/test/groovy/grape/GrabResolverTest.groovy
index fe370b1892..2eb0557573 100644
--- a/src/test/groovy/grape/GrabResolverTest.groovy
+++ b/src/test/groovy/grape/GrabResolverTest.groovy
@@ -50,7 +50,9 @@ final class GrabResolverTest {
         grapeRoot.deleteOnExit()
 
         Grape.instance.settings.getResolver('downloadGrapes').resolvers.removeAll {
-            it.name == 'jcenter' || it.name == 'localm2' || it.name == 'cachedGrapes'
+            // jcenter is no longer used but it is left in this test just in case
+            // someone running this test has an old ~/.groovy/grapeConfig.xml
+            it.name == 'localm2' || it.name == 'cachedGrapes' || it.name == 'jcenter'
         }
     }
 
diff --git a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
index d922bb572a..b233142aa3 100644
--- a/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosuresSTCTest.groovy
@@ -18,8 +18,6 @@
  */
 package groovy.transform.stc
 
-import groovy.test.NotYetImplemented
-
 /**
  * Unit tests for static type checking : closures.
  */
@@ -375,7 +373,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
         'Cannot find matching method A#m()'
     }
 
-    @NotYetImplemented // GROOVY-10356
+    // GROOVY-10356
     void testClosureSharedVariable4() {
         assertScript '''
             interface A {
@@ -385,7 +383,7 @@ class ClosuresSTCTest extends StaticTypeCheckingTestCase {
             def x = { ->
                 a = null
             }
-            a?.m() // A closure shared variable [a] has been assigned with various types and ...
+            a?.m()
         '''
     }
 
diff --git a/src/test/groovy/transform/stc/STCAssignmentTest.groovy b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
index 519743417a..c573582bcc 100644
--- a/src/test/groovy/transform/stc/STCAssignmentTest.groovy
+++ b/src/test/groovy/transform/stc/STCAssignmentTest.groovy
@@ -1062,18 +1062,22 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         ''', 'Inconvertible types: cannot cast java.lang.String[] to java.util.Set[]'
     }
 
-    // GROOVY-5535
+    // GROOVY-5535, GROOVY-10623
     void testAssignToNullInsideIf() {
-        assertScript '''
-            Date test() {
-                Date x = new Date()
-                if (true) {
-                    x = null
+        ['Date', 'def', 'var'].each {
+            assertScript """
+                Date test() {
+                    $it x = new Date()
+                    if (true) {
+                        x = null
+                        Date y = x
+                    }
+                    Date z = x
+                    return x
                 }
-                x
-            }
-            assert test() == null
-        '''
+                assert test() == null
+            """
+        }
     }
 
     // GROOVY-10294
@@ -1103,6 +1107,17 @@ class STCAssignmentTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10623
+    void testAssignToNullAfterInit() {
+        assertScript '''
+            class C {
+            }
+            def x = new C()
+            x = null
+            C c = x
+        '''
+    }
+
     // GROOVY-5798
     void testShouldNotThrowConversionError() {
         assertScript '''
diff --git a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
index 857c71212d..c2bd6a9480 100644
--- a/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
+++ b/subprojects/groovy-macro/src/main/groovy/org/codehaus/groovy/macro/matcher/ASTMatcher.groovy
@@ -75,17 +75,16 @@ import org.codehaus.groovy.macro.matcher.internal.MatchingConstraintsBuilder
 @AutoFinal @CompileStatic
 class ASTMatcher extends ContextualClassCodeVisitor {
 
-    public static final String WILDCARD = "_"
+    public static final String WILDCARD = '_'
 
-    private Object current = null
     private boolean match = true
+    private Object  current
 
     private ASTMatcher() {
     }
 
     @Override
     protected SourceUnit getSourceUnit() {
-        return null
     }
 
     /**
@@ -230,7 +229,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
             def nodeProps = node.properties
             def curProps = cur.properties
             if (nodeProps.size() == curProps.size()) {
-                def iter = curProps.iterator()
+                Iterator<? extends ASTNode> iter = curProps.iterator()
                 // now let's visit the contents of the class
                 for (PropertyNode pn : nodeProps) {
                     doWithNode(pn, iter.next()) {
@@ -307,8 +306,7 @@ class ASTMatcher extends ContextualClassCodeVisitor {
     void visitImports(ModuleNode node) {
         if (node) {
             doWithNode(node, current) {
-                ModuleNode module = (ModuleNode) current
-                def imports = module.imports
+                def imports = ((ModuleNode) current).imports
                 if (imports.size() == node.imports.size()) {
                     def iter = imports.iterator()
                     for (ImportNode importNode : node.imports) {
@@ -321,38 +319,38 @@ class ASTMatcher extends ContextualClassCodeVisitor {
                     failIfNot(false)
                     return
                 }
-                imports = module.starImports
-                if (imports.size() == node.starImports.size()) {
-                    def iter = imports.iterator()
-                    for (ImportNode importNode : node.starImports) {
-                        doWithNode(importNode, iter.next()) {
-                            visitAnnotations(importNode)
-                            importNode.visit(this)
+                def starImports = ((ModuleNode) current).starImports
+                if (starImports.size() == node.starImports.size()) {
+                    def iter = starImports.iterator()
+                    for (starImport in node.starImports) {
+                        doWithNode(starImport, iter.next()) {
+                            visitAnnotations(starImport)
+                            starImport.visit(this)
                         }
                     }
                 } else {
                     failIfNot(false)
                     return
                 }
-                imports = module.staticImports
-                if (imports.size() == node.staticImports.size()) {
-                    def iter = imports.values().iterator()
-                    for (ImportNode importNode : node.staticImports.values()) {
-                        doWithNode(importNode, iter.next()) {
-                            visitAnnotations(importNode)
-                            importNode.visit(this)
+                def staticImports = ((ModuleNode) current).staticImports
+                if (staticImports.size() == node.staticImports.size()) {
+                    def iter = staticImports.values().iterator()
+                    for (staticImport in node.staticImports.values()) {
+                        doWithNode(staticImport, iter.next()) {
+                            visitAnnotations(staticImport)
+                            staticImport.visit(this)
                         }
                     }
                 } else {
                     failIfNot(false)
                 }
-                imports = module.staticStarImports
-                if (imports.size() == node.staticStarImports.size()) {
-                    def iter = imports.values().iterator()
-                    for (ImportNode importNode : node.staticStarImports.values()) {
-                        doWithNode(importNode, iter.next()) {
-                            visitAnnotations(importNode)
-                            importNode.visit(this)
+                def staticStarImports = ((ModuleNode) current).staticStarImports
+                if (staticStarImports.size() == node.staticStarImports.size()) {
+                    def iter = staticStarImports.values().iterator()
+                    for (staticStarImport in node.staticStarImports.values()) {
+                        doWithNode(staticStarImport, iter.next()) {
+                            visitAnnotations(staticStarImport)
+                            staticStarImport.visit(this)
                         }
                     }
                 } else {


[groovy] 03/05: GROOVY-10688: STC: common generics resolver for assign and elvis/ternary

Posted by em...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

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

commit 9508db373fd5fe47d048e78e0e7edeb508bd6d5f
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Jul 25 14:23:46 2022 -0500

    GROOVY-10688: STC: common generics resolver for assign and elvis/ternary
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 78 +++++++++++-----------
 .../transform/stc/TernaryOperatorSTCTest.groovy    | 20 ++++++
 2 files changed, 59 insertions(+), 39 deletions(-)

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 a38c74f094..0ac085a786 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -841,33 +841,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (rightExpression instanceof ConstructorCallExpression)
                     inferDiamondType((ConstructorCallExpression) rightExpression, lType);
 
-                if (lType.isUsingGenerics()
-                        && missesGenericsTypes(resultType)
-                        // GROOVY-10324, GROOVY-10342, et al.
-                        && !resultType.isGenericsPlaceHolder()) {
-                    // unchecked assignment
-                    // List<Type> list = new LinkedList()
-                    // Iterable<Type> iter = new LinkedList()
-                    // Collection<Type> coll = Collections.emptyList()
-                    // Collection<Type> view = ConcurrentHashMap.newKeySet()
-
-                    // the inferred type of the binary expression is the type of the RHS
-                    // "completed" with generics type information available from the LHS
-                    if (lType.equals(resultType)) {
-                        // GROOVY-6126, GROOVY-6558, GROOVY-6564, et al.
-                        if (!lType.isGenericsPlaceHolder()) resultType = lType;
-                    } else {
-                        // GROOVY-5640, GROOVY-9033, GROOVY-10220, GROOVY-10235, et al.
-                        Map<GenericsTypeName, GenericsType> gt = new HashMap<>();
-                        extractGenericsConnections(gt, resultType, resultType.redirect());
-                        ClassNode sc = resultType;
-                        do { sc = getNextSuperClass(sc, lType);
-                        } while (sc != null && !sc.equals(lType));
-                        extractGenericsConnections(gt, lType, sc);
-
-                        resultType = applyGenericsContext(gt, resultType.redirect());
-                    }
-                }
+                // handle unchecked assignment: List<Type> list = []
+                resultType = adjustForTargetType(resultType, lType);
 
                 ClassNode originType = getOriginalDeclarationType(leftExpression);
                 typeCheckAssignment(expression, leftExpression, originType, rightExpression, resultType);
@@ -4245,7 +4220,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param type the inferred type of {@code expr}
      */
     private ClassNode checkForTargetType(final Expression expr, final ClassNode type) {
-        ClassNode sourceType = type;
         ClassNode targetType = null;
         MethodNode enclosingMethod = typeCheckingContext.getEnclosingMethod();
         MethodCall enclosingMethodCall = (MethodCall)typeCheckingContext.getEnclosingMethodCall();
@@ -4266,25 +4240,51 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
 
         if (expr instanceof ClosureExpression) { // GROOVY-10271, GROOVY-10272
-            return isSAMType(targetType) ? targetType : sourceType;
+            return isSAMType(targetType) ? targetType : type;
         }
 
-        if (expr instanceof ConstructorCallExpression) { // GROOVY-9972, GROOVY-9983
-            // GROOVY-10114: type parameter(s) could be inferred from call arguments
-            if (targetType == null) targetType = sourceType.getPlainNodeReference();
+        if (targetType == null)
+            targetType = type.getPlainNodeReference();
+        if (type == UNKNOWN_PARAMETER_TYPE) return targetType;
+
+        if (expr instanceof ConstructorCallExpression) { // GROOVY-9972, GROOVY-9983, GROOVY-10114
             inferDiamondType((ConstructorCallExpression) expr, targetType);
         }
 
-        if (targetType == null) return sourceType;
+        return adjustForTargetType(type, targetType);
+    }
+
+    private static ClassNode adjustForTargetType(final ClassNode resultType, final ClassNode targetType) {
+        if (targetType.isUsingGenerics()
+                && missesGenericsTypes(resultType)
+                // GROOVY-10324, GROOVY-10342, et al.
+                && !resultType.isGenericsPlaceHolder()) {
+            // unchecked assignment
+            // List<Type> list = new LinkedList()
+            // Iterable<Type> iter = new LinkedList()
+            // Collection<Type> col1 = Collections.emptyList()
+            // Collection<Type> col2 = Collections.emptyList() ?: []
+            // Collection<Type> view = ConcurrentHashMap.newKeySet()
+
+            // the inferred type of the binary expression is the type of the RHS
+            // "completed" with generics type information available from the LHS
+            if (targetType.equals(resultType)) {
+                // GROOVY-6126, GROOVY-6558, GROOVY-6564, et al.
+                if (!targetType.isGenericsPlaceHolder()) return targetType;
+            } else {
+                // GROOVY-5640, GROOVY-9033, GROOVY-10220, GROOVY-10235, GROOVY-10688, et al.
+                Map<GenericsTypeName, GenericsType> gt = new HashMap<>();
+                extractGenericsConnections(gt, resultType, resultType.redirect());
+                ClassNode sc = resultType;
+                do { sc = getNextSuperClass(sc, targetType);
+                } while (sc != null && !sc.equals(targetType));
+                extractGenericsConnections(gt, targetType, sc);
 
-        if (!isPrimitiveType(getUnwrapper(targetType)) && !isObjectType(targetType)
-                && !sourceType.isGenericsPlaceHolder() && missesGenericsTypes(sourceType)) {
-            // unchecked assignment with ternary/elvis, like "List<T> list = listOfT ?: []"
-            // the inferred type is the RHS type "completed" with generics information from LHS
-            return GenericsUtils.parameterizeType(targetType, sourceType.getPlainNodeReference());
+                return applyGenericsContext(gt, resultType.redirect());
+            }
         }
 
-        return sourceType != UNKNOWN_PARAMETER_TYPE ? sourceType : targetType;
+        return resultType;
     }
 
     private static boolean isTypeSource(final Expression expr, final Expression right) {
diff --git a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
index 61deb89ff1..1a8acde043 100644
--- a/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
+++ b/src/test/groovy/transform/stc/TernaryOperatorSTCTest.groovy
@@ -166,6 +166,20 @@ class TernaryOperatorSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-10688
+    void testTypeParameterTypeParameter3() {
+        assertScript '''
+            class A<T,U> {
+            }
+            <T> void test(
+                A<Double, ? extends T> x) {
+                A<Double, ? extends T> y = x
+                A<Double, ? extends T> z = true ? y : x
+            }
+            test(null)
+        '''
+    }
+
     // GROOVY-10271
     void testFunctionalInterfaceTarget1() {
         for (flag in ['true', 'false']) {
@@ -274,6 +288,12 @@ class TernaryOperatorSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    void testCommonInterface3() {
+        assertScript '''import static java.util.concurrent.ConcurrentHashMap.*
+            Set<Integer> integers = false ? new HashSet<>() : newKeySet()
+        '''
+    }
+
     // GROOVY-10130
     void testInstanceofGuard() {
         assertScript '''