You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2019/11/11 05:59:14 UTC

[groovy] branch GROOVY_3_0_X updated (abef390 -> 741d336)

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

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


    from abef390  Remove outdated javadoc hotfix (#1074)
     new 02b16fb  JUnit 4
     new a11cc18  minor edits for readability
     new 0bd8238  refactor checks for this and super object expressions
     new ed61e9c  trivial refactor
     new fa9fb90  fix generics
     new 131d090  minor edits
     new db4bb80  use redirect for reference comparison
     new 9d6e21f  trivial refactor
     new 741d336  GROOVY-7722: prevent stack overflow resolving generics placeholders (closes #1077)

The 9 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:
 .../java/org/codehaus/groovy/ast/ClassHelper.java  |  88 +++++++-------
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  23 ++--
 .../groovy/classgen/asm/BytecodeHelper.java        |   4 +-
 .../groovy/tools/javac/JavaStubGenerator.java      |   5 +-
 .../transform/stc/StaticTypeCheckingVisitor.java   | 131 ++++++++++-----------
 src/test/groovy/bugs/Groovy7722.groovy             |  83 +++++++++++++
 src/test/groovy/grape/GrabResolverTest.groovy      |  93 ++++++++-------
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   |  33 +++++-
 8 files changed, 292 insertions(+), 168 deletions(-)
 create mode 100644 src/test/groovy/bugs/Groovy7722.groovy


[groovy] 03/09: refactor checks for this and super object expressions

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

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

commit 0bd82385322361c446a3178e05de3d7f26a1c361
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 9 16:26:36 2019 -0600

    refactor checks for this and super object expressions
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 63 +++++++++++-----------
 1 file changed, 30 insertions(+), 33 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 ae8bee4..4b81c30 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -567,18 +567,15 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private void checkSuperCallFromClosure(Expression call, MethodNode directCallTarget) {
         if (call instanceof MethodCallExpression && typeCheckingContext.getEnclosingClosure() != null) {
             Expression objectExpression = ((MethodCallExpression) call).getObjectExpression();
-            if (objectExpression instanceof VariableExpression) {
-                VariableExpression var = (VariableExpression) objectExpression;
-                if (var.isSuperExpression()) {
-                    ClassNode current = typeCheckingContext.getEnclosingClassNode();
-                    LinkedList<MethodNode> list = current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED);
-                    if (list == null) {
-                        list = new LinkedList<MethodNode>();
-                        current.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, list);
-                    }
-                    list.add(directCallTarget);
-                    call.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, current);
+            if (isSuperExpression(objectExpression)) {
+                ClassNode current = typeCheckingContext.getEnclosingClassNode();
+                LinkedList<MethodNode> list = current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED);
+                if (list == null) {
+                    list = new LinkedList<MethodNode>();
+                    current.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, list);
                 }
+                list.add(directCallTarget);
+                call.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, current);
             }
         }
     }
@@ -2260,15 +2257,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         ClassNode[] args = getArgumentTypes(argumentList);
         if (args.length > 0 &&
                 typeCheckingContext.getEnclosingClosure() != null &&
-                argumentList.getExpression(0) instanceof VariableExpression &&
-                ((VariableExpression) argumentList.getExpression(0)).isThisExpression() &&
-                call.getType() instanceof InnerClassNode &&
-                call.getType().getOuterClass().equals(args[0]) &&
+                isThisExpression(argumentList.getExpression(0)) &&
+                args[0].equals(call.getType().getOuterClass()) &&
                 !call.getType().isStaticClass()) {
             args[0] = CLOSURE_TYPE;
         }
 
