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/08/30 19:58:07 UTC

[groovy] branch GROOVY_3_0_X updated: GROOVY-10088: STC: apply receiver generics to setter parameter

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


The following commit(s) were added to refs/heads/GROOVY_3_0_X by this push:
     new 7e715dc291 GROOVY-10088: STC: apply receiver generics to setter parameter
7e715dc291 is described below

commit 7e715dc2911dd0a60733f6161fdf32bed3d8aa0d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 13 14:40:17 2021 -0500

    GROOVY-10088: STC: apply receiver generics to setter parameter
---
 .../transform/stc/StaticTypeCheckingVisitor.java       | 18 +++++++++++++++---
 src/test/groovy/transform/stc/GenericsSTCTest.groovy   |  2 +-
 2 files changed, 16 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 1cb2ad2819..0e4162f0d3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -136,6 +136,7 @@ import java.util.Set;
 import java.util.StringJoiner;
 import java.util.concurrent.atomic.AtomicLong;
 import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
 import java.util.function.Supplier;
 
 import static org.apache.groovy.util.BeanUtils.capitalize;
@@ -981,6 +982,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // but we must check if the binary expression is an assignment
         // because we need to check if a setter uses @DelegatesTo
         VariableExpression ve = varX("%", setterInfo.receiverType);
+        ve.setType(setterInfo.receiverType); // same as origin type
+
+        Function<MethodNode, ClassNode> firstParamType = (method) -> {
+            ClassNode type = method.getParameters()[0].getOriginType();
+            if (!method.isStatic() && !(method instanceof ExtensionMethodNode) && GenericsUtils.hasUnresolvedGenerics(type)) {
+                Map<GenericsTypeName, GenericsType> spec = extractPlaceHolders(null, setterInfo.receiverType, method.getDeclaringClass());
+                type = applyGenericsContext(spec, type);
+            }
+            return type;
+        };
+
         // for compound assignment "x op= y" find type as if it was "x = (x op y)"
         Expression valueExpression = rightExpression;
         if (isCompoundAssignment(expression)) {
@@ -1005,7 +1017,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // this may happen if there's a setter of type boolean/String/Class, and that we are using the property
             // notation AND that the RHS is not a boolean/String/Class
             for (MethodNode setter : setterInfo.setters) {
-                ClassNode type = getWrapper(setter.getParameters()[0].getOriginType());
+                ClassNode type = getWrapper(firstParamType.apply(setter));
                 if (Boolean_TYPE.equals(type) || STRING_TYPE.equals(type) || CLASS_Type.equals(type)) {
                     call = new MethodCallExpression(ve, setterInfo.name, castX(type, valueExpression));
                     call.setImplicitThis(false);
@@ -1022,13 +1034,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (setter == directSetterCandidate) {
                     leftExpression.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, directSetterCandidate);
                     leftExpression.removeNodeMetaData(INFERRED_TYPE); // clear assumption
-                    storeType(leftExpression, getType(valueExpression));
+                    storeType(leftExpression, firstParamType.apply(setter));
                     break;
                 }
             }
             return false;
         } else {
-            ClassNode firstSetterType = setterInfo.setters.get(0).getParameters()[0].getOriginType();
+            ClassNode firstSetterType = firstParamType.apply(setterInfo.setters.get(0));
             addAssignmentError(firstSetterType, getType(valueExpression), expression);
             return true;
         }
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index c2af8d8d31..3d6950c8d7 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -2300,7 +2300,7 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
 
             new D<Number>().p = 'x'
         ''',
-        'Cannot assign value of type java.lang.String to variable of type T'
+        'Cannot assign value of type java.lang.String to variable of type java.lang.Number'
     }
 
     // GROOVY-10225