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/07/23 22:40:28 UTC

[groovy] branch master updated (7bca43a -> 39a3c74)

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

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


    from 7bca43a  GROOVY-10179: STC: for-in collection type: consider instanceof flow-type
     new 6d6d99c  trivial refactor
     new 39a3c74  GROOVY-10180: STC: method lookup: try instanceof type(s) before declared

The 2 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:
 .../transform/stc/StaticTypeCheckingVisitor.java   | 54 +++++++--------
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 79 ++++++++++++----------
 .../console/ui/AstNodeToScriptAdapter.groovy       | 62 +++++++----------
 3 files changed, 97 insertions(+), 98 deletions(-)

[groovy] 02/02: GROOVY-10180: STC: method lookup: try instanceof type(s) before declared

Posted by em...@apache.org.
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

commit 39a3c7479d7d5a2af297e2be5a28bb2bc47e0da8
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 23 17:40:13 2021 -0500

    GROOVY-10180: STC: method lookup: try instanceof type(s) before declared
    
    - better match for "each" using Map vs. Object:
        void test(obj) { if (obj instanceof Map) obj.each { e -> } }
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 54 +++++++--------
 .../stc/ClosureParamTypeInferenceSTCTest.groovy    | 79 ++++++++++++----------
 2 files changed, 71 insertions(+), 62 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 d946e86..f0fbd9e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3812,40 +3812,40 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
         ClassNode receiver = getType(objectExpression);
         List<Receiver<String>> owners = new ArrayList<>();
-        if (isClassClassNodeWrappingConcreteType(receiver)) {
-            ClassNode staticType = receiver.getGenericsTypes()[0].getType();
-            owners.add(Receiver.make(staticType)); // Type from Class<Type>
-            addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
-            owners.add(Receiver.make(receiver)); // Class<Type>
-        } else {
-            owners.add(Receiver.make(receiver));
-            if (receiver.isInterface()) {
-                owners.add(Receiver.make(OBJECT_TYPE));
-            }
-            addSelfTypes(receiver, owners);
-            addTraitType(receiver, owners);
-        }
-        if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
-            List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
-            if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
-                for (ClassNode node : potentialReceiverType) {
-                    owners.add(Receiver.make(node));
-                }
-            }
-        }
-        if (typeCheckingContext.lastImplicitItType != null
-                && objectExpression instanceof VariableExpression
-                && ((VariableExpression) objectExpression).getName().equals("it")) {
-            owners.add(Receiver.make(typeCheckingContext.lastImplicitItType));
-        }
         if (typeCheckingContext.delegationMetadata != null
                 && objectExpression instanceof VariableExpression
                 && ((VariableExpression) objectExpression).getName().equals("owner")
                 && /*isNested:*/typeCheckingContext.delegationMetadata.getParent() != null) {
-            owners.clear();
             List<Receiver<String>> enclosingClass = Collections.singletonList(
                     Receiver.make(typeCheckingContext.getEnclosingClassNode()));
             addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
+        } else {
+            if (!typeCheckingContext.temporaryIfBranchTypeInformation.isEmpty()) {
+                List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
+                if (potentialReceiverType != null && !potentialReceiverType.isEmpty()) {
+                    for (ClassNode node : potentialReceiverType) {
+                        owners.add(Receiver.make(node));
+                    }
+                }
+            }
+            if (typeCheckingContext.lastImplicitItType != null
+                    && objectExpression instanceof VariableExpression
+                    && ((VariableExpression) objectExpression).getName().equals("it")) {
+                owners.add(Receiver.make(typeCheckingContext.lastImplicitItType));
+            }
+            if (isClassClassNodeWrappingConcreteType(receiver)) {
+                ClassNode staticType = receiver.getGenericsTypes()[0].getType();
+                owners.add(Receiver.make(staticType)); // Type from Class<Type>
+                addTraitType(staticType, owners); // T in Class<T$Trait$Helper>
+                owners.add(Receiver.make(receiver)); // Class<Type>
+            } else {
+                owners.add(Receiver.make(receiver));
+                addSelfTypes(receiver, owners);
+                addTraitType(receiver, owners);
+                if (receiver.isInterface()) {
+                    owners.add(Receiver.make(OBJECT_TYPE));
+                }
+            }
         }
         return owners;
     }
diff --git a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
index efb8dba..5cb1930 100644
--- a/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
+++ b/src/test/groovy/transform/stc/ClosureParamTypeInferenceSTCTest.groovy
@@ -22,22 +22,41 @@ package groovy.transform.stc
  * Unit tests for static type checking : closure parameter type inference.
  */
 class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
