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/05/13 17:07:50 UTC

[groovy] branch master updated: GROOVY-8409, GROOVY-9902: STC: retain generics for setter receiver

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

emilles 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 7109f64  GROOVY-8409, GROOVY-9902: STC: retain generics for setter receiver
7109f64 is described below

commit 7109f64f17601016e41cb989ec1ee78f764c6a81
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu May 13 12:07:37 2021 -0500

    GROOVY-8409, GROOVY-9902: STC: retain generics for setter receiver
---
 .../groovy/ast/expr/VariableExpression.java        | 26 ++++++------
 .../transform/stc/StaticTypeCheckingSupport.java   |  3 --
 .../transform/stc/StaticTypeCheckingVisitor.java   | 11 ++---
 .../groovy/transform/stc/GenericsSTCTest.groovy    | 49 +++++++++++++++++++++-
 4 files changed, 66 insertions(+), 23 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/expr/VariableExpression.java b/src/main/java/org/codehaus/groovy/ast/expr/VariableExpression.java
index 04e9bdb..7a83054 100644
--- a/src/main/java/org/codehaus/groovy/ast/expr/VariableExpression.java
+++ b/src/main/java/org/codehaus/groovy/ast/expr/VariableExpression.java
@@ -50,16 +50,16 @@ public class VariableExpression extends Expression implements Variable {
         this.accessedVariable = origin;
     }
 