-
         MethodNode node;
         if (looksLikeNamedArgConstructor(receiver, args)
                 && findMethod(receiver, "<init>", DefaultGroovyMethods.init(args)).size() == 1
@@ -3350,7 +3344,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             boolean callArgsVisited = false;
             if (isCallOnClosure) {
                 // this is a closure.call() call
-                if (objectExpression == VariableExpression.THIS_EXPRESSION) {
+                if (isThisExpression(objectExpression)) {
                     // isClosureCall() check verified earlier that a field exists
                     FieldNode field = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name);
                     GenericsType[] genericsTypes = field.getType().getGenericsTypes();
@@ -3394,6 +3388,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         storeType(call, data);
                     }
                 }
+
                 int nbOfArgs;
                 if (callArguments instanceof ArgumentListExpression) {
                     ArgumentListExpression list = (ArgumentListExpression) callArguments;
@@ -3426,8 +3421,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     // if we are not in a static context but the current receiver is a static class, we must
                     // ensure that all methods are either static or declared by the current receiver or a superclass
                     if (!mn.isEmpty()
-                            && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0)
-                            && (call.isImplicitThis() || (objectExpression instanceof VariableExpression && ((VariableExpression) objectExpression).isThisExpression()))) {
+                            && (call.isImplicitThis() || isThisExpression(objectExpression))
+                            && (typeCheckingContext.isInStaticContext || (receiverType.getModifiers() & Opcodes.ACC_STATIC) != 0)) {
                         // we create separate method lists just to be able to print out
                         // a nice error message to the user
                         // a method is accessible if it is static, or if we are not in a static context and it is
@@ -3490,15 +3485,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         }
 
                         ClassNode returnType = getType(directMethodCallCandidate);
-
                         if (isUsingGenericsOrIsArrayUsingGenerics(returnType)) {
                             visitMethodCallArguments(chosenReceiver.getType(), argumentList, true, directMethodCallCandidate);
-                            ClassNode irtg = inferReturnTypeGenerics(
-                                    chosenReceiver.getType(),
-                                    directMethodCallCandidate,
-                                    callArguments,
-                                    call.getGenericsTypes());
-                            returnType = irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType;
+                            ClassNode irtg = inferReturnTypeGenerics(chosenReceiver.getType(), directMethodCallCandidate, callArguments, call.getGenericsTypes());
+                            returnType = (irtg != null && implementsInterfaceOrIsSubclassOf(irtg, returnType) ? irtg : returnType);
                             callArgsVisited = true;
                         }
                         if (directMethodCallCandidate == GET_DELEGATE && typeCheckingContext.getEnclosingClosure() != null) {
@@ -3802,8 +3792,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected boolean isClosureCall(final String name, final Expression objectExpression, final Expression arguments) {
-        if (objectExpression instanceof ClosureExpression && ("call".equals(name) || "doCall".equals(name))) return true;
-        if (objectExpression == VariableExpression.THIS_EXPRESSION) {
+        if (objectExpression instanceof ClosureExpression && "call".equals(name) || "doCall".equals(name)) return true;
+        if (isThisExpression(objectExpression)) {
             FieldNode fieldNode = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name);
             if (fieldNode != null) {
                 ClassNode type = fieldNode.getType();
@@ -4833,15 +4823,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return node;
         }
         if (exp instanceof VariableExpression) {
-            final VariableExpression vexp = (VariableExpression) exp;
+            VariableExpression vexp = (VariableExpression) exp;
             ClassNode selfTrait = isTraitSelf(vexp);
             if (selfTrait != null) return makeSelf(selfTrait);
-            if (vexp == VariableExpression.THIS_EXPRESSION) return makeThis();
-            if (vexp == VariableExpression.SUPER_EXPRESSION) return makeSuper();
-            final Variable variable = vexp.getAccessedVariable();
+            if (vexp.isThisExpression()) return makeThis();
+            if (vexp.isSuperExpression()) return makeSuper();
+            Variable variable = vexp.getAccessedVariable();
             if (variable instanceof FieldNode) {
                 FieldNode fieldNode = (FieldNode) variable;
-
                 checkOrMarkPrivateAccess(vexp, fieldNode, isLHSOfEnclosingAssignment(vexp));
                 return getType(fieldNode);
             }
@@ -5075,6 +5064,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return expression instanceof ConstantExpression && ((ConstantExpression) expression).isNullExpression();
     }
 
+    protected static boolean isThisExpression(final Expression expression) {
+        return expression instanceof VariableExpression && ((VariableExpression) expression).isThisExpression();
+    }
+
+    protected static boolean isSuperExpression(final Expression expression) {
+        return expression instanceof VariableExpression && ((VariableExpression) expression).isSuperExpression();
+    }
+
     protected ClassNode inferMapExpressionType(final MapExpression map) {
         ClassNode mapType = LINKEDHASHMAP_CLASSNODE.getPlainNodeReference();
         List<MapEntryExpression> entryExpressions = map.getMapEntryExpressions();


[groovy] 08/09: trivial refactor

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

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

commit 9d6e21f6cd0318f6f494ad4cb4238caccaa0e9d9
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 21:22:43 2019 -0600

    trivial refactor
---
 .../groovy/transform/stc/StaticTypeCheckingVisitor.java | 17 +++++++++--------
 1 file changed, 9 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 e0f3da3..b032191 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -4171,7 +4171,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitTryCatchFinally(final TryCatchStatement statement) {
-        final List<CatchStatement> catchStatements = statement.getCatchStatements();
+        List<CatchStatement> catchStatements = statement.getCatchStatements();
         for (CatchStatement catchStatement : catchStatements) {
             ClassNode exceptionType = catchStatement.getExceptionType();
             typeCheckingContext.controlStructureVariables.put(catchStatement.getVariable(), exceptionType);
@@ -4183,16 +4183,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 typeCheckingContext.controlStructureVariables.remove(catchStatement.getVariable());
             }
         }
-
     }
 
     protected void storeType(final Expression exp, ClassNode cn) {
-        if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable() && isPrimitiveType(cn)) {
-            cn = getWrapper(cn);
-        } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe() && isPrimitiveType(cn)) {
-            cn = getWrapper(cn);
-        } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe() && isPrimitiveType(cn)) {
-            cn = getWrapper(cn);
+        if (cn != null && isPrimitiveType(cn)) {
+            if (exp instanceof VariableExpression && ((VariableExpression) exp).isClosureSharedVariable()) {
+                cn = getWrapper(cn);
+            } else if (exp instanceof MethodCallExpression && ((MethodCallExpression) exp).isSafe()) {
+                cn = getWrapper(cn);
+            } else if (exp instanceof PropertyExpression && ((PropertyExpression) exp).isSafe()) {
+                cn = getWrapper(cn);
+            }
         }
         if (cn == UNKNOWN_PARAMETER_TYPE) {
             // this can happen for example when "null" is used in an assignment or a method parameter.


[groovy] 09/09: GROOVY-7722: prevent stack overflow resolving generics placeholders (closes #1077)

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

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

commit 741d336cebb8a8cedeb511cc796acbd25cd4d43b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 9 10:16:10 2019 -0600

    GROOVY-7722: prevent stack overflow resolving generics placeholders (closes #1077)
    
    GROOVY-7864
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  2 +
 src/test/groovy/bugs/Groovy7722.groovy             | 83 ++++++++++++++++++++++
 2 files changed, 85 insertions(+)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index 71f6ec9..8675c25 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -52,6 +52,7 @@ import java.util.function.Predicate;
 
 import static groovy.lang.Tuple.tuple;
 import static org.apache.groovy.util.SystemUtil.getSystemPropertySafe;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.plus;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.getCorrectedClassNode;
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.implementsInterfaceOrIsSubclassOf;
 
@@ -354,6 +355,7 @@ public class GenericsUtils {
         }
         if (type.isGenericsPlaceHolder() && !exclusions.contains(type.getUnresolvedName())) {
             String name = type.getGenericsTypes()[0].getName();
+            exclusions = plus(exclusions, name); // GROOVY-7722
             type = genericsSpec.get(name);
             if (type != null && type.isGenericsPlaceHolder()) {
                 if (type.getGenericsTypes() == null) {
diff --git a/src/test/groovy/bugs/Groovy7722.groovy b/src/test/groovy/bugs/Groovy7722.groovy
new file mode 100644
index 0000000..1fd017c
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy7722.groovy
@@ -0,0 +1,83 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy7722 {
+
+    @Test
+    void testGenericsStackOverflow1() {
+        assertScript '''
+            interface Action1<T> {
+                void call(T t)
+            }
+            abstract class Subscriber<T> {
+            }
+            interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
+            }
+
+            new OnSubscribe<List>() {
+                @Override
+                void call(Subscriber<? super List> o) {
+                    println 'called'
+                }
+            }.call(null)
+        '''
+    }
+
+    @Test // GROOVY-7864
+    void testGenericsStackOverflow2() {
+        assertScript '''
+            // from RxJava 1.x
+            class Observable<T> {
+                interface OnSubscribe<T> extends Action1<Subscriber<? super T>> {
+                }
+                static <T> Observable<T> create(OnSubscribe<T> f) {
+                    return new Observable<T>(/*RxJavaHooks.onCreate(f)*/);
+                }
+            }
+            abstract class Subscriber<T> implements Observer<T>, Subscription {
+            }
+            interface Action1<T> /*extends Action*/ {
+                void call(T t)
+            }
+            interface Observer<T> {
+                void onNext(T t)
+                void onCompleted()
+                void onError(Throwable t)
+            }
+            public interface Subscription {
+                void unsubscribe()
+                boolean isUnsubscribed()
+            }
+
+            Observable.create(new Observable.OnSubscribe() {
+                @Override
+                void call(Subscriber subscriber) {
+                    //...
+                }
+            })
+        '''
+    }
+}


[groovy] 04/09: trivial refactor

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

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

commit ed61e9cd5f21a85a32c49fb3d430e497dba0871b
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 04:11:50 2019 -0600

    trivial refactor
---
 .../groovy/transform/stc/StaticTypeCheckingVisitor.java  | 16 +++++++---------
 1 file changed, 7 insertions(+), 9 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 4b81c30..a2dca5f 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3792,19 +3792,17 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected boolean isClosureCall(final String name, final Expression objectExpression, final Expression arguments) {
-        if (objectExpression instanceof ClosureExpression && "call".equals(name) || "doCall".equals(name)) return true;
+        if (objectExpression instanceof ClosureExpression && ("call".equals(name) || "doCall".equals(name))) return true;
         if (isThisExpression(objectExpression)) {
             FieldNode fieldNode = typeCheckingContext.getEnclosingClassNode().getDeclaredField(name);
-            if (fieldNode != null) {
-                ClassNode type = fieldNode.getType();
-                if (CLOSURE_TYPE.equals(type) && !typeCheckingContext.getEnclosingClassNode().hasPossibleMethod(name, arguments)) {
-                    return true;
-                }
+            if (fieldNode != null && CLOSURE_TYPE.equals(fieldNode.getType())
+                    && !typeCheckingContext.getEnclosingClassNode().hasPossibleMethod(name, arguments)) {
+                return true;
             }
-        } else {
-            if (!"call".equals(name) && !"doCall".equals(name)) return false;
+        } else if (!"call".equals(name) && !"doCall".equals(name)) {
+            return false;
         }
-        return (getType(objectExpression).equals(CLOSURE_TYPE));
+        return getType(objectExpression).equals(CLOSURE_TYPE);
     }
 
     protected void typeCheckClosureCall(final Expression callArguments, final ClassNode[] args, final Parameter[] parameters) {


[groovy] 01/09: JUnit 4

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

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

commit 02b16fbca96e8b3ed6c46474ff957408767d4a6d
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 9 10:13:57 2019 -0600

    JUnit 4
---
 src/test/groovy/grape/GrabResolverTest.groovy | 93 +++++++++++++++------------
 1 file changed, 53 insertions(+), 40 deletions(-)

diff --git a/src/test/groovy/grape/GrabResolverTest.groovy b/src/test/groovy/grape/GrabResolverTest.groovy
index 369f10b..f7e4429 100644
--- a/src/test/groovy/grape/GrabResolverTest.groovy
+++ b/src/test/groovy/grape/GrabResolverTest.groovy
@@ -18,82 +18,95 @@
  */
 package groovy.grape
 
-import groovy.test.GroovyTestCase
+import groovy.transform.CompileStatic
 import org.codehaus.groovy.control.CompilationFailedException
+import org.junit.AfterClass
+import org.junit.Before
+import org.junit.BeforeClass
+import org.junit.Ignore
+import org.junit.Test
 
-class GrabResolverTest extends GroovyTestCase {
-    def originalGrapeRoot
-    def grapeRoot
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
 
+@CompileStatic
+final class GrabResolverTest {
+
+    private static String originalGrapeRoot
+
+    @BeforeClass
+    static void setUpTestSuite() {
+        originalGrapeRoot = System.getProperty('grape.root')
+    }
+
+    @Before
     void setUp() {
-        Grape.@instance = null // isolate our test from other tests
+        Grape.@instance = null // isolate each test
 
-        // create a new grape root directory so as to insure a clean slate for this test
-        originalGrapeRoot = System.getProperty("grape.root")
-        grapeRoot = new File(System.getProperty("java.io.tmpdir"), "GrabResolverTest${System.currentTimeMillis()}")
+        // create a new grape root directory so as to insure a clean slate for each test
+        def grapeRoot = new File(System.getProperty('java.io.tmpdir'), "GrabResolverTest${System.currentTimeMillis()}")
+        System.setProperty('grape.root', grapeRoot.path)
         assert grapeRoot.mkdir()
         grapeRoot.deleteOnExit()
-        System.setProperty("grape.root", grapeRoot.path)
     }
 
-    void tearDown() {
+    @AfterClass
+    static void tearDownTestSuite() {
         if (originalGrapeRoot == null) {
-            // SDN bug: 4463345
-            System.getProperties().remove("grape.root")
+            System.clearProperty('grape.root')
         } else {
-            System.setProperty("grape.root", originalGrapeRoot)
+            System.setProperty('grape.root', originalGrapeRoot)
         }
 
-        Grape.@instance = null // isolate our test from other tests
+        Grape.@instance = null // isolate these tests from other tests
     }
 
-    void manualTestChecksumsCanBeDisabled() {
+    @Test @Ignore('manual')
+    void testChecksumsCanBeDisabled() {
         // TODO someone has cleaned up the checksum info in the public repos that this test
         // was relying on and so this test no longer fails unless you have the corrupt SHA1
         // value cached in your local grapes repo, change test to not rely on that fact and
         // then reinstate (use a local file repo?)
-        GroovyShell shell = new GroovyShell(new GroovyClassLoader())
-        shouldFail(RuntimeException) {
-            shell.evaluate """
+        shouldFail RuntimeException, '''
             @Grab('org.mvel:mvel2:2.1.3.Final')
             import org.mvel2.MVEL
             assert MVEL.name == 'org.mvel2.MVEL'
-            """
-        }
-        shell.evaluate """
-        @Grab('org.mvel:mvel2:2.1.3.Final')
-        @GrabConfig(disableChecksums=true)
-        import org.mvel2.MVEL
-        assert MVEL.name == 'org.mvel2.MVEL'
-        """
+        '''
+        assertScript '''
+            @Grab('org.mvel:mvel2:2.1.3.Final')
+            @GrabConfig(disableChecksums=true)
+            import org.mvel2.MVEL
+            assert MVEL.name == 'org.mvel2.MVEL'
+        '''
     }
 
+    @Test // NOTE: 'org.restlet:org.restlet:1.1.6' must not be in local m2 repository for this test to pass
     void testResolverDefinitionIsRequired() {
-        GroovyShell shell = new GroovyShell(new GroovyClassLoader())
-        shouldFail(CompilationFailedException) {
-            shell.evaluate("""
-                @Grab(group='org.restlet', module='org.restlet', version='1.1.6')
-                class AnnotationHost {}
-                import org.restlet.Application
-            """)
-        }
+        shouldFail CompilationFailedException, '''
+            @Grab(group='org.restlet', module='org.restlet', version='1.1.6')
+            import org.restlet.Application
+            class AnnotationHost {}
+            println 'hello world'
+        '''
     }
 
+    @Test
     void testResolverDefinitionResolvesDependency() {
-        GroovyShell shell = new GroovyShell(new GroovyClassLoader())
-        shell.evaluate("""
+        assertScript '''
             @GrabResolver(name='restlet.org', root='http://maven.restlet.org')
             @Grab(group='org.restlet', module='org.restlet', version='1.1.6')
             class AnnotationHost {}
-            assert org.restlet.Application.class.simpleName == 'Application'""")
+            assert org.restlet.Application.class.simpleName == 'Application'
+        '''
     }
 
+    @Test
     void testResolverDefinitionResolvesDependencyWithShorthand() {
-        GroovyShell shell = new GroovyShell(new GroovyClassLoader())
-        shell.evaluate("""
+        assertScript '''
             @GrabResolver('http://maven.restlet.org')
             @Grab('org.restlet:org.restlet:1.1.6')
             class AnnotationHost {}
-            assert org.restlet.Application.class.simpleName == 'Application'""")
+            assert org.restlet.Application.class.simpleName == 'Application'
+        '''
     }
 }


[groovy] 06/09: minor edits

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

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

commit 131d09096ec8da4c82dc795d1fe334dcbe12fc76
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 19:31:21 2019 -0600

    minor edits
---
 .../java/org/codehaus/groovy/ast/ClassHelper.java  | 86 +++++++++++-----------
 .../groovy/classgen/asm/BytecodeHelper.java        |  4 +-
 .../groovy/tools/javac/JavaStubGenerator.java      |  5 +-
 3 files changed, 48 insertions(+), 47 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
index b5b5170..c71f786 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
@@ -69,10 +69,9 @@ import java.util.Map;
 import java.util.regex.Pattern;
 
 /**
- * This class is a Helper for ClassNode and classes handling ClassNodes.
- * It does contain a set of predefined ClassNodes for the most used
- * types and some code for cached ClassNode creation and basic
- * ClassNode handling
+ * Helper for {@link ClassNode} and classes handling them.  Contains a set of
+ * pre-defined instances for the most used types and some code for cached node
+ * creation and basic handling.
  */
 public class ClassHelper {
 
@@ -87,57 +86,68 @@ public class ClassHelper {
             Iterator.class, GeneratedClosure.class, GeneratedLambda.class, GroovyObjectSupport.class
     };
 
-    public static final Class[] TUPLE_CLASSES = new Class[] {
+    public static final Class[] TUPLE_CLASSES = new Class[]{
             Tuple0.class, Tuple1.class, Tuple2.class, Tuple3.class, Tuple4.class, Tuple5.class, Tuple6.class,
             Tuple7.class, Tuple8.class, Tuple9.class, Tuple10.class, Tuple11.class, Tuple12.class, Tuple13.class,
             Tuple14.class, Tuple15.class, Tuple16.class
     };
 
     private static final String[] primitiveClassNames = new String[]{
-            "", "boolean", "char", "byte", "short",
-            "int", "long", "double", "float", "void"
+            "", "boolean", "char", "byte", "short", "int", "long", "double", "float", "void"
     };
 
     public static final ClassNode
-            DYNAMIC_TYPE = makeCached(Object.class), OBJECT_TYPE = DYNAMIC_TYPE,
-            VOID_TYPE = makeCached(Void.TYPE),
+            DYNAMIC_TYPE = makeCached(Object.class),
+            OBJECT_TYPE = DYNAMIC_TYPE,
             CLOSURE_TYPE = makeCached(Closure.class),
-            GSTRING_TYPE = makeCached(GString.class), LIST_TYPE = makeWithoutCaching(List.class),
-            TUPLE_TYPE = makeWithoutCaching(Tuple.class),
-            MAP_TYPE = makeWithoutCaching(Map.class), RANGE_TYPE = makeCached(Range.class),
-            PATTERN_TYPE = makeCached(Pattern.class), STRING_TYPE = makeCached(String.class),
-            SCRIPT_TYPE = makeCached(Script.class), REFERENCE_TYPE = makeWithoutCaching(Reference.class),
+            GSTRING_TYPE = makeCached(GString.class),
+            RANGE_TYPE = makeCached(Range.class),
+            PATTERN_TYPE = makeCached(Pattern.class),
+            STRING_TYPE = makeCached(String.class),
+            SCRIPT_TYPE = makeCached(Script.class),
             BINDING_TYPE = makeCached(Binding.class),
 
-    boolean_TYPE = makeCached(boolean.class), char_TYPE = makeCached(char.class),
-            byte_TYPE = makeCached(byte.class), int_TYPE = makeCached(int.class),
-            long_TYPE = makeCached(long.class), short_TYPE = makeCached(short.class),
-            double_TYPE = makeCached(double.class), float_TYPE = makeCached(float.class),
-            Byte_TYPE = makeCached(Byte.class), Short_TYPE = makeCached(Short.class),
-            Integer_TYPE = makeCached(Integer.class), Long_TYPE = makeCached(Long.class),
-            Character_TYPE = makeCached(Character.class), Float_TYPE = makeCached(Float.class),
-            Double_TYPE = makeCached(Double.class), Boolean_TYPE = makeCached(Boolean.class),
+            boolean_TYPE = makeCached(boolean.class),
+            char_TYPE = makeCached(char.class),
+            byte_TYPE = makeCached(byte.class),
+            int_TYPE = makeCached(int.class),
+            long_TYPE = makeCached(long.class),
+            short_TYPE = makeCached(short.class),
+            double_TYPE = makeCached(double.class),
+            float_TYPE = makeCached(float.class),
+            Byte_TYPE = makeCached(Byte.class),
+            Short_TYPE = makeCached(Short.class),
+            Integer_TYPE = makeCached(Integer.class),
+            Long_TYPE = makeCached(Long.class),
+            Character_TYPE = makeCached(Character.class),
+            Float_TYPE = makeCached(Float.class),
+            Double_TYPE = makeCached(Double.class),
+            Boolean_TYPE = makeCached(Boolean.class),
             BigInteger_TYPE = makeCached(java.math.BigInteger.class),
             BigDecimal_TYPE = makeCached(java.math.BigDecimal.class),
             Number_TYPE = makeCached(Number.class),
 
-    void_WRAPPER_TYPE = makeCached(Void.class), METACLASS_TYPE = makeCached(MetaClass.class),
+            VOID_TYPE = makeCached(Void.TYPE),
+            void_WRAPPER_TYPE = makeCached(Void.class),
+            METACLASS_TYPE = makeCached(MetaClass.class),
             Iterator_TYPE = makeCached(Iterator.class),
-            AUTOCLOSEABLE_TYPE = makeCached(AutoCloseable.class),
-
-    Enum_Type = makeWithoutCaching(Enum.class),
             Annotation_TYPE = makeCached(Annotation.class),
             ELEMENT_TYPE_TYPE = makeCached(ElementType.class),
+            AUTOCLOSEABLE_TYPE = makeCached(AutoCloseable.class),
 
-//    FunctionalInterface_Type = ClassHelper.makeCached(FunctionalInterface.class),
-
-    // uncached constants.
-    CLASS_Type = makeWithoutCaching(Class.class), COMPARABLE_TYPE = makeWithoutCaching(Comparable.class),
-            GENERATED_CLOSURE_Type = makeWithoutCaching(GeneratedClosure.class),
-            GENERATED_LAMBDA_TYPE = makeWithoutCaching(GeneratedLambda.class),
-            GROOVY_OBJECT_SUPPORT_TYPE = makeWithoutCaching(GroovyObjectSupport.class),
+            // uncached constants
+            MAP_TYPE = makeWithoutCaching(Map.class),
+            LIST_TYPE = makeWithoutCaching(List.class),
+            Enum_Type = makeWithoutCaching(Enum.class),
+            CLASS_Type = makeWithoutCaching(Class.class),
+            TUPLE_TYPE = makeWithoutCaching(Tuple.class),
+            REFERENCE_TYPE = makeWithoutCaching(Reference.class),
+            COMPARABLE_TYPE = makeWithoutCaching(Comparable.class),
             GROOVY_OBJECT_TYPE = makeWithoutCaching(GroovyObject.class),
-            GROOVY_INTERCEPTABLE_TYPE = makeWithoutCaching(GroovyInterceptable.class);
+            GENERATED_LAMBDA_TYPE = makeWithoutCaching(GeneratedLambda.class),
+            GENERATED_CLOSURE_Type = makeWithoutCaching(GeneratedClosure.class),
+            GROOVY_INTERCEPTABLE_TYPE = makeWithoutCaching(GroovyInterceptable.class),
+            GROOVY_OBJECT_SUPPORT_TYPE = makeWithoutCaching(GroovyObjectSupport.class);
 
     private static final ClassNode[] types = new ClassNode[]{
             OBJECT_TYPE,
@@ -154,8 +164,7 @@ public class ClassHelper {
             GROOVY_OBJECT_TYPE, GROOVY_INTERCEPTABLE_TYPE, Enum_Type, Annotation_TYPE
     };
 
-    private static final int ABSTRACT_STATIC_PRIVATE =
-            Modifier.ABSTRACT | Modifier.PRIVATE | Modifier.STATIC;
+    private static final int ABSTRACT_STATIC_PRIVATE = Opcodes.ACC_ABSTRACT | Opcodes.ACC_STATIC | Opcodes.ACC_PRIVATE;
     private static final int VISIBILITY = 5; // public|protected
 
     protected static final ClassNode[] EMPTY_TYPE_ARRAY = {};
@@ -168,10 +177,8 @@ public class ClassHelper {
         if (classNodeSoftReference == null || (classNode = classNodeSoftReference.get()) == null) {
             classNode = new ClassNode(c);
             ClassHelperCache.classCache.put(c, new SoftReference<ClassNode>(classNode));
-
             VMPluginFactory.getPlugin().setAdditionalClassInformation(classNode);
         }
-
         return classNode;
     }
 
@@ -189,7 +196,6 @@ public class ClassHelper {
         for (int i = 0; i < cns.length; i++) {
             cns[i] = make(classes[i]);
         }
-
         return cns;
     }
 
@@ -236,7 +242,6 @@ public class ClassHelper {
         }
     }
 
-
     /**
      * Creates a ClassNode using a given class.
      * Unlike make(String) this method will not use the cache
@@ -332,7 +337,6 @@ public class ClassHelper {
         return cn;
     }
 
-
     /**
      * Test to determine if a ClassNode is a primitive type.
      * Note: this only works for ClassNodes created using a
diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java b/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java
index 58323b5..6dea156 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/BytecodeHelper.java
@@ -478,7 +478,7 @@ public class BytecodeHelper implements Opcodes {
      */
     @Deprecated
     public static boolean box(MethodVisitor mv, ClassNode type) {
-        if (ClassHelper.isPrimitiveType(type) && !"void".equalsIgnoreCase(type.getName())) {
+        if (ClassHelper.isPrimitiveType(type) && !ClassHelper.VOID_TYPE.equals(type)) {
             box(mv, BytecodeHelper.getTypeDescription(type));
             return true;
         }
@@ -505,7 +505,7 @@ public class BytecodeHelper implements Opcodes {
      * Generates the bytecode to unbox the current value on the stack.
      */
     public static void unbox(MethodVisitor mv, ClassNode type) {
-        if (ClassHelper.isPrimitiveType(type) && !"void".equalsIgnoreCase(type.getName())) {
+        if (ClassHelper.isPrimitiveType(type) && !ClassHelper.VOID_TYPE.equals(type)) {
             unbox(mv, type.getName(), BytecodeHelper.getTypeDescription(type));
         }
     }
diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
index 2510ff0..871fe37 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavaStubGenerator.java
@@ -806,12 +806,9 @@ public class JavaStubGenerator {
     }
 
     private void printReturn(PrintWriter out, ClassNode retType) {
-        String retName = retType.getName();
-        if (!retName.equals("void")) {
+        if (!ClassHelper.VOID_TYPE.equals(retType)) {
             out.print("return ");
-
             printDefaultValue(out, retType);
-
             out.print(";");
         }
     }


[groovy] 02/09: minor edits for readability

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

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

commit a11cc18b902d00578605abd680d18ccf0555d7b7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 9 10:14:50 2019 -0600

    minor edits for readability
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java    | 21 ++++++++++++---------
 1 file changed, 12 insertions(+), 9 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
index da4e4be..71f6ec9 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -372,28 +372,31 @@ public class GenericsUtils {
             newgTypes = new GenericsType[oldgTypes.length];
             for (int i = 0; i < newgTypes.length; i++) {
                 GenericsType oldgType = oldgTypes[i];
-                if (oldgType.isPlaceholder()) {
-                    if (genericsSpec.get(oldgType.getName()) != null) {
-                        newgTypes[i] = new GenericsType(genericsSpec.get(oldgType.getName()));
-                    } else {
-                        newgTypes[i] = new GenericsType(ClassHelper.OBJECT_TYPE);
-                    }
-                } else if (oldgType.isWildcard()) {
-                    ClassNode oldLower = oldgType.getLowerBound();
-                    ClassNode lower = oldLower != null ? correctToGenericsSpecRecurse(genericsSpec, oldLower, exclusions) : null;
+                if (oldgType.isWildcard()) {
                     ClassNode[] oldUpper = oldgType.getUpperBounds();
                     ClassNode[] upper = null;
                     if (oldUpper != null) {
+                        // correct "? extends T" or "? extends T & I"
                         upper = new ClassNode[oldUpper.length];
                         for (int j = 0; j < oldUpper.length; j++) {
                             upper[j] = correctToGenericsSpecRecurse(genericsSpec, oldUpper[j], exclusions);
                         }
                     }
+                    ClassNode oldLower = oldgType.getLowerBound();
+                    ClassNode lower = null;
+                    if (oldLower != null) {
+                        // correct "? super T"
+                        lower = correctToGenericsSpecRecurse(genericsSpec, oldLower, exclusions);
+                    }
                     GenericsType fixed = new GenericsType(oldgType.getType(), upper, lower);
                     fixed.setName(oldgType.getName());
                     fixed.setWildcard(true);
                     newgTypes[i] = fixed;
+                } else if (oldgType.isPlaceholder()) {
+                    // correct "T"
+                    newgTypes[i] = new GenericsType(genericsSpec.getOrDefault(oldgType.getName(), ClassHelper.OBJECT_TYPE));
                 } else {
+                    // correct "List<T>", etc.
                     newgTypes[i] = new GenericsType(correctToGenericsSpecRecurse(genericsSpec, correctToGenericsSpec(genericsSpec, oldgType), exclusions));
                 }
             }


[groovy] 07/09: use redirect for reference comparison

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

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

commit db4bb8060bf8e3af21fb63f8837a93056d59d60e
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 19:59:04 2019 -0600

    use redirect for reference comparison
---
 .../java/org/codehaus/groovy/ast/ClassHelper.java  |  2 ++
 .../classgen/asm/sc/BugsStaticCompileTest.groovy   | 33 ++++++++++++++++++++--
 2 files changed, 32 insertions(+), 3 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
index c71f786..b5f7fac 100644
--- a/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
+++ b/src/main/java/org/codehaus/groovy/ast/ClassHelper.java
@@ -364,6 +364,7 @@ public class ClassHelper {
      * @see #make(String)
      */
     public static boolean isStaticConstantInitializerType(ClassNode cn) {
+        cn = cn.redirect();
         return cn == int_TYPE ||
                 cn == float_TYPE ||
                 cn == long_TYPE ||
@@ -376,6 +377,7 @@ public class ClassHelper {
     }
 
     public static boolean isNumberType(ClassNode cn) {
+        cn = cn.redirect();
         return cn == Byte_TYPE ||
                 cn == Short_TYPE ||
                 cn == Integer_TYPE ||
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
index 66eda6c..ce29a78 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/BugsStaticCompileTest.groovy
@@ -196,7 +196,7 @@ class BugsStaticCompileTest extends BugsSTCTest implements StaticCompilationTest
             @groovy.transform.CompileStatic
             class Main {
                 void test() {
-                    @ASTTest(phase=INSTRUCTION_SELECTION, value= {
+                    @ASTTest(phase=INSTRUCTION_SELECTION, value={
                         assert node.rightExpression.getNodeMetaData(INFERRED_TYPE).nameWithoutPackage == 'Sql'
                     })
                     def sql = Sql.newInstance("a", "b", "c", "d")
@@ -720,7 +720,7 @@ import groovy.transform.TypeCheckingMode
         shouldFailWithMessages '''
             def fieldMatcher = '[x=1] [a=b] [foo=bar]' =~ ~"\\\\[([^=\\\\[]+)=([^\\\\]]+)\\\\]"
             assert fieldMatcher instanceof java.util.regex.Matcher
-            @ASTTest(phase=INSTRUCTION_SELECTION, value = {
+            @ASTTest(phase=INSTRUCTION_SELECTION, value={
                 assert node.getNodeMetaData(INFERRED_TYPE) == OBJECT_TYPE
             })
             def value = fieldMatcher[0]
@@ -1470,7 +1470,6 @@ println someInt
         assertScript '''
             import static java.nio.file.AccessMode.*
 
-            @groovy.transform.CompileStatic
             class Dummy {
                 static main() {
                     // more than 5 to match `of(E first, E[] rest)` variant
@@ -1481,4 +1480,32 @@ println someInt
             assert Dummy.main() == [READ, WRITE, EXECUTE].toSet()
         '''
     }
+
+    void testNumberWrapperMultiAssign() {
+        assertScript '''
+            import org.codehaus.groovy.ast.CodeVisitorSupport
+            import org.codehaus.groovy.ast.expr.ConstantExpression
+
+            void test() {
+                @ASTTest(phase=INSTRUCTION_SELECTION, value={
+                    node.visit(new CodeVisitorSupport() {
+                        @Override
+                        void visitConstantExpression(ConstantExpression expr) {
+                            switch (expr.text) {
+                            case '123':
+                            case '456':
+                                assert ClassHelper.isNumberType(expr.type)
+                                break
+                            default:
+                                assert false : "unexpected constant: $expr"
+                            }
+                        }
+                    })
+                })
+                def (Integer i, Long j) = [123, 456L]
+            }
+
+            test()
+        '''
+    }
 }


[groovy] 05/09: fix generics

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

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

commit fa9fb909c4ae14604265a061b558932517b9d1d6
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 04:24:36 2019 -0600

    fix generics
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 39 ++++++++++------------
 1 file changed, 18 insertions(+), 21 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 a2dca5f..e0f3da3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -1199,12 +1199,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return null;
         }
 
-        for (int i = 0, n = TUPLE_CLASSES.length; i < n; i++) {
-            Class tcn = TUPLE_CLASSES[i];
+        for (int i = 0, n = TUPLE_CLASSES.length; i < n; i += 1) {
+            Class<?> tcn = TUPLE_CLASSES[i];
             if (tcn.equals(cn.getTypeClass())) {
                 ListExpression listExpression = new ListExpression();
                 GenericsType[] genericsTypes = cn.getGenericsTypes();
-                for (int j = 0; j < i; j++) {
+                for (int j = 0; j < i; j += 1) {
                     // the index of element in tuple starts with 1
                     MethodCallExpression mce = new MethodCallExpression(rightExpression, "getV" + (j + 1), ArgumentListExpression.EMPTY_ARGUMENTS);
                     ClassNode elementType = (genericsTypes != null ? genericsTypes[j].getType() : OBJECT_TYPE);
@@ -2370,7 +2370,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         SharedVariableCollector collector = new SharedVariableCollector(getSourceUnit());
         collector.visitClosureExpression(expression);
         Set<VariableExpression> closureSharedExpressions = collector.getClosureSharedExpressions();
-        Map<VariableExpression, ListHashMap> typesBeforeVisit = null;
+        Map<VariableExpression, Map<StaticTypesMarker, Object>> typesBeforeVisit = null;
         if (!closureSharedExpressions.isEmpty()) {
             typesBeforeVisit = new HashMap<>();
             saveVariableExpressionMetadata(closureSharedExpressions, typesBeforeVisit);
@@ -2433,11 +2433,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return (DelegationMetadata) expression.getNodeMetaData(DELEGATION_METADATA);
     }
 
-    protected void restoreVariableExpressionMetadata(final Map<VariableExpression, ListHashMap> typesBeforeVisit) {
+    protected void restoreVariableExpressionMetadata(final Map<VariableExpression, Map<StaticTypesMarker, Object>> typesBeforeVisit) {
         if (typesBeforeVisit != null) {
-            for (Map.Entry<VariableExpression, ListHashMap> entry : typesBeforeVisit.entrySet()) {
+            for (Map.Entry<VariableExpression, Map<StaticTypesMarker, Object>> entry : typesBeforeVisit.entrySet()) {
                 VariableExpression ve = entry.getKey();
-                ListHashMap metadata = entry.getValue();
+                Map<StaticTypesMarker, Object> metadata = entry.getValue();
                 for (StaticTypesMarker marker : StaticTypesMarker.values()) {
                     ve.removeNodeMetaData(marker);
                     Object value = metadata.get(marker);
@@ -2447,12 +2447,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    protected void saveVariableExpressionMetadata(final Set<VariableExpression> closureSharedExpressions, final Map<VariableExpression, ListHashMap> typesBeforeVisit) {
+    protected void saveVariableExpressionMetadata(final Set<VariableExpression> closureSharedExpressions, final Map<VariableExpression, Map<StaticTypesMarker, Object>> typesBeforeVisit) {
         for (VariableExpression ve : closureSharedExpressions) {
             // GROOVY-6921: We must force a call to getType in order to update closure shared variable whose
             // types are inferred thanks to closure parameter type inference
             getType(ve);
-            ListHashMap<StaticTypesMarker, Object> metadata = new ListHashMap<StaticTypesMarker, Object>();
+            Map<StaticTypesMarker, Object> metadata = new ListHashMap<StaticTypesMarker, Object>();
             for (StaticTypesMarker marker : StaticTypesMarker.values()) {
                 Object value = ve.getNodeMetaData(marker);
                 if (value != null) {
@@ -3541,22 +3541,19 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
 
             // now that a method has been chosen, we are allowed to visit the closures
+            MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
             if (!callArgsVisited) {
-                MethodNode mn = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
-                visitMethodCallArguments(receiver, argumentList, true, mn);
+                visitMethodCallArguments(receiver, argumentList, true, target);
                 // GROOVY-6219
-                if (mn != null) {
+                if (target != null) {
                     List<Expression> argExpressions = argumentList.getExpressions();
-                    Parameter[] parameters = mn.getParameters();
-                    for (int i = 0; i < argExpressions.size() && i < parameters.length; i++) {
+                    Parameter[] parameters = target.getParameters();
+                    for (int i = 0; i < argExpressions.size() && i < parameters.length; i += 1) {
                         Expression arg = argExpressions.get(i);
-                        ClassNode pType = parameters[i].getType();
-                        ClassNode aType = getType(arg);
-                        if (CLOSURE_TYPE.equals(pType) && CLOSURE_TYPE.equals(aType)) {
-                            if (!isAssignableTo(aType, pType)) {
-                                addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call);
-                                call.removeNodeMetaData(DIRECT_METHOD_CALL_TARGET);
-                            }
+                        ClassNode aType = getType(arg), pType = parameters[i].getType();
+                        if (CLOSURE_TYPE.equals(aType) && CLOSURE_TYPE.equals(pType) && !isAssignableTo(aType, pType)) {
+                            addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call);
+                            call.removeNodeMetaData(DIRECT_METHOD_CALL_TARGET);
                         }
                     }
                 }