-    void testInferenceForDGM_CollectUsingExplicitIt() {
+
+    void testInferenceForDGM_collectUsingExplicitIt() {
         assertScript '''
             ['a','b'].collect { it -> it.toUpperCase() }
         '''
-    }
-
-    void testInferenceForDGM_CollectUsingExplicitItAndIncorrectType() {
         shouldFailWithMessages '''
             ['a','b'].collect { Date it -> it.toUpperCase() }
         ''', 'Expected parameter of type java.lang.String but got java.util.Date'
     }
 
-    void testInferenceForDGM_CollectUsingImplicitIt() {
+    void testInferenceForDGM_collectUsingImplicitIt() {
         assertScript '''
             ['a','b'].collect { it.toUpperCase() }
         '''
+        assertScript '''
+            def items = []
+            ['a','b','c'].collect(items) { it.toUpperCase() }
+        '''
+        assertScript '''
+            String[] array = ['foo', 'bar', 'baz']
+            assert array.collect { it.startsWith('ba') } == [false, true, true]
+        '''
+        assertScript '''
+            List<Boolean> answer = [true]
+            String[] array = ['foo', 'bar', 'baz']
+            array.collect(answer){it.startsWith('ba')}
+            assert answer == [true, false, true, true]
+        '''
+        assertScript '''
+            Iterator<String> iter = ['foo', 'bar', 'baz'].iterator()
+            assert iter.collect { it.startsWith('ba') } == [false, true, true]
+        '''
+        assertScript '''
+            assert [1234, 3.14].collect { it.intValue() } == [1234,3]
+        '''
     }
 
     void testInferenceForDGM_eachUsingExplicitIt() {
@@ -52,12 +71,6 @@ class ClosureParamTypeInferenceSTCTest extends StaticTypeCheckingTestCase {
         '''
     }
 
-    void testInferenceForDGM_CollectUsingImplicitItAndLUB() {
-        assertScript '''
-            assert [1234, 3.14].collect { it.intValue() } == [1234,3]
-        '''
-    }
-
     void testInferenceForDGM_countUsingFirstSignature() {
         assertScript '''
             def src = [a: 1, b:2, c:3]
@@ -103,13 +116,6 @@ assert result == ['b', 'r', 'e', 'a', 'd', 'b', 'u', 't', 't', 'e', 'r']
 '''
     }
 
-    void testInferenceForDGM_Collect2() {
-        assertScript '''
-def items = []
-['a','b','c'].collect(items) { it.toUpperCase() }
-'''
-    }
-
     void testInferenceForDGM_CollectMap() {
         assertScript '''
         assert [a: 'foo',b:'bar'].collect { k,v -> k+v } == ['afoo','bbar']
@@ -221,23 +227,6 @@ def items = []
 '''
     }
 
-    void testDGM_collectOnArray() {
-        assertScript '''
-            String[] arr = ['foo', 'bar', 'baz']
-            assert arr.collect { it.startsWith('ba') } == [false, true, true]
-            List<Boolean> answer = [true]
-            arr.collect(answer) { it.startsWith('ba') }
-            assert answer == [true, false, true, true]
-        '''
-    }
-
-    void testDGM_collectOnIterator() {
-        assertScript '''
-            Iterator<String> itr = ['foo', 'bar', 'baz'].iterator()
-            assert itr.collect { it.startsWith('ba') } == [false, true, true]
-        '''
-    }
-
     void testInferenceOnNonExtensionMethod() {
         assertScript '''import groovy.transform.stc.ClosureParams
             import groovy.transform.stc.FirstParam
@@ -1497,4 +1486,24 @@ method()
             assert iterable.collect { it.prop } == ['x', 'y', 'z']
         '''
     }
+
+    void testGroovy10180() {
+        assertScript '''
+            void test(args) {
+                if (args instanceof Map) {
+                    args.each { e ->
+                        def k = e.key, v = e.value
+                    }
+                }
+            }
+        '''
+        assertScript '''
+            void test(args) {
+                if (args instanceof Map) {
+                    args.each { k, v ->
+                    }
+                }
+            }
+        '''
+    }
 }

[groovy] 01/02: trivial refactor

Posted by em...@apache.org.
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

commit 6d6d99cdf717864f1ee7426e971d324412105bdc
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Jul 23 17:40:05 2021 -0500

    trivial refactor
---
 .../console/ui/AstNodeToScriptAdapter.groovy       | 62 +++++++++-------------
 1 file changed, 26 insertions(+), 36 deletions(-)

diff --git a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
index fa78b38..c51c5b3 100644
--- a/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
+++ b/subprojects/groovy-console/src/main/groovy/groovy/console/ui/AstNodeToScriptAdapter.groovy
@@ -18,9 +18,9 @@
  */
 package groovy.console.ui
 
+import groovy.transform.AutoFinal
 import groovy.transform.CompileStatic
 import org.apache.groovy.io.StringBuilderWriter
-import org.codehaus.groovy.ast.ASTNode
 import org.codehaus.groovy.ast.AnnotationNode
 import org.codehaus.groovy.ast.ClassHelper
 import org.codehaus.groovy.ast.ClassNode
@@ -108,7 +108,7 @@ import java.security.CodeSource
  * back to the groovy source. It is used by GroovyConsole's AST Browser, but can also be invoked from
  * the command line.
  */
-@CompileStatic
+@AutoFinal @CompileStatic
 class AstNodeToScriptAdapter {
 
     /**
@@ -154,22 +154,16 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP
      *    optional compiler configuration
      * @returns the source code from the AST state
      */
-
     String compileToScript(String script, int compilePhase, ClassLoader classLoader = null, boolean showScriptFreeForm = true, boolean showScriptClass = true, CompilerConfiguration config = null) {
-
         def writer = new StringBuilderWriter()
-
-        classLoader = classLoader ?: new GroovyClassLoader(getClass().classLoader)
-
         def scriptName = 'script' + System.currentTimeMillis() + '.groovy'
         GroovyCodeSource codeSource = new GroovyCodeSource(script, scriptName, '/groovy/script')
-        CompilationUnit cu = new CompilationUnit((CompilerConfiguration) (config ?: CompilerConfiguration.DEFAULT), (CodeSource) codeSource.codeSource, (GroovyClassLoader) classLoader)
+        CompilationUnit cu = new CompilationUnit((CompilerConfiguration) (config ?: CompilerConfiguration.DEFAULT), (CodeSource) codeSource.codeSource, (GroovyClassLoader) classLoader ?: new GroovyClassLoader(this.class.classLoader))
         cu.addPhaseOperation(new AstNodeToScriptVisitor(writer, showScriptFreeForm, showScriptClass), compilePhase)
         cu.addSource(codeSource.getName(), script)
         try {
             cu.compile(compilePhase)
         } catch (CompilationFailedException cfe) {
-
             writer.println 'Unable to produce AST for this phase due to earlier compilation error:'
             cfe.message.eachLine {
                 writer.println it
@@ -187,11 +181,11 @@ and [compilephase] is a valid Integer based org.codehaus.groovy.control.CompileP
 /**
  * An adapter from ASTNode tree to source code.
  */
-@CompileStatic
+@AutoFinal @CompileStatic
 class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperation, GroovyClassVisitor, GroovyCodeVisitor {
 
     private final Writer _out
-    Stack<String> classNameStack = new Stack<String>()
+    Stack<String> classNameStack = new Stack<>()
     String _indent = ''
     boolean readyToIndent = true
     boolean showScriptFreeForm
@@ -685,12 +679,11 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
 
     @Override
     void visitMethodCallExpression(MethodCallExpression expression) {
-
-        Expression objectExp = expression.getObjectExpression()
-        if (objectExp instanceof VariableExpression) {
-            visitVariableExpression(objectExp, false)
+        Expression objectExpr = expression.objectExpression
+        if (objectExpr instanceof VariableExpression) {
+            visitVariableExpression(objectExpr, false)
         } else {
-            objectExp.visit(this)
+            objectExpr.visit(this)
         }
         if (expression.spreadSafe) {
             print '*'
@@ -699,25 +692,23 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
             print '?'
         }
         print '.'
-        Expression method = expression.getMethod()
+        Expression method = expression.method
         if (method instanceof ConstantExpression) {
             visitConstantExpression(method, true)
         } else {
             method.visit(this)
         }
-        expression.getArguments().visit(this)
+        expression.arguments.visit(this)
     }
 
     @Override
     void visitStaticMethodCallExpression(StaticMethodCallExpression expression) {
+        boolean parens = expression?.arguments instanceof MethodCallExpression
+                || expression?.arguments instanceof VariableExpression
         print expression?.ownerType?.name + '.' + expression?.method
-        if (expression?.arguments instanceof VariableExpression || expression?.arguments instanceof MethodCallExpression) {
-            print '('
-            expression?.arguments?.visit this
-            print ')'
-        } else {
-            expression?.arguments?.visit this
-        }
+        if (parens) print '('
+        expression?.arguments?.visit(this)
+        if (parens) print ')'
     }
 
     @Override
@@ -762,7 +753,6 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         print ')'
     }
 
-
     @Override
     void visitClosureExpression(ClosureExpression expression) {
         print '{ '
@@ -959,7 +949,6 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         printLineBreak()
     }
 
-
     @Override
     void visitMapExpression(MapExpression expression) {
         print '['
@@ -974,7 +963,7 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
     @Override
     void visitMapEntryExpression(MapEntryExpression expression) {
         if (expression?.keyExpression instanceof SpreadMapExpression) {
-            print '*'            // is this correct? 
+            print '*'            // is this correct?
         } else {
             expression?.keyExpression?.visit this
         }
@@ -1143,14 +1132,16 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         print ']'
     }
 
-    private void visitExpressionsAndCommaSeparate(List<? super Expression> expressions) {
-        boolean first = true
-        expressions?.each {
-            if (!first) {
-                print ', '
+    private void visitExpressionsAndCommaSeparate(List<? extends Expression> expressions) {
+        if (expressions) {
+            boolean first = true
+            for (e in expressions) {
+                if (!first) {
+                    print ', '
+                }
+                first = false
+                e.visit(this)
             }
-            first = false
-            ((ASTNode) it).visit this
         }
     }
 
@@ -1178,5 +1169,4 @@ class AstNodeToScriptVisitor implements CompilationUnit.IPrimaryClassNodeOperati
         }
         return true
     }
-
 }