-    public VariableExpression(String variable, ClassNode type) {
-        this.variable = variable;
+    public VariableExpression(final String name, final ClassNode type) {
+        variable = name;
         originType = type;
-        setType(ClassHelper.getWrapper(type));
+        setType(ClassHelper.isPrimitiveType(type) ? ClassHelper.getWrapper(type) : type);
     }
-    
+
     public VariableExpression(String variable) {
         this(variable, ClassHelper.DYNAMIC_TYPE);
     }
-    
+
     public VariableExpression(Variable variable) {
         this(variable.getName(), variable.getOriginType());
         setAccessedVariable(variable);
@@ -80,7 +80,7 @@ public class VariableExpression extends Expression implements Variable {
     public String getText() {
         return variable;
     }
-    
+
     @Override
     public String getName() {
         return variable;
@@ -100,13 +100,13 @@ public class VariableExpression extends Expression implements Variable {
     public boolean hasInitialExpression() {
         return false;
     }
-    
+
     @Override
     public boolean isInStaticContext() {
         if (accessedVariable!=null && accessedVariable!=this) return accessedVariable.isInStaticContext();
         return inStaticContext;
     }
-    
+
     public void setInStaticContext(boolean inStaticContext) {
         this.inStaticContext = inStaticContext;
     }
@@ -123,7 +123,7 @@ public class VariableExpression extends Expression implements Variable {
         super.setType(cn);
         isDynamicTyped |= ClassHelper.DYNAMIC_TYPE==cn;
     }
-    
+
     @Override
     public boolean isDynamicTyped() {
         if (accessedVariable!=null && accessedVariable!=this) return accessedVariable.isDynamicTyped();
@@ -156,7 +156,7 @@ public class VariableExpression extends Expression implements Variable {
      */
     @Override
     public void setClosureSharedVariable(boolean inClosure) {
-        closureShare = inClosure;        
+        closureShare = inClosure;
     }
 
     @Override
@@ -170,9 +170,9 @@ public class VariableExpression extends Expression implements Variable {
      * @param useRef
      */
     public void setUseReferenceDirectly(boolean useRef) {
-        this.useRef = useRef;        
+        this.useRef = useRef;
     }
-    
+
     /**
      * For internal use only. This flag is used by compiler internals and should probably
      * be converted to a node metadata in future.
@@ -180,7 +180,7 @@ public class VariableExpression extends Expression implements Variable {
     public boolean isUseReferenceDirectly() {
         return useRef;
     }
-    
+
     @Override
     public ClassNode getType() {
         if (accessedVariable!=null && accessedVariable!=this) return accessedVariable.getType();
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 b06fda3..b7bafd5 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -1031,9 +1031,6 @@ public abstract class StaticTypeCheckingSupport {
         if (!asBoolean(methods)) {
             return Collections.emptyList();
         }
-        if (isUsingUncheckedGenerics(receiver)) {
-            return chooseBestMethod(makeRawType(receiver), methods, argumentTypes);
-        }
 
         int bestDist = Integer.MAX_VALUE;
         List<MethodNode> bestChoices = new LinkedList<>();
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 5a0fb9a..588532e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -805,7 +805,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
                     // the inferred type of the binary expression is the type of the RHS
                     // "completed" with generics type information available from the LHS
-                    resultType = GenericsUtils.parameterizeType(lType, resultType.getPlainNodeReference());
+                    if (!resultType.isGenericsPlaceHolder()) // plain reference drops placeholder
+                        resultType = GenericsUtils.parameterizeType(lType, resultType.getPlainNodeReference());
                 } else if (lType.equals(OBJECT_TYPE) && GenericsUtils.hasUnresolvedGenerics(resultType)) { // def list = []
                     Map<GenericsTypeName, GenericsType> placeholders = extractGenericsParameterMapOfThis(typeCheckingContext);
                     resultType = fullyResolveType(resultType, Optional.ofNullable(placeholders).orElseGet(Collections::emptyMap));
@@ -4888,11 +4889,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             if (!result.isEmpty()) return result;
         }
 
-        if (GSTRING_TYPE.equals(receiver)) return findMethod(STRING_TYPE, name, args);
-
+        if (GSTRING_TYPE.equals(receiver)) {
+            return findMethod(STRING_TYPE, name, args);
+        }
         if (isBeingCompiled(receiver)) {
-            chosen = findMethod(GROOVY_OBJECT_TYPE, name, args);
-            if (!chosen.isEmpty()) return chosen;
+            return findMethod(GROOVY_OBJECT_TYPE, name, args);
         }
 
         return EMPTY_METHODNODE_LIST;
diff --git a/src/test/groovy/transform/stc/GenericsSTCTest.groovy b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
index cd2a4ba..d65b991 100644
--- a/src/test/groovy/transform/stc/GenericsSTCTest.groovy
+++ b/src/test/groovy/transform/stc/GenericsSTCTest.groovy
@@ -1521,6 +1521,51 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
+    // GROOVY-8409, GROOVY-9902
+    void testShouldUseMethodGenericType11() {
+        config.with {
+            targetDirectory = File.createTempDir()
+            jointCompilationOptions = [stubDir: File.createTempDir()]
+        }
+        File parentDir = File.createTempDir()
+        try {
+            def a = new File(parentDir, 'Main.groovy')
+            a.write '''
+                def obj = new Pojo()
+                Foo raw = obj.getFoo('')
+                raw.bar = raw.baz // Cannot assign value of type Object to variable of type R
+            '''
+            def b = new File(parentDir, 'Pojo.java')
+            b.write '''
+                public class Pojo {
+                    public <R extends I> Foo<R> getFoo(String key) {
+                        return new Foo<>();
+                    }
+                }
+            '''
+            def c = new File(parentDir, 'Types.groovy')
+            c.write '''
+                interface I {
+                }
+                class Foo<T extends I> {
+                    T bar
+                    T baz
+                }
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b, c)
+            cu.compile()
+
+            loader.loadClass('Main').main()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+            config.jointCompilationOptions.stubDir.deleteDir()
+        }
+    }
+
     // GROOVY-5516
     void testAddAllWithCollectionShouldBeAllowed() {
         assertScript '''import org.codehaus.groovy.transform.stc.ExtensionMethodNode
@@ -2039,8 +2084,8 @@ class GenericsSTCTest extends StaticTypeCheckingTestCase {
             test(new Holder<Object>())
         ''',
         'Cannot call TypedProperty#eq(java.lang.String) with arguments [groovy.lang.GString]',
-        'Cannot call TypedProperty#eq(java.lang.String) with arguments [int]',
-        'Cannot call TypedProperty#eq(java.lang.Number) with arguments [java.lang.String]'
+        'Cannot find matching method TypedProperty#eq(int)', // chooseBestMethod removes "eq"
+        'Cannot find matching method TypedProperty#eq(java.lang.String)'
     }
 
     // GROOVY-5748