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

[groovy] branch GROOVY_3_0_X updated (cf8d148 -> b0b2eff)

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

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


    from cf8d148  refactor to use more of the SourceUnit API
     new 837afab  minor edits
     new 343188d  minor edits
     new 2ebfe81  fixed style issues
     new 3fe1cf2  rework checks for annotation collectors and fix generics warnings
     new 5160c93  refactor addTransformsToClassNode and supporting methods
     new ec757f2  minor edits
     new d0f3613  create parser-agnostic API for parsing snippet
     new 5220050  refactor to use more of the SourceUnit API
     new 5951bb3  remove outer class
     new 5396ef7  GROOVY-9126: Unreachable line numbers after ARETURN in bytecode (#1095)
     new b6b0688  GROOVY-8686: restrict instanceof flow type to enclosing statement
     new 3a581dc  GROOVY-9238: look again for collector annotations when anno list changes
     new 4af20f9  fix test suite isolation
     new dd6957e  Tweak GROOVY-9126: Remove unnecessary checks (#1096)
     new a206e4f  GROOVY-9312: disable direct references to local .m2 repo jars
     new f8f3273  GROOVY-8399: apply import customizations only once per module
     new 7532803  GROOVY-9245: exclude synthetic constructors from CachedClass
     new b0b2eff  STC: isLHSOfEnclosingAssignment returns true for ++/-- on variable expr

The 18 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/builder/InitializerStrategy.java     |  26 +-
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |   1 +
 .../groovy/classgen/asm/StatementWriter.java       |  21 +-
 .../groovy/control/CompilerConfiguration.java      |  20 +-
 .../control/customizers/ImportCustomizer.java      |  65 +-
 .../codehaus/groovy/reflection/CachedClass.java    | 192 +++---
 .../org/codehaus/groovy/reflection/ClassInfo.java  |  72 +-
 .../java/org/codehaus/groovy/syntax/TokenUtil.java |  77 +--
 .../ASTTransformationCollectorCodeVisitor.java     | 343 ++++------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 723 ++++++++++-----------
 src/resources/groovy/grape/defaultGrapeConfig.xml  |   1 -
 .../{Groovy3839Bug.groovy => Groovy3839.groovy}    |  68 +-
 .../bugs/{Groovy8063.groovy => Groovy8686.groovy}  |  42 +-
 .../bugs/{Groovy9063.groovy => Groovy9126.groovy}  |  33 +-
 .../bugs/{Groovy9226.groovy => Groovy9238.groovy}  |  31 +-
 .../bugs/{Groovy9204.groovy => Groovy9245.groovy}  |  44 +-
 src/test/groovy/grape/GrabResolverTest.groovy      |  43 +-
 src/test/groovy/grape/GrapeIvyTest.groovy          |  61 ++
 .../customizers/ImportCustomizerTest.groovy        | 132 +++-
 .../groovy/transform/BuilderTransformTest.groovy   |   3 +-
 .../main/groovy/groovy/util/OptionAccessor.groovy  |  38 --
 .../MarkupTemplateTypeCheckingExtension.groovy     |  17 +-
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 396 ++++++-----
 23 files changed, 1190 insertions(+), 1259 deletions(-)
 rename src/test/groovy/bugs/{Groovy3839Bug.groovy => Groovy3839.groovy} (56%)
 copy src/test/groovy/bugs/{Groovy8063.groovy => Groovy8686.groovy} (58%)
 copy src/test/groovy/bugs/{Groovy9063.groovy => Groovy9126.groovy} (62%)
 copy src/test/groovy/bugs/{Groovy9226.groovy => Groovy9238.groovy} (64%)
 copy src/test/groovy/bugs/{Groovy9204.groovy => Groovy9245.groovy} (65%)
 delete mode 100644 subprojects/groovy-cli-commons/src/main/groovy/groovy/util/OptionAccessor.groovy


[groovy] 08/18: refactor to use more of the SourceUnit API

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

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

commit 52200506075dfc6382426b3382186bc0248eb8b2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Nov 20 13:50:21 2019 -0600

    refactor to use more of the SourceUnit API
    
    (cherry picked from commit 4ae1eff52bf18124b4ef06bd8ab8b7154e2cdbd9)
---
 .../java/org/codehaus/groovy/ast/tools/GenericsUtils.java  |  2 +-
 .../java/org/codehaus/groovy/control/ParserPlugin.java     | 14 +++++++-------
 .../text/markup/MarkupTemplateTypeCheckingExtension.groovy |  2 +-
 3 files changed, 9 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 c142de5..055e17f 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -583,7 +583,7 @@ public class GenericsUtils {
 
     public static ClassNode[] parseClassNodesFromString(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) {
         try {
-            ModuleNode moduleNode = ParserPlugin.buildAST("Dummy<" + option + "> dummy;", compilationUnit.getClassLoader(), compilationUnit.getConfiguration(), null);
+            ModuleNode moduleNode = ParserPlugin.buildAST("Dummy<" + option + "> dummy;", compilationUnit.getConfiguration(), compilationUnit.getClassLoader(), null);
             DeclarationExpression dummyDeclaration = (DeclarationExpression) ((ExpressionStatement) moduleNode.getStatementBlock().getStatements().get(0)).getExpression();
 
             // the returned node is DummyNode<Param1, Param2, Param3, ...)
diff --git a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
index 1d4f488..ee02b95 100644
--- a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
@@ -22,7 +22,6 @@ import groovy.lang.GroovyClassLoader;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.syntax.ParserException;
 import org.codehaus.groovy.syntax.Reduction;
-import org.codehaus.groovy.util.CharSequenceReader;
 
 import java.io.Reader;
 
@@ -35,11 +34,12 @@ public interface ParserPlugin {
 
     ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException;
 
-    static ModuleNode buildAST(CharSequence source, GroovyClassLoader loader, CompilerConfiguration config, ErrorCollector errors) throws ParserException {
-        String scriptName = "Script" + System.nanoTime() + ".groovy";
-        SourceUnit sourceUnit = new SourceUnit(scriptName, source.toString(), config, loader, errors);
-
-        ParserPlugin parserPlugin = config.getPluginFactory().createParserPlugin();
-        return parserPlugin.buildAST(sourceUnit, loader, parserPlugin.parseCST(sourceUnit, new CharSequenceReader(source)));
+    static ModuleNode buildAST(CharSequence sourceText, CompilerConfiguration config, GroovyClassLoader loader, ErrorCollector errors) throws CompilationFailedException {
+        SourceUnit sourceUnit = new SourceUnit("Script" + System.nanoTime() + ".groovy", sourceText.toString(), config, loader, errors);
+        sourceUnit.parse();
+        sourceUnit.completePhase();
+        sourceUnit.nextPhase();
+        sourceUnit.convert();
+        return sourceUnit.getAST();
     }
 }
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
index 697e0b4..e52958c 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
@@ -174,7 +174,7 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
 
     @CompileStatic
     private static ClassNode buildNodeFromString(String option, TypeCheckingContext ctx) {
-        def moduleNode = ParserPlugin.buildAST("Dummy<$option> dummy;", ctx.compilationUnit.classLoader, ctx.compilationUnit.configuration, ctx.errorCollector)
+        def moduleNode = ParserPlugin.buildAST("Dummy<$option> dummy;", ctx.compilationUnit.configuration, ctx.compilationUnit.classLoader, ctx.errorCollector)
         ClassNode parsedNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
         ClassNode dummyClass = new ClassNode("dummy", 0, OBJECT_TYPE)
         dummyClass.setModule(new ModuleNode(ctx.source))


[groovy] 05/18: refactor addTransformsToClassNode and supporting methods

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

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

commit 5160c9359ef310c37f11de7ed17c8ffe01076b56
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Nov 19 15:00:15 2019 -0600

    refactor addTransformsToClassNode and supporting methods
    
    (cherry picked from commit b551e2b2def997463145cd995145fa10385d7389)
---
 .../ASTTransformationCollectorCodeVisitor.java     | 148 ++++++++++-----------
 .../{Groovy3839Bug.groovy => Groovy3839.groovy}    |  68 +++++-----
 2 files changed, 103 insertions(+), 113 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
index 5369e31..5fb0418 100644
--- a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
@@ -36,13 +36,13 @@ import org.codehaus.groovy.transform.trait.Traits;
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Optional;
+import java.util.stream.Stream;
 
 import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression;
 
@@ -51,7 +51,7 @@ import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evalua
  * themselves by {@link GroovyASTTransformation}. Each such annotation is added.
  * <p>
  * This visitor is only intended to be executed once, during the
- * {@code SEMANTIC_ANALYSIS} phase of compilation.
+ * {@link CompilePhase#SEMANTIC_ANALYSIS} phase of compilation.
  */
 public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSupport {
 
@@ -104,10 +104,7 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         nodeAnnotations.addAll(mergedList);
 
         for (AnnotationNode annotation : nodeAnnotations) {
-            Annotation transformClassAnnotation = getTransformClassAnnotation(annotation.getClassNode());
-            if (transformClassAnnotation != null) {
-                addTransformsToClassNode(annotation, transformClassAnnotation);
-            }
+            addTransformsToClassNode(annotation);
         }
     }
 
@@ -194,7 +191,7 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
                     if (klass != null) {
                         try {
                             act = (AnnotationCollectorTransform) klass.getDeclaredConstructor().newInstance();
-                        } catch (ReflectiveOperationException e) {
+                        } catch (ReflectiveOperationException | RuntimeException e) {
                             source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source));
                         }
                     }
@@ -202,7 +199,8 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
                     act = new AnnotationCollectorTransform();
                 }
                 if (act != null) {
-                    replacements.put(index, act.visit(annotation, alias, origin, source));
+                    List<AnnotationNode> result = act.visit(annotation, alias, origin, source);
+                    replacements.put(index, result);
                     return;
                 }
             }
@@ -212,22 +210,6 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         }
     }
 
-    private void addTransformsToClassNode(final AnnotationNode annotation, final Annotation transformClassAnnotation) {
-        List<String> transformClassNames = getTransformClassNames(annotation, transformClassAnnotation);
-
-        if (transformClassNames.isEmpty()) {
-            String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " does not specify any transform class names/classes";
-            source.getErrorCollector().addError(new SimpleMessage(error, source));
-        }
-
-        for (String transformClass : transformClassNames) {
-            Class<?> klass = loadTransformClass(transformClass, annotation);
-            if (klass != null) {
-                verifyAndAddTransform(annotation, klass);
-            }
-        }
-    }
-
     private Class<?> loadTransformClass(final String transformClass, final AnnotationNode annotation) {
         try {
             return transformLoader.loadClass(transformClass, false, true, false);
@@ -238,76 +220,82 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         return null;
     }
 
-    private void verifyAndAddTransform(final AnnotationNode annotation, final Class<?> klass) {
-        verifyClass(annotation, klass);
-        verifyCompilePhase(annotation, klass);
-        addTransform(annotation, klass);
-    }
+    //--------------------------------------------------------------------------
+
+    /**
+     * Determines if given annotation specifies an AST transformation and if so,
+     * adds it to the current class.
+     */
+    private void addTransformsToClassNode(final AnnotationNode annotation) {
+        Annotation transformClassAnnotation = getTransformClassAnnotation(annotation.getClassNode());
+        if (transformClassAnnotation != null) {
+            try {
+                Method valueMethod = transformClassAnnotation.getClass().getMethod("value");
+                String[] transformClassNames = (String[]) valueMethod.invoke(transformClassAnnotation);
+                if (transformClassNames == null) transformClassNames = new String[0];
+
+                Method classesMethod = transformClassAnnotation.getClass().getMethod("classes");
+                Class<?>[] transformClasses = (Class[]) classesMethod.invoke(transformClassAnnotation);
+                if (transformClasses == null) transformClasses = new Class[0];
+
+                if (transformClassNames.length == 0 && transformClasses.length == 0) {
+                    String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " does not specify any transform class names or types";
+                    source.getErrorCollector().addError(new SimpleMessage(error, source));
+                }
 
-    private void verifyClass(final AnnotationNode annotation, final Class<?> klass) {
-        if (!ASTTransformation.class.isAssignableFrom(klass)) {
-            String error = "Not an ASTTransformation: " + klass.getName() + " declared by " + annotation.getClassNode().getName();
-            source.getErrorCollector().addError(new SimpleMessage(error, source));
-        }
-    }
+                if (transformClassNames.length > 0 && transformClasses.length > 0) {
+                    String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " should specify transforms by name or by type, not by both";
+                    source.getErrorCollector().addError(new SimpleMessage(error, source));
+                }
 
-    private void verifyCompilePhase(final AnnotationNode annotation, final Class<?> klass) {
-        GroovyASTTransformation transformationClass = klass.getAnnotation(GroovyASTTransformation.class);
-        if (transformationClass != null) {
-            CompilePhase specifiedCompilePhase = transformationClass.phase();
-            if (specifiedCompilePhase.getPhaseNumber() < CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) {
-                String error = annotation.getClassNode().getName() + " is defined to be run in compile phase " + specifiedCompilePhase + ". Local AST transformations must run in " + CompilePhase.SEMANTIC_ANALYSIS + " or later!";
-                source.getErrorCollector().addError(new SimpleMessage(error, source));
+                Stream.concat(Stream.of(transformClassNames), Stream.of(transformClasses).map(Class::getName)).forEach(transformClassName -> {
+                    Class<?> transformClass = loadTransformClass(transformClassName, annotation);
+                    if (transformClass != null) {
+                        verifyAndAddTransform(annotation, transformClass);
+                    }
+                });
+            } catch (ReflectiveOperationException | RuntimeException e) {
+                source.getErrorCollector().addError(new ExceptionMessage(e, true, source));
             }
-        } else {
-            String error = "AST transformation implementation classes must be annotated with " + GroovyASTTransformation.class.getName() + ". " + klass.getName() + " lacks this annotation.";
-            source.getErrorCollector().addError(new SimpleMessage(error, source));
         }
     }
 
-    @SuppressWarnings("unchecked")
-    private void addTransform(final AnnotationNode annotation, final Class<?> klass) {
-        boolean apply = !Traits.isTrait(classNode) || klass == TraitASTTransformation.class;
-        if (apply) {
-            classNode.addTransform((Class<? extends ASTTransformation>) klass, annotation);
-        }
-    }
-
-    private static Annotation getTransformClassAnnotation(final ClassNode annotatedType) {
-        if (!annotatedType.isResolved()) return null;
+    private static Annotation getTransformClassAnnotation(final ClassNode annotationType) {
+        if (!annotationType.isResolved()) return null;
 
-        for (Annotation ann : annotatedType.getTypeClass().getAnnotations()) {
-            // because compiler clients are free to choose any GroovyClassLoader for
-            // resolving ClassNodes such as annotatedType, we have to compare by name,
-            // and cannot cast the return value to GroovyASTTransformationClass
-            if (ann.annotationType().getName().equals(GroovyASTTransformationClass.class.getName())) {
-                return ann;
+        for (Annotation a : annotationType.getTypeClass().getAnnotations()) {
+            // clients are free to choose any GroovyClassLoader for resolving a
+            // ClassNode such as annotationType; we have to compare by name and
+            // cannot cast the return value to our GroovyASTTransformationClass
+            if (a.annotationType().getName().equals(GroovyASTTransformationClass.class.getName())) {
+                return a;
             }
         }
 
         return null;
     }
 
-    private List<String> getTransformClassNames(final AnnotationNode annotation, final Annotation transformClassAnnotation) {
-        List<String> result = new ArrayList<>();
-        try {
-            Method valueMethod = transformClassAnnotation.getClass().getMethod("value");
-            String[] names = (String[]) valueMethod.invoke(transformClassAnnotation);
-            result.addAll(Arrays.asList(names));
-
-            Method classesMethod = transformClassAnnotation.getClass().getMethod("classes");
-            Class<?>[] classes = (Class[]) classesMethod.invoke(transformClassAnnotation);
-            for (Class<?> klass : classes) {
-                result.add(klass.getName());
-            }
+    @SuppressWarnings("unchecked")
+    private void verifyAndAddTransform(final AnnotationNode annotation, final Class<?> transformClass) {
+        if (!ASTTransformation.class.isAssignableFrom(transformClass)) {
+            String error = "Not an ASTTransformation: " + transformClass.getName() + " declared by " + annotation.getClassNode().getName();
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
+        }
 
-            if (names.length > 0 && classes.length > 0) {
-                String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " should specify transforms only by class names or by classes and not by both";
-                source.getErrorCollector().addError(new SimpleMessage(error, source));
-            }
-        } catch (Exception e) {
-            source.addException(e);
+        GroovyASTTransformation transformationClass = transformClass.getAnnotation(GroovyASTTransformation.class);
+        if (transformationClass == null) {
+            String error = "AST transformation implementation classes must be annotated with " + GroovyASTTransformation.class.getName() + ". " + transformClass.getName() + " lacks this annotation.";
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
+        }
+
+        CompilePhase specifiedCompilePhase = transformationClass.phase();
+        if (specifiedCompilePhase.getPhaseNumber() < CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) {
+            String error = annotation.getClassNode().getName() + " is defined to be run in compile phase " + specifiedCompilePhase + ". Local AST transformations must run in SEMANTIC_ANALYSIS or later!";
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
+        }
+
+        if (!Traits.isTrait(classNode) || transformClass == TraitASTTransformation.class) {
+            classNode.addTransform((Class<? extends ASTTransformation>) transformClass, annotation);
         }
-        return result;
     }
 }
diff --git a/src/test/groovy/bugs/Groovy3839Bug.groovy b/src/test/groovy/bugs/Groovy3839.groovy
similarity index 56%
rename from src/test/groovy/bugs/Groovy3839Bug.groovy
rename to src/test/groovy/bugs/Groovy3839.groovy
index 1fd10f1..dac7d45 100644
--- a/src/test/groovy/bugs/Groovy3839Bug.groovy
+++ b/src/test/groovy/bugs/Groovy3839.groovy
@@ -18,59 +18,61 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
+import groovy.transform.CompileStatic
+import org.junit.Test
 
-class Groovy3839Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy3839 {
+
+    @Test
     void testGroovyASTTransformationWithOneClass() {
-        assertScript """
+        assertScript '''
             import groovy.bugs.*
-    
+
             @G3839A1
             class G3839V1 {}
             // verify if the ast transform added field 1
             assert G3839V1.class.fields.find{it.name == 'f1'} != null
-        """
+        '''
     }
 
+    @Test
     void testGroovyASTTransformationWithMultipleClass() {
-        assertScript """
+        assertScript '''
             import groovy.bugs.*
-    
+
             @G3839A2
             class G3839V2 {}
             // verify if the ast transforms added field f2 and f3
             assert G3839V2.class.fields.find{it.name == 'f2'} != null
             assert G3839V2.class.fields.find{it.name == 'f3'} != null
-        """
+        '''
     }
-    
+
+    @Test
     void testGroovyASTTransformationWithNeitherTransClassNamesNorClasses() {
-        try {
-            assertScript """
-                import groovy.bugs.*
-        
-                @G3839A3
-                class G3839V3 {}
-                new G3839V3()
-            """
-            fail('The script should have failed as @GroovyASTTransformationClass in GroovyASTTransformationClass does not specify transform class names or classes')
-        }catch(ex) {
-            assert ex.message.contains('@GroovyASTTransformationClass in groovy.bugs.G3839A3 does not specify any transform class names/classes')
-        }
+        def err = shouldFail '''
+            import groovy.bugs.*
+
+            @G3839A3
+            class G3839V3 {}
+            new G3839V3()
+        '''
+        assert err =~ '@GroovyASTTransformationClass in groovy.bugs.G3839A3 does not specify any transform class names or types'
     }
 
+    @Test
     void testGroovyASTTransformationWithBothTransClassNamesAndClasses() {
-        try {
-            assertScript """
-                import groovy.bugs.*
-        
-                @G3839A4
-                class G3839V4 {}
-                new G3839V4()
-            """
-            fail('The script should have failed as @GroovyASTTransformationClass in GroovyASTTransformationClass does specifies both transform class names and classes')
-        }catch(ex) {
-            assert ex.message.contains('@GroovyASTTransformationClass in groovy.bugs.G3839A4 should specify transforms only by class names or by classes and not by both')
-        }
+        def err = shouldFail '''
+            import groovy.bugs.*
+
+            @G3839A4
+            class G3839V4 {}
+            new G3839V4()
+        '''
+        assert err =~ '@GroovyASTTransformationClass in groovy.bugs.G3839A4 should specify transforms by name or by type, not by both'
     }
 }


[groovy] 17/18: GROOVY-9245: exclude synthetic constructors from CachedClass

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

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

commit 753280331e907080a814de8201c97841e96345f7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 13:11:14 2019 -0600

    GROOVY-9245: exclude synthetic constructors from CachedClass
    
    (cherry picked from commit 9ee6f869762f377d542732bd5eb46e448d3a2654)
---
 .../transform/builder/InitializerStrategy.java     | 26 ++++----
 .../codehaus/groovy/reflection/CachedClass.java    |  1 +
 src/test/groovy/bugs/Groovy9245.groovy             | 70 ++++++++++++++++++++++
 .../groovy/transform/BuilderTransformTest.groovy   |  3 +-
 4 files changed, 84 insertions(+), 16 deletions(-)

diff --git a/src/main/java/groovy/transform/builder/InitializerStrategy.java b/src/main/java/groovy/transform/builder/InitializerStrategy.java
index b48d5af..6ce152a 100644
--- a/src/main/java/groovy/transform/builder/InitializerStrategy.java
+++ b/src/main/java/groovy/transform/builder/InitializerStrategy.java
@@ -133,7 +133,6 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
     public abstract static class UNSET {
     }
 
-    private static final int PUBLIC_STATIC = ACC_PUBLIC | ACC_STATIC;
     private static final Expression DEFAULT_INITIAL_VALUE = null;
     private static final ClassNode TUPLECONS_TYPE = ClassHelper.make(TupleConstructor.class);
 
@@ -176,13 +175,13 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
                     " processing: includes/excludes only allowed on classes", anno);
         }
         if (mNode instanceof ConstructorNode) {
-            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC);
+            mNode.setModifiers(ACC_PRIVATE);
         } else {
-            if ((mNode.getModifiers() & ACC_STATIC) == 0) {
+            if (!mNode.isStatic()) {
                 transform.addError("Error during " + BuilderASTTransformation.MY_TYPE_NAME +
                         " processing: method builders only allowed on static methods", anno);
             }
-            mNode.setModifiers(ACC_PRIVATE | ACC_SYNTHETIC | ACC_STATIC);
+            mNode.setModifiers(ACC_SYNTHETIC | ACC_PRIVATE | ACC_STATIC);
         }
         ClassNode buildee = mNode.getDeclaringClass();
         Parameter[] parameters = mNode.getParameters();
@@ -226,7 +225,7 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
 
     private static List<FieldNode> convertParamsToFields(ClassNode builder, Parameter[] parameters) {
         List<FieldNode> fieldNodes = new ArrayList<FieldNode>();
-        for(Parameter parameter: parameters) {
+        for (Parameter parameter: parameters) {
             Map<String,ClassNode> genericsSpec = createGenericsSpec(builder);
             ClassNode correctedType = correctToGenericsSpecRecurse(genericsSpec, parameter.getType());
             FieldNode fieldNode = new FieldNode(parameter.getName(), parameter.getModifiers(), correctedType, builder, DEFAULT_INITIAL_VALUE);
@@ -238,7 +237,7 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
 
     private static ClassNode createInnerHelperClass(ClassNode buildee, String builderClassName, int fieldsSize) {
         final String fullName = buildee.getName() + "$" + builderClassName;
-        ClassNode builder = new InnerClassNode(buildee, fullName, PUBLIC_STATIC, OBJECT_TYPE);
+        ClassNode builder = new InnerClassNode(buildee, fullName, ACC_PUBLIC | ACC_STATIC, OBJECT_TYPE);
         GenericsType[] gtypes = new GenericsType[fieldsSize];
         for (int i = 0; i < gtypes.length; i++) {
             gtypes[i] = makePlaceholder(i);
@@ -251,7 +250,7 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
         final BlockStatement body = new BlockStatement();
         body.addStatement(returnS(callX(builder, buildMethodName)));
         ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(numFields));
-        return new MethodNode(builderMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
+        return new MethodNode(builderMethodName, ACC_PUBLIC | ACC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, body);
     }
 
     private static GenericsType[] unsetGenTypes(int numFields) {
@@ -272,8 +271,8 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
 
     private static void createBuilderConstructors(ClassNode builder, ClassNode buildee, List<FieldNode> fields) {
         addGeneratedConstructor(builder, ACC_PRIVATE, NO_PARAMS, NO_EXCEPTIONS, block(ctorSuperS()));
-        final BlockStatement body = new BlockStatement();
-        body.addStatement(ctorSuperS());
+
+        BlockStatement body = block(ctorSuperS());
         initializeFields(fields, body, false);
         addGeneratedConstructor(builder, ACC_PRIVATE, getParams(fields, buildee), NO_EXCEPTIONS, body);
     }
@@ -281,10 +280,9 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
     private static void createBuildeeConstructors(BuilderASTTransformation transform, ClassNode buildee, ClassNode builder, List<FieldNode> fields, boolean needsConstructor, boolean useSetters) {
         createInitializerConstructor(buildee, builder, fields);
         if (needsConstructor) {
-            final BlockStatement body = new BlockStatement();
-            body.addStatement(ctorSuperS());
+            BlockStatement body = block(ctorSuperS());
             initializeFields(fields, body, useSetters);
-            addGeneratedConstructor(buildee, ACC_PRIVATE | ACC_SYNTHETIC, getParams(fields, buildee), NO_EXCEPTIONS, body);
+            addGeneratedConstructor(buildee, ACC_PRIVATE, getParams(fields, buildee), NO_EXCEPTIONS, body);
         }
     }
 
@@ -296,7 +294,7 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
             argsList.add(propX(varX(initParam), fieldNode.getName()));
         }
         String newName = "$" + mNode.getName(); // can't have private and public methods of the same name, so rename original
-        addGeneratedMethod(buildee, mNode.getName(), PUBLIC_STATIC, mNode.getReturnType(), params(param(paramType, "initializer")), NO_EXCEPTIONS,
+        addGeneratedMethod(buildee, mNode.getName(), ACC_PUBLIC | ACC_STATIC, mNode.getReturnType(), params(param(paramType, "initializer")), NO_EXCEPTIONS,
                 block(stmt(callX(buildee, newName, args(argsList)))));
         renameMethod(buildee, mNode, newName);
     }
@@ -331,7 +329,7 @@ public class InitializerStrategy extends BuilderASTTransformation.AbstractBuilde
 
     private static MethodNode createBuildMethod(ClassNode builder, String buildMethodName, List<FieldNode> fields) {
         ClassNode returnType = makeClassSafeWithGenerics(builder, unsetGenTypes(fields.size()));
-        return new MethodNode(buildMethodName, PUBLIC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, block(returnS(ctorX(returnType))));
+        return new MethodNode(buildMethodName, ACC_PUBLIC | ACC_STATIC, returnType, NO_PARAMS, NO_EXCEPTIONS, block(returnS(ctorX(returnType))));
     }
 
     private MethodNode createBuilderMethodForField(ClassNode builder, List<FieldNode> fields, String prefix, int fieldPos) {
diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
index 5752836..79a7756 100644
--- a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
@@ -72,6 +72,7 @@ public class CachedClass {
         public CachedConstructor[] initValue() {
             PrivilegedAction<CachedConstructor[]> action = () -> {
                 return Arrays.stream(getTheClass().getDeclaredConstructors())
+                    .filter(c -> !c.isSynthetic()) // GROOVY-9245: exclude inner class ctors
                     .filter(c -> checkCanSetAccessible(c, CachedClass.class))
                     .map(c -> new CachedConstructor(CachedClass.this, c))
                     .toArray(CachedConstructor[]::new);
diff --git a/src/test/groovy/bugs/Groovy9245.groovy b/src/test/groovy/bugs/Groovy9245.groovy
new file mode 100644
index 0000000..d8dcc6c
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9245.groovy
@@ -0,0 +1,70 @@
+/*
+ *  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 org.codehaus.groovy.control.CompilerConfiguration
+import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit
+import org.junit.Test
+
+final class Groovy9245 {
+
+    @Test
+    void testConstructorSelection() {
+        def config = new CompilerConfiguration(
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
+        )
+
+        def parentDir = File.createTempDir()
+        try {
+            def a = new File(parentDir, 'A.java')
+            a.write '''
+                public class A {
+                    private A() {
+                    }
+                    public A(String s) {
+                    }
+                    private static class B extends A {
+                    }
+                }
+            '''
+            def b = new File(parentDir, 'Main.groovy')
+            b.write '''
+                new A(null)
+                /*
+                groovy.lang.GroovyRuntimeException: Ambiguous method overloading for method A#<init>.
+                Cannot resolve which method to invoke for [null] due to overlapping prototypes between:
+                    [class java.lang.String]
+                    [class A$1]
+                */
+            '''
+
+            def loader = new GroovyClassLoader(this.class.classLoader)
+            def cu = new JavaAwareCompilationUnit(config, loader)
+            cu.addSources(a, b)
+            cu.compile()
+
+            Class clazz = loader.loadClass('Main')
+            assert clazz.newInstance().run()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+        }
+    }
+}
diff --git a/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy b/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
index 0a707ec..a200ff6 100644
--- a/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
+++ b/src/test/org/codehaus/groovy/transform/BuilderTransformTest.groovy
@@ -774,7 +774,7 @@ class BuilderTransformTest extends CompilableTestSupport {
          '''
     }
 
-    void testInternalFieldsAreIncludedIfRequestedForInitializerStrategyStrategy_GROOVY6454() {
+    void testInternalFieldsAreIncludedIfRequestedForInitializerStrategy_GROOVY6454() {
         assertScript '''
             import groovy.transform.builder.*
 
@@ -806,5 +806,4 @@ class BuilderTransformTest extends CompilableTestSupport {
             assert new FooBuilder().name('Mary').build().name == 'John'
          '''
     }
-
 }


[groovy] 16/18: GROOVY-8399: apply import customizations only once per module

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

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

commit f8f327372df07db90f42c6f42a14e3ee341820e8
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 21 11:48:44 2019 -0600

    GROOVY-8399: apply import customizations only once per module
    
    (cherry picked from commit 5640447ece03d024b6689983c4f5a3e338e56c8d)
---
 .../control/customizers/ImportCustomizer.java      |  65 +++++-----
 .../customizers/ImportCustomizerTest.groovy        | 132 +++++++++++++++------
 2 files changed, 131 insertions(+), 66 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java b/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
index ebd16f5..d1bf9d0 100644
--- a/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
+++ b/src/main/java/org/codehaus/groovy/control/customizers/ImportCustomizer.java
@@ -22,7 +22,6 @@ import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.classgen.GeneratorContext;
-import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilePhase;
 import org.codehaus.groovy.control.SourceUnit;
 
@@ -30,27 +29,31 @@ import java.util.LinkedList;
 import java.util.List;
 
 /**
- * This compilation customizer allows addiing various types of imports to the compilation unit. Supports adding :
+ * This compilation customizer allows addiing various types of imports to the compilation unit. Supports adding:
  * <ul>
- *     <li>standard imports thanks to {@link #addImport(String)}, {@link #addImport(String, String)} or {@link #addImports(String...)}</li>
- *     <li>star imports thanks to {@link #addStarImport(String)} or {@link #addStarImports(String...)}</li>
- *     <li>static imports thanks to {@link #addStaticImport(String, String)} or {@link #addStaticImport(String, String, String)}</li>
- *     <li>static star imports thanks to {@link #addStaticStar(String)} or {@link #addStaticStars(String...)}</li>
+ *     <li>standard imports via {@link #addImports(String...)} or {@link #addImport(String, String)}</li>
+ *     <li>star imports via {@link #addStarImports(String...)}</li>
+ *     <li>static imports via {@link #addStaticImport(String, String)} or {@link #addStaticImport(String, String, String)}</li>
+ *     <li>static star imports via {@link #addStaticStars(String...)}</li>
  * </ul>
  *
  * @since 1.8.0
  */
 public class ImportCustomizer extends CompilationCustomizer {
 
-    private final List<Import> imports = new LinkedList<Import>();
+    private final List<Import> imports = new LinkedList<>();
 
     public ImportCustomizer() {
         super(CompilePhase.CONVERSION);
     }
 
     @Override
-    public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) throws CompilationFailedException {
-        final ModuleNode ast = source.getAST();
+    public void call(final SourceUnit source, final GeneratorContext context, final ClassNode classNode) {
+        ModuleNode ast = source.getAST();
+
+        // GROOVY-8399: apply import customizations only once per module
+        if (!classNode.getName().equals(ast.getMainClassName())) return;
+
         for (Import anImport : imports) {
             switch (anImport.type) {
                 case regular:
@@ -75,15 +78,7 @@ public class ImportCustomizer extends CompilationCustomizer {
     }
 
     public ImportCustomizer addStaticImport(final String className, final String fieldName) {
-        final ClassNode node = ClassHelper.make(className);
-        imports.add(new Import(ImportType.staticImport, fieldName, node, fieldName));
-        return this;
-    }
-
-    public ImportCustomizer addStaticStars(final String... classNames) {
-        for (String className : classNames) {
-            addStaticStar(className);
-        }
+        imports.add(new Import(ImportType.staticImport, fieldName, ClassHelper.make(className), fieldName));
         return this;
     }
 
@@ -92,32 +87,40 @@ public class ImportCustomizer extends CompilationCustomizer {
         return this;
     }
 
-    public ImportCustomizer addImports(final String... imports) {
-            for (String anImport : imports) {
-                addImport(anImport);
-            }
+    public ImportCustomizer addImports(final String... classNames) {
+        for (String className : classNames) {
+            addImport(className);
+        }
         return this;
     }
 
     public ImportCustomizer addStarImports(final String... packageNames) {
-            for (String packageName : packageNames) {
-                addStarImport(packageName);
-            }
+        for (String packageName : packageNames) {
+            addStarImport(packageName);
+        }
         return this;
     }
 
+    public ImportCustomizer addStaticStars(final String... classNames) {
+        for (String className : classNames) {
+            addStaticStar(className);
+        }
+        return this;
+    }
+
+    //
+
     private void addImport(final String className) {
-        final ClassNode node = ClassHelper.make(className);
+        ClassNode node = ClassHelper.make(className);
         imports.add(new Import(ImportType.regular, node.getNameWithoutPackage(), node));
     }
 
-    private void addStaticStar(final String className) {
-        imports.add(new Import(ImportCustomizer.ImportType.staticStar, className, ClassHelper.make(className)));
+    private void addStarImport(final String packageName) {
+        imports.add(new Import(ImportType.star, packageName.endsWith(".") ? packageName : packageName + "."));
     }
 
-    private void addStarImport(final String packagename) {
-        final String packageNameEndingWithDot = packagename.endsWith(".")?packagename:packagename+'.';
-        imports.add(new Import(ImportType.star,packageNameEndingWithDot));
+    private void addStaticStar(final String className) {
+        imports.add(new Import(ImportCustomizer.ImportType.staticStar, className, ClassHelper.make(className)));
     }
 
     // -------------------- Helper classes -------------------------
diff --git a/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy b/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
index 733c24d..adcd0c4 100644
--- a/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
+++ b/src/test/org/codehaus/groovy/control/customizers/ImportCustomizerTest.groovy
@@ -18,99 +18,161 @@
  */
 package org.codehaus.groovy.control.customizers
 
-import groovy.test.GroovyTestCase
 import org.codehaus.groovy.control.CompilerConfiguration
+import org.junit.Before
+import org.junit.Test
 
 /**
- * Tests the import customizer.
+ * Tests for {@link ImportCustomizer}.
  */
-class ImportCustomizerTest extends GroovyTestCase {
-    CompilerConfiguration configuration
-    ImportCustomizer importCustomizer
+final class ImportCustomizerTest {
 
+    private final CompilerConfiguration configuration = new CompilerConfiguration()
+    private final ImportCustomizer importCustomizer = new ImportCustomizer()
+
+    @Before
     void setUp() {
-        configuration = new CompilerConfiguration()
-        importCustomizer = new ImportCustomizer()
         configuration.addCompilationCustomizers(importCustomizer)
     }
 
+    @Test
     void testAddImport() {
-        importCustomizer.addImports("java.util.concurrent.atomic.AtomicInteger")
+        importCustomizer.addImports('java.util.concurrent.atomic.AtomicInteger')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AtomicInteger(0)")
+        shell.evaluate('new AtomicInteger(0)')
         // no exception means success
     }
 
+    @Test
     void testAddImportWithAlias() {
-        importCustomizer.addImport("AI","java.util.concurrent.atomic.AtomicInteger")
+        importCustomizer.addImport('AI', 'java.util.concurrent.atomic.AtomicInteger')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AI(0)")
+        shell.evaluate('new AI(0)')
         // no exception means success
     }
 
+    @Test
     void testAddInnerClassImport() {
-        importCustomizer.addImports("org.codehaus.groovy.control.customizers.ImportCustomizerTest.Inner")
+        importCustomizer.addImports('org.codehaus.groovy.control.customizers.ImportCustomizerTest.Inner')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new Inner()")
+        shell.evaluate('new Inner()')
         // no exception means success
     }
 
+    @Test
     void testAddInnerClassImport2() {
-        importCustomizer.addImports("org.codehaus.groovy.control.customizers.ImportCustomizerTest")
+        importCustomizer.addImports('org.codehaus.groovy.control.customizers.ImportCustomizerTest')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new ImportCustomizerTest.Inner()")
+        shell.evaluate('new ImportCustomizerTest.Inner()')
         // no exception means success
     }
 
+    @Test
     void testAddStaticImport() {
-        importCustomizer.addStaticImport("java.lang.Math", "PI")
+        importCustomizer.addStaticImport('java.lang.Math', 'PI')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("PI")
+        shell.evaluate('PI')
         // no exception means success
     }
 
+    @Test
     void testAddStaticImportWithAlias() {
-        importCustomizer.addStaticImport("pi","java.lang.Math", "PI")
+        importCustomizer.addStaticImport('pi', 'java.lang.Math', 'PI')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("pi")
+        shell.evaluate('pi')
         // no exception means success
     }
 
+    @Test
     void testAddStaticStarImport() {
-        importCustomizer.addStaticStars("java.lang.Math")
+        importCustomizer.addStaticStars('java.lang.Math')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("PI")
+        shell.evaluate('PI')
         // no exception means success
     }
 
+    @Test
     void testAddStarImport() {
-        importCustomizer.addStarImports("java.util.concurrent.atomic")
+        importCustomizer.addStarImports('java.util.concurrent.atomic')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("new AtomicInteger(0)")
+        shell.evaluate('new AtomicInteger(0)')
         // no exception means success
     }
 
+    @Test
     void testAddImports() {
-        importCustomizer.addImports("java.util.concurrent.atomic.AtomicInteger","java.util.concurrent.atomic.AtomicLong")
+        importCustomizer.addImports('java.util.concurrent.atomic.AtomicInteger', 'java.util.concurrent.atomic.AtomicLong')
         def shell = new GroovyShell(configuration)
-        shell.evaluate("""new AtomicInteger(0)
-        new AtomicLong(0)""")
+        shell.evaluate('''
+            new AtomicInteger(0)
+            new AtomicLong(0)
+        ''')
         // no exception means success
     }
 
+    @Test
     void testAddImportsOnScriptEngine() {
-        File script = File.createTempFile('test', '.groovy')
-            script.deleteOnExit()
-            script.write """
+        importCustomizer.addImports('java.text.SimpleDateFormat')
+
+        def script = File.createTempFile('test', '.groovy')
+        script.deleteOnExit()
+        script.write '''
             println new SimpleDateFormat()
-        """
+        '''
+        // run script with script engine; this will not work if import customizer is not used
+        def scriptEngine = new GroovyScriptEngine(script.parent)
+        scriptEngine.config = configuration
+        scriptEngine.run(script.name, new Binding())
+    }
 
-        importCustomizer.addImports 'java.text.SimpleDateFormat'
+    @Test // GROOVY-8399
+    void testAddImportsOnModuleWithMultipleClasses() {
+        importCustomizer.addImports('java.text.SimpleDateFormat')
+        def shell = new GroovyShell(configuration)
+        shell.evaluate('''\
+            @groovy.transform.ASTTest({
+                def imports = node.module.imports*.text
+                assert imports == ['import java.text.SimpleDateFormat as SimpleDateFormat']
+            })
+            class A {
+                static class AA {
+                }
+            }
+            class B {
+                static class BB {
+                }
+            }
+            class C {
+                static class CC {
+                }
+            }
+            println new SimpleDateFormat()
+        ''')
+    }
 
-        // Run script with script engine: this will not work, import customizer is not used
-        GroovyScriptEngine scriptEngine = new GroovyScriptEngine(script.parent)
-        scriptEngine.setConfig configuration
-        scriptEngine.run script.name, new Binding()
+    @Test // GROOVY-8399
+    void testAddStarImportsOnModuleWithMultipleClasses() {
+        importCustomizer.addStarImports('java.text', 'groovy.transform')
+        def shell = new GroovyShell(configuration)
+        shell.evaluate('''\
+            @groovy.transform.ASTTest({
+                def imports = node.module.starImports*.text
+                assert imports == ['import java.text.*', 'import groovy.transform.*']
+            })
+            class A {
+                static class AA {
+                }
+            }
+            class B {
+                static class BB {
+                }
+            }
+            class C {
+                static class CC {
+                }
+            }
+            println new SimpleDateFormat()
+        ''')
     }
 
     protected static class Inner {}


[groovy] 06/18: minor edits

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

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

commit ec757f24477c7c7d395df91ded022b9005d8afec
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Nov 20 09:53:15 2019 -0600

    minor edits
    
    (cherry picked from commit ab2b7d827f9eddc552b7c6e8fe976cd59c0477e2)
---
 .../groovy/control/CompilerConfiguration.java      |  20 +-
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 396 ++++++++++-----------
 2 files changed, 204 insertions(+), 212 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
index 3ed8da0..1530ada 100644
--- a/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
+++ b/src/main/java/org/codehaus/groovy/control/CompilerConfiguration.java
@@ -97,7 +97,7 @@ public class CompilerConfiguration {
     public static final String PRE_JDK5 = JDK4;
 
     /**
-     * JDK version to bytecode version mapping
+     * JDK version to bytecode version mapping.
      */
     public static final Map<String, Integer> JDK_TO_BYTECODE_VERSION_MAP = Maps.of(
             JDK4, Opcodes.V1_4,
@@ -113,11 +113,15 @@ public class CompilerConfiguration {
             JDK14, Opcodes.V14
     );
 
-    /** The valid targetBytecode values. */
-    public static final String[] ALLOWED_JDKS = JDK_TO_BYTECODE_VERSION_MAP.keySet().toArray(new String[0]);
+    /**
+     * The valid targetBytecode values.
+     */
+    public static final String[] ALLOWED_JDKS = JDK_TO_BYTECODE_VERSION_MAP.keySet().toArray(new String[JDK_TO_BYTECODE_VERSION_MAP.size()]);
+
+    public static final int ASM_API_VERSION = Opcodes.ASM7;
 
     /**
-     * The default source encoding
+     * The default source encoding.
      */
     public static final String DEFAULT_SOURCE_ENCODING = "UTF-8";
 
@@ -302,7 +306,7 @@ public class CompilerConfiguration {
     /**
      * Classpath for use during compilation
      */
-    private LinkedList<String> classpath;
+    private List<String> classpath;
 
     /**
      * If true, the compiler should produce action information
@@ -382,8 +386,6 @@ public class CompilerConfiguration {
 
     private BytecodeProcessor bytecodePostprocessor;
 
-    public static final int ASM_API_VERSION = Opcodes.ASM7;
-
     /**
      * Sets the compiler flags/settings to default values.
      *
@@ -1037,7 +1039,7 @@ public class CompilerConfiguration {
      */
     public CompilerConfiguration addCompilationCustomizers(CompilationCustomizer... customizers) {
         if (customizers == null) throw new IllegalArgumentException("provided customizers list must not be null");
-        compilationCustomizers.addAll(Arrays.asList(customizers));
+        Collections.addAll(compilationCustomizers, customizers);
         return this;
     }
 
@@ -1112,6 +1114,6 @@ public class CompilerConfiguration {
      */
     public boolean isMemStubEnabled() {
         Object memStubEnabled = getJointCompilationOptions().get(MEM_STUB);
-        return Optional.ofNullable(memStubEnabled).map(value -> "true".equals(value.toString())).orElse(Boolean.FALSE).booleanValue();
+        return Optional.ofNullable(memStubEnabled).map(value -> Boolean.parseBoolean(value.toString())).orElse(Boolean.FALSE).booleanValue();
     }
 }
diff --git a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
index 33e794e..83afe21 100644
--- a/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ b/subprojects/parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -19,6 +19,7 @@
 package org.apache.groovy.parser.antlr4;
 
 import groovy.lang.Tuple2;
+import groovy.transform.Trait;
 import org.antlr.v4.runtime.ANTLRErrorListener;
 import org.antlr.v4.runtime.CharStream;
 import org.antlr.v4.runtime.CharStreams;
@@ -32,6 +33,174 @@ import org.antlr.v4.runtime.misc.Interval;
 import org.antlr.v4.runtime.misc.ParseCancellationException;
 import org.antlr.v4.runtime.tree.ParseTree;
 import org.antlr.v4.runtime.tree.TerminalNode;
+import org.apache.groovy.parser.antlr4.GroovyParser.AdditiveExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AndExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AnnotatedQualifiedClassNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AnnotationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AnnotationNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AnnotationsOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AnonymousInnerClassDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ArgumentsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ArrayInitializerContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AssertStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.AssignmentExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BlockContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BlockStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BlockStatementsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BlockStatementsOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BooleanLiteralAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BreakStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.BuiltInTypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CastExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CastParExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CatchClauseContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CatchTypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassBodyContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassBodyDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassOrInterfaceModifierContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassOrInterfaceModifiersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassOrInterfaceModifiersOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassOrInterfaceTypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassicalForControlContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClassifiedModifiersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClosureContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ClosureOrLambdaExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CommandArgumentContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CommandExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CommandExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CompilationUnitContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ConditionalExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ConditionalStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ContinueStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CreatedNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.CreatorContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.DimsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.DimsOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.DoWhileStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.DynamicMemberNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ElementValueArrayInitializerContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ElementValueContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ElementValuePairContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ElementValuePairsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ElementValuesContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnhancedArgumentListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnhancedArgumentListElementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnhancedForControlContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnhancedStatementExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnumConstantContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EnumConstantsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.EqualityExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ExclusiveOrExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ExpressionInParContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ExpressionListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ExpressionListElementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FieldDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FinallyBlockContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FloatingPointLiteralAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ForControlContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ForInitContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ForStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ForUpdateContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FormalParameterContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FormalParameterListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.FormalParametersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.GroovyParserRuleContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.GstringContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.GstringPathContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.GstringValueContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.IdentifierContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.IdentifierPrmrAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.IfElseStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ImportDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.InclusiveOrExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.IndexPropertyArgsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.IntegerLiteralAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.KeywordsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LabeledStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LambdaBodyContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LocalVariableDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LogicalAndExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LogicalOrExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.LoopStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MapContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MapEntryContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MapEntryLabelContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MapEntryListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MemberDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MethodBodyContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MethodDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MethodNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ModifierContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ModifiersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ModifiersOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MultipleAssignmentExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.MultiplicativeExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.NamePartContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.NamedPropertyArgsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.NewPrmrAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.NonWildcardTypeArgumentsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.NullLiteralAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PackageDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ParExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PathElementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PathExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PostfixExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PowerExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.PrimitiveTypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.QualifiedClassNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.QualifiedClassNameListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.QualifiedNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.QualifiedStandardClassNameContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.RegexExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.RelationalExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ResourceContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ResourceListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ResourcesContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ReturnStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ReturnTypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ScriptStatementsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ShiftExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.StandardLambdaExpressionContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.StandardLambdaParametersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.StatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.StringLiteralContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.SuperPrmrAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.SwitchBlockStatementGroupContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.SwitchLabelContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.SwitchStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.SynchronizedStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ThisFormalParameterContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ThisPrmrAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.ThrowStmtAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TryCatchStatementContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeArgumentContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeArgumentsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeArgumentsOrDiamondContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeBoundContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeListContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeNamePairContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeNamePairsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeParameterContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.TypeParametersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.UnaryAddExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.UnaryNotExprAltContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableDeclarationContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableDeclaratorContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableDeclaratorIdContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableDeclaratorsContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableInitializerContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableInitializersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableModifierContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableModifiersContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableModifiersOptContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.VariableNamesContext;
+import org.apache.groovy.parser.antlr4.GroovyParser.WhileStmtAltContext;
 import org.apache.groovy.parser.antlr4.internal.DescriptiveErrorStrategy;
 import org.apache.groovy.parser.antlr4.internal.atnmanager.AtnManager;
 import org.apache.groovy.parser.antlr4.util.StringUtils;
@@ -130,7 +299,6 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
 import java.util.Deque;
-import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.LinkedList;
@@ -138,199 +306,31 @@ import java.util.List;
 import java.util.Map;
 import java.util.Objects;
 import java.util.Optional;
-import java.util.Set;
 import java.util.stream.Collectors;
 import java.util.stream.Stream;
 
 import static groovy.lang.Tuple.tuple;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ADD;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AS;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AdditiveExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AndExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotatedQualifiedClassNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationsOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnonymousInnerClassDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ArgumentsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ArrayInitializerContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AssertStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.AssignmentExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BooleanLiteralAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.BuiltInTypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CASE;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastParExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CatchClauseContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CatchTypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifierContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceTypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassicalForControlContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassifiedModifiersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClosureContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClosureOrLambdaExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandArgumentContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CompilationUnitContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ContinueStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CreatedNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.CreatorContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEC;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEF;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEFAULT;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DimsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DimsOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DoWhileStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.DynamicMemberNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueArrayInitializerContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuesContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListElementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedForControlContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedStatementExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.EqualityExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExclusiveOrExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionInParContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListElementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FieldDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FinallyBlockContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FloatingPointLiteralAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForControlContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForInitContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForUpdateContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParametersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GE;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GT;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GroovyParserRuleContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringPathContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringValueContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IN;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.INC;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.INSTANCEOF;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierPrmrAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IfElseStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ImportDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.InclusiveOrExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IndexPropertyArgsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.IntegerLiteralAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.KeywordsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LE;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LT;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LabeledStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LambdaBodyContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LocalVariableDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalAndExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalOrExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.LoopStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryLabelContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MemberDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodBodyContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifierContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MultipleAssignmentExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.MultiplicativeExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_IN;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_INSTANCEOF;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NamePartContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NamedPropertyArgsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NewPrmrAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NonWildcardTypeArgumentsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.NullLiteralAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PRIVATE;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PackageDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ParExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PathElementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PathExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PostfixExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PowerExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.PrimitiveTypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedStandardClassNameContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.RegexExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.RelationalExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourcesContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnTypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.STATIC;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SUB;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ScriptStatementsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ShiftExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaExpressionContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaParametersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.StatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.StringLiteralContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SuperPrmrAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchBlockStatementGroupContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchLabelContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.SynchronizedStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ThisFormalParameterContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ThisPrmrAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.ThrowStmtAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TryCatchStatementContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsOrDiamondContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeBoundContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeListContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParameterContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParametersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryAddExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryNotExprAltContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VAR;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclarationContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorIdContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorsContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableInitializerContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableInitializersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifierContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersOptContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableNamesContext;
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.WhileStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyParser.ADD;
+import static org.apache.groovy.parser.antlr4.GroovyParser.AS;
+import static org.apache.groovy.parser.antlr4.GroovyParser.CASE;
+import static org.apache.groovy.parser.antlr4.GroovyParser.DEC;
+import static org.apache.groovy.parser.antlr4.GroovyParser.DEF;
+import static org.apache.groovy.parser.antlr4.GroovyParser.DEFAULT;
+import static org.apache.groovy.parser.antlr4.GroovyParser.GE;
+import static org.apache.groovy.parser.antlr4.GroovyParser.GT;
+import static org.apache.groovy.parser.antlr4.GroovyParser.IN;
+import static org.apache.groovy.parser.antlr4.GroovyParser.INC;
+import static org.apache.groovy.parser.antlr4.GroovyParser.INSTANCEOF;
+import static org.apache.groovy.parser.antlr4.GroovyParser.LE;
+import static org.apache.groovy.parser.antlr4.GroovyParser.LT;
+import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_IN;
+import static org.apache.groovy.parser.antlr4.GroovyParser.NOT_INSTANCEOF;
+import static org.apache.groovy.parser.antlr4.GroovyParser.PRIVATE;
+import static org.apache.groovy.parser.antlr4.GroovyParser.STATIC;
+import static org.apache.groovy.parser.antlr4.GroovyParser.SUB;
+import static org.apache.groovy.parser.antlr4.GroovyParser.VAR;
 import static org.apache.groovy.parser.antlr4.util.PositionConfigureUtils.configureAST;
+import static org.codehaus.groovy.classgen.asm.util.TypeUtil.isPrimitiveType;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
 
@@ -1190,11 +1190,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     }
 
     private void attachTraitAnnotation(ClassNode classNode) {
-        attachAnnotation(classNode, GROOVY_TRANSFORM_TRAIT);
-    }
-
-    private void attachAnnotation(ClassNode classNode, String annotationClassName) {
-        classNode.addAnnotation(new AnnotationNode(ClassHelper.make(annotationClassName)));
+        classNode.addAnnotation(new AnnotationNode(ClassHelper.make(Trait.class)));
     }
 
     @SuppressWarnings("unchecked")
@@ -2310,7 +2306,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
                 String baseExprText = baseExpr.getText();
                 if (VOID_STR.equals(baseExprText)) { // e.g. void()
                     return configureAST(createCallMethodCallExpression(this.createConstantExpression(baseExpr), argumentsExpr), ctx);
-                } else if (PRIMITIVE_TYPE_SET.contains(baseExprText)) { // e.g. int(), long(), float(), etc.
+                } else if (isPrimitiveType(baseExprText)) { // e.g. int(), long(), float(), etc.
                     throw createParsingFailedException("Primitive type literal: " + baseExprText + " cannot be used as a method name", ctx);
                 }
             }
@@ -3337,7 +3333,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         // statements like `foo(String a)` is invalid
         MethodCallExpression methodCallExpression = (MethodCallExpression) expression;
         String methodName = methodCallExpression.getMethodAsString();
-        if (methodCallExpression.isImplicitThis() && Character.isUpperCase(methodName.codePointAt(0)) || PRIMITIVE_TYPE_SET.contains(methodName)) {
+        if (methodCallExpression.isImplicitThis() && Character.isUpperCase(methodName.codePointAt(0)) || isPrimitiveType(methodName)) {
             throw createParsingFailedException("Invalid method declaration", ctx);
         }
     }
@@ -4639,11 +4635,8 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     private static final String PACKAGE_INFO = "package-info";
     private static final String PACKAGE_INFO_FILE_NAME = PACKAGE_INFO + ".groovy";
 
-    private static final String GROOVY_TRANSFORM_TRAIT = "groovy.transform.Trait";
-    private static final Set<String> PRIMITIVE_TYPE_SET = Collections.unmodifiableSet(new HashSet<>(Arrays.asList("boolean", "char", "byte", "short", "int", "long", "float", "double")));
-
+    private static final String CLASS_NAME = "_CLASS_NAME";
     private static final String INSIDE_PARENTHESES_LEVEL = "_INSIDE_PARENTHESES_LEVEL";
-
     private static final String IS_INSIDE_INSTANCEOF_EXPR = "_IS_INSIDE_INSTANCEOF_EXPR";
     private static final String IS_SWITCH_DEFAULT = "_IS_SWITCH_DEFAULT";
     private static final String IS_NUMERIC = "_IS_NUMERIC";
@@ -4651,7 +4644,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     private static final String IS_INTERFACE_WITH_DEFAULT_METHODS = "_IS_INTERFACE_WITH_DEFAULT_METHODS";
     private static final String IS_INSIDE_CONDITIONAL_EXPRESSION = "_IS_INSIDE_CONDITIONAL_EXPRESSION";
     private static final String IS_COMMAND_EXPRESSION = "_IS_COMMAND_EXPRESSION";
-
     private static final String PATH_EXPRESSION_BASE_EXPR = "_PATH_EXPRESSION_BASE_EXPR";
     private static final String PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES = "_PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES";
     private static final String PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN = "_PATH_EXPRESSION_BASE_EXPR_SAFE_CHAIN";
@@ -4663,6 +4655,4 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     private static final String INTEGER_LITERAL_TEXT = "_INTEGER_LITERAL_TEXT";
     private static final String FLOATING_POINT_LITERAL_TEXT = "_FLOATING_POINT_LITERAL_TEXT";
     private static final String ENCLOSING_INSTANCE_EXPRESSION = "_ENCLOSING_INSTANCE_EXPRESSION";
-
-    private static final String CLASS_NAME = "_CLASS_NAME";
 }


[groovy] 18/18: STC: isLHSOfEnclosingAssignment returns true for ++/-- on variable expr

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

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

commit b0b2effbeef1ef0ebe20ed095b4c97e243c1f035
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 10:17:13 2019 -0600

    STC: isLHSOfEnclosingAssignment returns true for ++/-- on variable expr
    
    PV_FIELDS_MUTATION is recorded instead of PV_FIELDS_ACCESS
    
    This is a first step towards fixing:
    
        @NotYetImplemented // GROOVY-7304
        void testShouldGoThroughPrivateBridgeAccessorWithWriteAccess() {
            ['++i', 'i++', 'i+=1', 'i=i+1'].each {
                assertScript """
                    class Foo {
                        private int i = 1
                        def m() { new String().with { $it } }
                    }
                    assert new Foo().m() == 2
                    class Bar extends Foo {}
                    assert new Bar().m() == 2
                """
            }
        }
    
    (cherry picked from commit 8c0c5b018805fcab7217f5cdc784fc88354cfb15)
---
 .../java/org/codehaus/groovy/syntax/TokenUtil.java | 77 +++++++++-------------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 63 ++++++++++--------
 2 files changed, 67 insertions(+), 73 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java b/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
index b03b6c7..884ab2d 100644
--- a/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
+++ b/src/main/java/org/codehaus/groovy/syntax/TokenUtil.java
@@ -18,45 +18,30 @@
  */
 package org.codehaus.groovy.syntax;
 
-import static org.codehaus.groovy.syntax.Types.BITWISE_AND;
-import static org.codehaus.groovy.syntax.Types.BITWISE_AND_EQUAL;
-import static org.codehaus.groovy.syntax.Types.BITWISE_OR;
-import static org.codehaus.groovy.syntax.Types.BITWISE_OR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.BITWISE_XOR;
-import static org.codehaus.groovy.syntax.Types.BITWISE_XOR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.DIVIDE;
-import static org.codehaus.groovy.syntax.Types.DIVIDE_EQUAL;
-import static org.codehaus.groovy.syntax.Types.INTDIV;
-import static org.codehaus.groovy.syntax.Types.INTDIV_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LEFT_SHIFT;
-import static org.codehaus.groovy.syntax.Types.LEFT_SHIFT_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_AND;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_AND_EQUAL;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_OR;
-import static org.codehaus.groovy.syntax.Types.LOGICAL_OR_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MINUS;
-import static org.codehaus.groovy.syntax.Types.MINUS_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MOD;
-import static org.codehaus.groovy.syntax.Types.MOD_EQUAL;
-import static org.codehaus.groovy.syntax.Types.MULTIPLY;
-import static org.codehaus.groovy.syntax.Types.MULTIPLY_EQUAL;
-import static org.codehaus.groovy.syntax.Types.PLUS;
-import static org.codehaus.groovy.syntax.Types.PLUS_EQUAL;
-import static org.codehaus.groovy.syntax.Types.POWER;
-import static org.codehaus.groovy.syntax.Types.POWER_EQUAL;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_EQUAL;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED;
-import static org.codehaus.groovy.syntax.Types.RIGHT_SHIFT_UNSIGNED_EQUAL;
+import java.util.Optional;
 
 /**
  * Utility methods for working with Tokens.
- *
  */
 public class TokenUtil {
+
     private TokenUtil() {
     }
 
+    public static Optional<Token> asAssignment(int op) {
+        switch (op) {
+            case Types.PLUS_PLUS:
+            case Types.PREFIX_PLUS_PLUS:
+            case Types.POSTFIX_PLUS_PLUS:
+                return Optional.of(Token.newSymbol(Types.PLUS_EQUAL, -1, -1));
+            case Types.MINUS_MINUS:
+            case Types.PREFIX_MINUS_MINUS:
+            case Types.POSTFIX_MINUS_MINUS:
+                return Optional.of(Token.newSymbol(Types.MINUS_EQUAL, -1, -1));
+        }
+        return Optional.empty();
+    }
+
     /**
      * Removes the assignment portion of a given token.  If the given token
      * is not an operator with assignment, the given token is returned.
@@ -67,21 +52,21 @@ public class TokenUtil {
      */
     public static int removeAssignment(int op) {
         switch (op) {
-            case PLUS_EQUAL: return PLUS;
-            case MINUS_EQUAL: return MINUS;
-            case MULTIPLY_EQUAL: return MULTIPLY;
-            case LEFT_SHIFT_EQUAL: return LEFT_SHIFT;
-            case RIGHT_SHIFT_EQUAL: return RIGHT_SHIFT;
-            case RIGHT_SHIFT_UNSIGNED_EQUAL: return RIGHT_SHIFT_UNSIGNED;
-            case LOGICAL_OR_EQUAL: return LOGICAL_OR;
-            case LOGICAL_AND_EQUAL: return LOGICAL_AND;
-            case MOD_EQUAL: return MOD;
-            case DIVIDE_EQUAL: return DIVIDE;
-            case INTDIV_EQUAL: return INTDIV;
-            case POWER_EQUAL: return POWER;
-            case BITWISE_OR_EQUAL: return BITWISE_OR;
-            case BITWISE_AND_EQUAL: return BITWISE_AND;
-            case BITWISE_XOR_EQUAL: return BITWISE_XOR;
+            case Types.PLUS_EQUAL: return Types.PLUS;
+            case Types.MINUS_EQUAL: return Types.MINUS;
+            case Types.MULTIPLY_EQUAL: return Types.MULTIPLY;
+            case Types.LEFT_SHIFT_EQUAL: return Types.LEFT_SHIFT;
+            case Types.RIGHT_SHIFT_EQUAL: return Types.RIGHT_SHIFT;
+            case Types.RIGHT_SHIFT_UNSIGNED_EQUAL: return Types.RIGHT_SHIFT_UNSIGNED;
+            case Types.LOGICAL_OR_EQUAL: return Types.LOGICAL_OR;
+            case Types.LOGICAL_AND_EQUAL: return Types.LOGICAL_AND;
+            case Types.MOD_EQUAL: return Types.MOD;
+            case Types.DIVIDE_EQUAL: return Types.DIVIDE;
+            case Types.INTDIV_EQUAL: return Types.INTDIV;
+            case Types.POWER_EQUAL: return Types.POWER;
+            case Types.BITWISE_OR_EQUAL: return Types.BITWISE_OR;
+            case Types.BITWISE_AND_EQUAL: return Types.BITWISE_AND;
+            case Types.BITWISE_XOR_EQUAL: return Types.BITWISE_XOR;
             default: return op;
         }
     }
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 79132b3..bc36c28 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -187,6 +187,7 @@ import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.castX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.constX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.isOrImplements;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
 import static org.codehaus.groovy.ast.tools.GeneralUtils.thisPropX;
@@ -2044,7 +2045,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitPostfixExpression(final PostfixExpression expression) {
-        super.visitPostfixExpression(expression);
         Expression operand = expression.getExpression();
         int operator = expression.getOperation().getType();
         visitPrefixOrPostifExpression(expression, operand, operator);
@@ -2052,46 +2052,55 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitPrefixExpression(final PrefixExpression expression) {
-        super.visitPrefixExpression(expression);
         Expression operand = expression.getExpression();
         int operator = expression.getOperation().getType();
         visitPrefixOrPostifExpression(expression, operand, operator);
     }
 
     private void visitPrefixOrPostifExpression(final Expression origin, final Expression operand, final int operator) {
-        boolean isPostfix = origin instanceof PostfixExpression;
-        ClassNode exprType = getType(operand);
-        String name = operator == PLUS_PLUS ? "next" : operator == MINUS_MINUS ? "previous" : null;
-
-        if (name != null && isNumberType(exprType)) {
-            if (!isPrimitiveType(exprType)) {
-                MethodNode node = findMethodOrFail(varX("_dummy_", exprType), exprType, name);
+        Optional<Token> token = TokenUtil.asAssignment(operator);
+        if (token.isPresent()) { // push "operand += 1" or "operand -= 1" onto stack for LHS checks
+            typeCheckingContext.pushEnclosingBinaryExpression(binX(operand, token.get(), constX(1)));
+        }
+        try {
+            operand.visit(this);
+            ClassNode operandType = getType(operand);
+            boolean isPostfix = (origin instanceof PostfixExpression);
+            String name = (operator == PLUS_PLUS ? "next" : operator == MINUS_MINUS ? "previous" : null);
+
+            if (name != null && isNumberType(operandType)) {
+                if (!isPrimitiveType(operandType)) {
+                    MethodNode node = findMethodOrFail(varX("_dummy_", operandType), operandType, name);
+                    if (node != null) {
+                        storeTargetMethod(origin, node);
+                        storeType(origin, isPostfix ? operandType : getMathWideningClassNode(operandType));
+                        return;
+                    }
+                }
+                storeType(origin, operandType);
+                return;
+            }
+            if (name != null && operandType.isDerivedFrom(Number_TYPE)) {
+                // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
+                MethodNode node = findMethodOrFail(operand, operandType, name);
                 if (node != null) {
                     storeTargetMethod(origin, node);
-                    storeType(origin, isPostfix ? exprType : getMathWideningClassNode(exprType));
+                    storeType(origin, getMathWideningClassNode(operandType));
                     return;
                 }
             }
-            storeType(origin, exprType);
-            return;
-        }
-        if (name != null && exprType.isDerivedFrom(Number_TYPE)) {
-            // special case for numbers, improve type checking as we can expect ++ and -- to return the same type
-            MethodNode node = findMethodOrFail(operand, exprType, name);
+            if (name == null) {
+                addUnsupportedPreOrPostfixExpressionError(origin);
+                return;
+            }
+
+            MethodNode node = findMethodOrFail(operand, operandType, name);
             if (node != null) {
                 storeTargetMethod(origin, node);
-                storeType(origin, getMathWideningClassNode(exprType));
-                return;
+                storeType(origin, isPostfix ? operandType : inferReturnTypeGenerics(operandType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
             }
-        }
-        if (name == null) {
-            addUnsupportedPreOrPostfixExpressionError(origin);
-            return;
-        }
-        MethodNode node = findMethodOrFail(operand, exprType, name);
-        if (node != null) {
-            storeTargetMethod(origin, node);
-            storeType(origin, isPostfix ? exprType : inferReturnTypeGenerics(exprType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
+        } finally {
+            if (token.isPresent()) typeCheckingContext.popEnclosingBinaryExpression();
         }
     }
 


[groovy] 01/18: minor edits

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

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

commit 837afab8fc58c131d6af1b0613bbd70f8c048d3c
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 17 17:19:01 2019 -0600

    minor edits
    
    (cherry picked from commit ab630c095da254d346803e8406b05ddab7f724b6)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 571 +++++++++------------
 1 file changed, 256 insertions(+), 315 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 44140c0..fa99933 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -332,11 +332,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             checkReturnType(returnStatement);
             if (typeCheckingContext.getEnclosingClosure() != null) {
                 addClosureReturnType(getType(returnStatement.getExpression()));
-            } else if (typeCheckingContext.getEnclosingMethod() != null) {
-            } else {
-                throw new GroovyBugError("Unexpected return statement at "
-                        + returnStatement.getLineNumber() + ":" + returnStatement.getColumnNumber()
-                        + " " + returnStatement.getText());
+            } else if (typeCheckingContext.getEnclosingMethod() == null) {
+                throw new GroovyBugError("Unexpected return statement at " + returnStatement.getLineNumber() + ":" + returnStatement.getColumnNumber() + " " + returnStatement.getText());
             }
         }
     };
@@ -348,7 +345,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected FieldNode currentField;
     protected PropertyNode currentProperty;
 
-    public StaticTypeCheckingVisitor(SourceUnit source, ClassNode cn) {
+    public StaticTypeCheckingVisitor(final SourceUnit source, final ClassNode cn) {
         this.typeCheckingContext = new TypeCheckingContext(this);
         this.extension = createDefaultTypeCheckingExtension();
         this.typeCheckingContext.source = source;
@@ -383,12 +380,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return typeCheckingContext;
     }
 
-    public void addTypeCheckingExtension(TypeCheckingExtension extension) {
+    public void addTypeCheckingExtension(final TypeCheckingExtension extension) {
         this.extension.addHandler(extension);
     }
 
-    public void setCompilationUnit(CompilationUnit cu) {
-        typeCheckingContext.setCompilationUnit(cu);
+    public void setCompilationUnit(final CompilationUnit compilationUnit) {
+        typeCheckingContext.setCompilationUnit(compilationUnit);
     }
 
     @Override
@@ -474,7 +471,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      *
      * @return true if the inner class node should be skipped
      */
-    protected boolean isSkippedInnerClass(AnnotatedNode node) {
+    protected boolean isSkippedInnerClass(final AnnotatedNode node) {
         if (!(node instanceof InnerClassNode)) return false;
         MethodNode enclosingMethod = ((InnerClassNode) node).getEnclosingMethod();
         return enclosingMethod != null && isSkipMode(enclosingMethod);
@@ -489,7 +486,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private static void addPrivateFieldOrMethodAccess(Expression source, ClassNode cn, StaticTypesMarker key, ASTNode accessedMember) {
+    private static void addPrivateFieldOrMethodAccess(final Expression source, final ClassNode cn, final StaticTypesMarker key, final ASTNode accessedMember) {
         cn.getNodeMetaData(key, x -> new LinkedHashSet<>()).add(accessedMember);
         source.putNodeMetaData(key, accessedMember);
     }
@@ -497,7 +494,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     /**
      * Given a field node, checks if we are accessing or setting a private field from an inner class.
      */
-    private void checkOrMarkPrivateAccess(Expression source, FieldNode fn, boolean lhsOfAssignment) {
+    private void checkOrMarkPrivateAccess(final Expression source, final FieldNode fn, final boolean lhsOfAssignment) {
         if (fn == null) return;
         ClassNode declaringClass = fn.getDeclaringClass(), enclosingClassNode = typeCheckingContext.getEnclosingClassNode();
         if (fn.isPrivate() && (declaringClass != enclosingClassNode || typeCheckingContext.getEnclosingClosure() != null)
@@ -520,7 +517,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private MethodNode findValidGetter(ClassNode classNode, String name) {
+    private MethodNode findValidGetter(final ClassNode classNode, final String name) {
         MethodNode getterMethod = classNode.getGetterMethod(name);
         if (getterMethod != null && (getterMethod.isPublic() || getterMethod.isProtected())) {
             return getterMethod;
@@ -531,7 +528,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     /**
      * Given a method node, checks if we are calling a private method from an inner class.
      */
-    private void checkOrMarkPrivateAccess(Expression source, MethodNode mn) {
+    private void checkOrMarkPrivateAccess(final Expression source, final MethodNode mn) {
         if (mn == null) {
             return;
         }
@@ -559,7 +556,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void checkSuperCallFromClosure(Expression call, MethodNode directCallTarget) {
+    private void checkSuperCallFromClosure(final Expression call, final MethodNode directCallTarget) {
         if (call instanceof MethodCallExpression && typeCheckingContext.getEnclosingClosure() != null) {
             Expression objectExpression = ((MethodCallExpression) call).getObjectExpression();
             if (isSuperExpression(objectExpression)) {
@@ -571,9 +568,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * wrap type in Class&lt;&gt; if usingClass==true
+     * Wrap type in Class&lt;&gt; if usingClass==true.
      */
-    private static ClassNode makeType(ClassNode cn, boolean usingClass) {
+    private static ClassNode makeType(final ClassNode cn, final boolean usingClass) {
         if (usingClass) {
             ClassNode clazzType = CLASS_Type.getPlainNodeReference();
             clazzType.setGenericsTypes(new GenericsType[]{new GenericsType(cn)});
@@ -583,7 +580,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private boolean storeTypeForThis(VariableExpression vexp) {
+    private boolean storeTypeForThis(final VariableExpression vexp) {
         if (vexp == VariableExpression.THIS_EXPRESSION) return true;
         if (!vexp.isThisExpression()) return false;
         ClassNode enclosingClassNode = typeCheckingContext.getEnclosingClassNode();
@@ -591,7 +588,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return true;
     }
 
-    private boolean storeTypeForSuper(VariableExpression vexp) {
+    private boolean storeTypeForSuper(final VariableExpression vexp) {
         if (vexp == VariableExpression.SUPER_EXPRESSION) return true;
         if (!vexp.isSuperExpression()) return false;
         ClassNode superClassNode = typeCheckingContext.getEnclosingClassNode().getSuperClass();
@@ -600,12 +597,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitVariableExpression(VariableExpression vexp) {
+    public void visitVariableExpression(final VariableExpression vexp) {
         super.visitVariableExpression(vexp);
 
         if (storeTypeForThis(vexp)) return;
         if (storeTypeForSuper(vexp)) return;
-        final Variable accessedVariable = vexp.getAccessedVariable();
+        Variable accessedVariable = vexp.getAccessedVariable();
         if (accessedVariable instanceof PropertyNode) {
             // we must be careful, because the property node may be of a wrong type:
             // if a class contains a getter and a setter of different types or
@@ -649,11 +646,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
-            ClassNode actualType =
-                    findActualTypeByGenericsPlaceholderName(
-                            fieldNode.getOriginType().getUnresolvedName(),
-                            makeDeclaringAndActualGenericsTypeMap(fieldNode.getDeclaringClass(), typeCheckingContext.getEnclosingClassNode())
-                    );
+            ClassNode actualType = findActualTypeByGenericsPlaceholderName(
+                    fieldNode.getOriginType().getUnresolvedName(),
+                    makeDeclaringAndActualGenericsTypeMap(fieldNode.getDeclaringClass(), typeCheckingContext.getEnclosingClassNode())
+            );
 
             if (actualType != null) {
                 storeType(vexp, actualType);
@@ -683,35 +679,31 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         }
 
-        if (!(accessedVariable instanceof DynamicVariable)) {
-            if (typeCheckingContext.getEnclosingClosure() == null) {
-                VariableExpression variable = null;
-                if (accessedVariable instanceof Parameter) {
-                    variable = new ParameterVariableExpression((Parameter) accessedVariable);
-                } else if (accessedVariable instanceof VariableExpression) {
-                    variable = (VariableExpression) accessedVariable;
-                }
+        if (accessedVariable instanceof DynamicVariable) {
+            // a dynamic variable is either an undeclared variable
+            // or a member of a class used in a 'with'
+            DynamicVariable dyn = (DynamicVariable) accessedVariable;
+            // first, we must check the 'with' context
+            String dynName = dyn.getName();
+            if (tryVariableExpressionAsProperty(vexp, dynName)) return;
 
-                if (variable != null) {
-                    ClassNode inferredType = getInferredTypeFromTempInfo(variable, variable.getNodeMetaData(INFERRED_TYPE));
-                    // instanceof applies, stash away the type, reusing key used elsewhere
-                    if (inferredType != null && !inferredType.getName().equals("java.lang.Object")) {
-                        vexp.putNodeMetaData(INFERRED_RETURN_TYPE, inferredType);
-                    }
+            if (!extension.handleUnresolvedVariableExpression(vexp)) {
+                addStaticTypeError("The variable [" + vexp.getName() + "] is undeclared.", vexp);
+            }
+        } else if (enclosingClosure == null) {
+            VariableExpression variable = null;
+            if (accessedVariable instanceof Parameter) {
+                variable = new ParameterVariableExpression((Parameter) accessedVariable);
+            } else if (accessedVariable instanceof VariableExpression) {
+                variable = (VariableExpression) accessedVariable;
+            }
+            if (variable != null) {
+                ClassNode inferredType = getInferredTypeFromTempInfo(variable, variable.getNodeMetaData(INFERRED_TYPE));
+                // instanceof applies, stash away the type, reusing key used elsewhere
+                if (inferredType != null && !inferredType.equals(OBJECT_TYPE)) {
+                    vexp.putNodeMetaData(INFERRED_RETURN_TYPE, inferredType);
                 }
             }
-            return;
-        }
-
-        // a dynamic variable is either an undeclared variable
-        // or a member of a class used in a 'with'
-        DynamicVariable dyn = (DynamicVariable) accessedVariable;
-        // first, we must check the 'with' context
-        String dynName = dyn.getName();
-        if (tryVariableExpressionAsProperty(vexp, dynName)) return;
-
-        if (!extension.handleUnresolvedVariableExpression(vexp)) {
-            addStaticTypeError("The variable [" + vexp.getName() + "] is undeclared.", vexp);
         }
     }
 
@@ -745,8 +737,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         if (!extension.handleUnresolvedProperty(pexp)) {
             Expression objectExpression = pexp.getObjectExpression();
-            addStaticTypeError("No such property: " + pexp.getPropertyAsString() +
-                    " for class: " + findCurrentInstanceOfClass(objectExpression, getType(objectExpression)).toString(false), pexp);
+            addStaticTypeError("No such property: " + pexp.getPropertyAsString() + " for class: " +
+                    findCurrentInstanceOfClass(objectExpression, getType(objectExpression)).toString(false), pexp);
         }
     }
 
@@ -760,8 +752,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         super.visitAttributeExpression(expression);
         if (!existsProperty(expression, true) && !extension.handleUnresolvedAttribute(expression)) {
             Expression objectExpression = expression.getObjectExpression();
-            addStaticTypeError("No such property: " + expression.getPropertyAsString() +
-                    " for class: " + findCurrentInstanceOfClass(objectExpression, objectExpression.getType()), expression);
+            addStaticTypeError("No such property: " + expression.getPropertyAsString() + " for class: " +
+                    findCurrentInstanceOfClass(objectExpression, objectExpression.getType()), expression);
         }
     }
 
@@ -781,11 +773,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitBinaryExpression(final BinaryExpression expression) {
+        boolean isAssignment = expression.getOperation().isA(ASSIGNMENT_OPERATOR);
+
         BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
         typeCheckingContext.pushEnclosingBinaryExpression(expression);
         try {
-            final Expression leftExpression = expression.getLeftExpression();
-            final Expression rightExpression = expression.getRightExpression();
+            Expression leftExpression = expression.getLeftExpression();
+            Expression rightExpression = expression.getRightExpression();
             int op = expression.getOperation().getType();
             leftExpression.visit(this);
             SetterInfo setterInfo = removeSetterInfo(leftExpression);
@@ -794,13 +788,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (ensureValidSetter(expression, leftExpression, rightExpression, setterInfo)) {
                     return;
                 }
-
             } else {
                 lType = getType(leftExpression);
 
                 Expression constructedRightExpression = rightExpression;
 
-                boolean isMethodRefRHS = rightExpression instanceof MethodReferenceExpression && isFunctionalInterface(lType);
+                boolean isMethodRefRHS = (rightExpression instanceof MethodReferenceExpression && isFunctionalInterface(lType));
                 if (isMethodRefRHS) {
                     constructedRightExpression = constructLambdaExpressionForMethodReference(lType);
                 }
@@ -809,25 +802,21 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
                 if (isMethodRefRHS) {
                     LambdaExpression lambdaExpression = (LambdaExpression) constructedRightExpression;
-                    ClassNode[] argumentTypes =
-                            Arrays.stream(lambdaExpression.getParameters())
-                                    .map(Parameter::getType)
-                                    .toArray(ClassNode[]::new);
-
-                    rightExpression.putNodeMetaData(CLOSURE_ARGUMENTS, argumentTypes);
                     rightExpression.putNodeMetaData(CONSTRUCTED_LAMBDA_EXPRESSION, lambdaExpression);
+                    rightExpression.putNodeMetaData(CLOSURE_ARGUMENTS,
+                            Arrays.stream(lambdaExpression.getParameters()).map(Parameter::getType).toArray(ClassNode[]::new));
                 }
 
                 rightExpression.visit(this);
             }
 
             if (lType == null) lType = getType(leftExpression);
+            ClassNode rType = (isNullConstant(rightExpression) && !isPrimitiveType(lType)
+                    // primitive types should be ignored as they will result in another failure
+                    ? UNKNOWN_PARAMETER_TYPE
+                    : getType(rightExpression)
+            );
 
-            ClassNode rType = getType(rightExpression);
-            if (isNullConstant(rightExpression)) {
-                if (!isPrimitiveType(lType))
-                    rType = UNKNOWN_PARAMETER_TYPE; // primitive types should be ignored as they will result in another failure
-            }
             BinaryExpression reversedBinaryExpression = binX(rightExpression, expression.getOperation(), leftExpression);
             ClassNode resultType = (op == KEYWORD_IN || op == COMPARE_NOT_IN)
                     ? getResultType(rType, op, lType, reversedBinaryExpression)
@@ -862,7 +851,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
-            if (lType.isUsingGenerics() && missesGenericsTypes(resultType) && isAssignment(op)) {
+            if (isAssignment && lType.isUsingGenerics() && missesGenericsTypes(resultType)) {
                 // unchecked assignment
                 // examples:
                 // List<A> list = []
@@ -895,8 +884,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
-            boolean isEmptyDeclaration = expression instanceof DeclarationExpression && rightExpression instanceof EmptyExpression;
-            if (!isEmptyDeclaration && isAssignment(op)) {
+            boolean isEmptyDeclaration = (expression instanceof DeclarationExpression && rightExpression instanceof EmptyExpression);
+            if (isAssignment && !isEmptyDeclaration) {
                 if (rightExpression instanceof ConstructorCallExpression) {
                     inferDiamondType((ConstructorCallExpression) rightExpression, lType);
                 }
@@ -941,21 +930,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 // if right expression is a ClosureExpression, store parameter type information
                 if (leftExpression instanceof VariableExpression) {
                     if (rightExpression instanceof ClosureExpression) {
-                        Parameter[] parameters = ((ClosureExpression) rightExpression).getParameters();
-                        leftExpression.putNodeMetaData(CLOSURE_ARGUMENTS, parameters);
-                    } else if (rightExpression instanceof VariableExpression &&
-                            ((VariableExpression) rightExpression).getAccessedVariable() instanceof Expression &&
-                            ((Expression) ((VariableExpression) rightExpression).getAccessedVariable()).getNodeMetaData(CLOSURE_ARGUMENTS) != null) {
+                        leftExpression.putNodeMetaData(CLOSURE_ARGUMENTS, ((ClosureExpression) rightExpression).getParameters());
+                    } else if (rightExpression instanceof VariableExpression
+                            && ((VariableExpression) rightExpression).getAccessedVariable() instanceof Expression
+                            && ((Expression) ((VariableExpression) rightExpression).getAccessedVariable()).getNodeMetaData(CLOSURE_ARGUMENTS) != null) {
                         Variable targetVariable = findTargetVariable((VariableExpression) leftExpression);
                         if (targetVariable instanceof ASTNode) {
-                            ((ASTNode) targetVariable).putNodeMetaData(
-                                    CLOSURE_ARGUMENTS,
-                                    ((Expression) ((VariableExpression) rightExpression).getAccessedVariable()).getNodeMetaData(CLOSURE_ARGUMENTS));
+                            ((ASTNode) targetVariable).putNodeMetaData(CLOSURE_ARGUMENTS, ((Expression) ((VariableExpression) rightExpression).getAccessedVariable()).getNodeMetaData(CLOSURE_ARGUMENTS));
                         }
                     }
                 }
-
-
             } else if (op == KEYWORD_INSTANCEOF /*|| op == COMPARE_NOT_INSTANCEOF*/) {
                 pushInstanceOfTypeInfo(leftExpression, rightExpression);
             }
@@ -969,7 +953,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void validateResourceInARM(BinaryExpression expression, ClassNode lType) {
+    private void validateResourceInARM(final BinaryExpression expression, final ClassNode lType) {
         if (expression instanceof DeclarationExpression) {
             if (TryCatchStatement.isResource(expression)) {
                 if (!lType.implementsInterface(AUTOCLOSEABLE_TYPE)) {
@@ -979,7 +963,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void inferParameterAndReturnTypesOfClosureOnRHS(ClassNode lType, Expression rightExpression, int op) {
+    private void inferParameterAndReturnTypesOfClosureOnRHS(final ClassNode lType, final Expression rightExpression, final int op) {
         if (ASSIGN == op) {
             if (rightExpression instanceof ClosureExpression && isFunctionalInterface(lType)) {
                 Tuple2<ClassNode[], ClassNode> typeInfo = GenericsUtils.parameterizeSAM(lType);
@@ -1005,8 +989,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * Given a binary expression corresponding to an assignment, will check that the type of the RHS matches one
-     * of the possible setters and if not, throw a type checking error.
+     * Given a binary expression corresponding to an assignment, will check that
+     * the type of the RHS matches one of the possible setters and if not, throw
+     * a type checking error.
      *
      * @param expression      the assignment expression
      * @param leftExpression  left expression of the assignment
@@ -1060,20 +1045,20 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return false;
     }
 
-    private boolean isCompoundAssignment(Expression exp) {
+    private boolean isCompoundAssignment(final Expression exp) {
         if (!(exp instanceof BinaryExpression)) return false;
         int type = ((BinaryExpression) exp).getOperation().getType();
         return isAssignment(type) && type != ASSIGN;
     }
 
-    private Token getOpWithoutEqual(Expression exp) {
+    private Token getOpWithoutEqual(final Expression exp) {
         if (!(exp instanceof BinaryExpression)) return null; // should never happen
         Token op = ((BinaryExpression) exp).getOperation();
         int typeWithoutEqual = TokenUtil.removeAssignment(op.getType());
         return new Token(typeWithoutEqual, op.getText() /* will do */, op.getStartLine(), op.getStartColumn());
     }
 
-    protected ClassNode getOriginalDeclarationType(Expression lhs) {
+    protected ClassNode getOriginalDeclarationType(final Expression lhs) {
         if (lhs instanceof VariableExpression) {
             Variable var = findTargetVariable((VariableExpression) lhs);
             if (var instanceof PropertyNode) {
@@ -1107,7 +1092,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void adjustGenerics(ClassNode from, ClassNode to) {
+    private void adjustGenerics(final ClassNode from, final ClassNode to) {
         GenericsType[] genericsTypes = from.getGenericsTypes();
         if (genericsTypes == null) {
             // case of: def foo = new HashMap<>()
@@ -1126,19 +1111,18 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * Stores information about types when [objectOfInstanceof instanceof typeExpression] is visited
+     * Stores information about types when [objectOfInstanceof instanceof typeExpression] is visited.
      *
      * @param objectOfInstanceOf the expression which must be checked against instanceof
      * @param typeExpression     the expression which represents the target type
      */
     protected void pushInstanceOfTypeInfo(final Expression objectOfInstanceOf, final Expression typeExpression) {
-        Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.peek();
-        Object key = extractTemporaryTypeInfoKey(objectOfInstanceOf);
-        List<ClassNode> potentialTypes = tempo.computeIfAbsent(key, k -> new LinkedList<>());
+        List<ClassNode> potentialTypes = typeCheckingContext.temporaryIfBranchTypeInformation.peek()
+            .computeIfAbsent(extractTemporaryTypeInfoKey(objectOfInstanceOf), key -> new LinkedList<>());
         potentialTypes.add(typeExpression.getType());
     }
 
-    private boolean typeCheckMultipleAssignmentAndContinue(Expression leftExpression, Expression rightExpression) {
+    private boolean typeCheckMultipleAssignmentAndContinue(final Expression leftExpression, Expression rightExpression) {
         // multiple assignment check
         if (!(leftExpression instanceof TupleExpression)) return true;
 
@@ -1174,7 +1158,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return true;
     }
 
-    private Expression transformRightExpressionToSupportMultipleAssignment(Expression rightExpression) {
+    private Expression transformRightExpressionToSupportMultipleAssignment(final Expression rightExpression) {
         if (rightExpression instanceof ListExpression) {
             return rightExpression;
         }
@@ -1212,7 +1196,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private static ClassNode adjustTypeForSpreading(ClassNode inferredRightExpressionType, Expression leftExpression) {
+    private static ClassNode adjustTypeForSpreading(final ClassNode inferredRightExpressionType, final Expression leftExpression) {
         // imagine we have: list*.foo = 100
         // then the assignment must be checked against [100], not 100
         ClassNode wrappedRHS = inferredRightExpressionType;
@@ -1225,7 +1209,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return wrappedRHS;
     }
 
-    private boolean addedReadOnlyPropertyError(Expression expr) {
+    private boolean addedReadOnlyPropertyError(final Expression expr) {
         // if expr is of READONLY_PROPERTY_RETURN type, then it means we are on a missing property
         if (expr.getNodeMetaData(READONLY_PROPERTY) == null) return false;
         String name;
@@ -1238,7 +1222,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return true;
     }
 
-    private void addPrecisionErrors(ClassNode leftRedirect, ClassNode lhsType, ClassNode inferredrhsType, Expression rightExpression) {
+    private void addPrecisionErrors(final ClassNode leftRedirect, final ClassNode lhsType, final ClassNode inferredrhsType, final Expression rightExpression) {
         if (isNumberType(leftRedirect) && isNumberType(inferredrhsType)) {
             if (checkPossibleLossOfPrecision(leftRedirect, inferredrhsType, rightExpression)) {
                 addStaticTypeError("Possible loss of precision from " + inferredrhsType + " to " + leftRedirect, rightExpression);
@@ -1265,10 +1249,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void addListAssignmentConstructorErrors(
-            ClassNode leftRedirect, ClassNode leftExpressionType,
-            ClassNode inferredRightExpressionType, Expression rightExpression,
-            Expression assignmentExpression) {
+    private void addListAssignmentConstructorErrors(final ClassNode leftRedirect, final ClassNode leftExpressionType, final ClassNode inferredRightExpressionType, final Expression rightExpression, final Expression assignmentExpression) {
         // if left type is not a list but right type is a list, then we're in the case of a groovy
         // constructor type : Dimension d = [100,200]
         // In that case, more checks can be performed
@@ -1288,7 +1269,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void addMapAssignmentConstructorErrors(ClassNode leftRedirect, Expression leftExpression, Expression rightExpression) {
+    private void addMapAssignmentConstructorErrors(final ClassNode leftRedirect, final Expression leftExpression, final Expression rightExpression) {
         // if left type is not a list but right type is a map, then we're in the case of a groovy
         // constructor type : A a = [x:2, y:3]
         // In this case, more checks can be performed
@@ -1304,7 +1285,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void checkTypeGenerics(ClassNode leftExpressionType, ClassNode wrappedRHS, Expression rightExpression) {
+    private void checkTypeGenerics(final ClassNode leftExpressionType, final ClassNode wrappedRHS, final Expression rightExpression) {
         // last, check generic type information to ensure that inferred types are compatible
         if (!leftExpressionType.isUsingGenerics()) return;
         // List<Foo> l = new List() is an example for incomplete generics type info
@@ -1321,7 +1302,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 + " to: " + leftExpressionType.toString(false), rightExpression);
     }
 
-    private boolean hasGStringStringError(ClassNode leftExpressionType, ClassNode wrappedRHS, Expression rightExpression) {
+    private boolean hasGStringStringError(final ClassNode leftExpressionType, final ClassNode wrappedRHS, final Expression rightExpression) {
         if (isParameterizedWithString(leftExpressionType) && isParameterizedWithGStringOrGStringString(wrappedRHS)) {
             addStaticTypeError("You are trying to use a GString in place of a String in a type which explicitly declares accepting String. " +
                     "Make sure to call toString() on all GString values.", rightExpression);
@@ -1330,12 +1311,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return false;
     }
 
-    protected void typeCheckAssignment(
-            final BinaryExpression assignmentExpression,
-            final Expression leftExpression,
-            final ClassNode leftExpressionType,
-            final Expression rightExpression,
-            final ClassNode inferredRightExpressionTypeOrig) {
+    protected void typeCheckAssignment(final BinaryExpression assignmentExpression, final Expression leftExpression, final ClassNode leftExpressionType, final Expression rightExpression, final ClassNode inferredRightExpressionTypeOrig) {
         ClassNode inferredRightExpressionType = inferredRightExpressionTypeOrig;
         if (!typeCheckMultipleAssignmentAndContinue(leftExpression, rightExpression)) return;
 
@@ -1414,7 +1390,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * Checks that a constructor style expression is valid regarding the number of arguments and the argument types.
+     * Checks that a constructor style expression is valid regarding the number
+     * of arguments and the argument types.
      *
      * @param node      the class node for which we will try to find a matching constructor
      * @param arguments the constructor arguments
@@ -1426,7 +1403,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * Checks that a constructor style expression is valid regarding the number of arguments and the argument types.
+     * Checks that a constructor style expression is valid regarding the number
+     * of arguments and the argument types.
      *
      * @param node      the class node for which we will try to find a matching constructor
      * @param arguments the constructor arguments
@@ -1458,8 +1436,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * When instanceof checks are found in the code, we store temporary type information data in the {@link
-     * TypeCheckingContext#temporaryIfBranchTypeInformation} table. This method computes the key which must be used to store this type
+     * When instanceof checks are found in the code, we store temporary type
+     * information data in the {@link TypeCheckingContext#temporaryIfBranchTypeInformation}
+     * table. This method computes the key which must be used to store this type
      * info.
      *
      * @param expression the expression for which to compute the key
@@ -1726,7 +1705,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return foundGetterOrSetter;
     }
 
-    private static boolean hasAccessToField(ClassNode accessor, FieldNode field) {
+    private static boolean hasAccessToField(final ClassNode accessor, final FieldNode field) {
         if (field.isPublic() || accessor.equals(field.getDeclaringClass())) {
             return true;
         }
@@ -1737,7 +1716,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private MethodNode findGetter(ClassNode current, String name, boolean searchOuterClasses) {
+    private MethodNode findGetter(final ClassNode current, String name, final boolean searchOuterClasses) {
         MethodNode getterMethod = current.getGetterMethod(name);
         if (getterMethod == null && searchOuterClasses && current.getOuterClass() != null) {
             return findGetter(current.getOuterClass(), name, true);
@@ -1745,7 +1724,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return getterMethod;
     }
 
-    private ClassNode getTypeForSpreadExpression(ClassNode testClass, ClassNode objectExpressionType, PropertyExpression pexp) {
+    private ClassNode getTypeForSpreadExpression(final ClassNode testClass, final ClassNode objectExpressionType, final PropertyExpression pexp) {
         if (!pexp.isSpreadSafe()) return null;
         MethodCallExpression mce = callX(varX("_", testClass), "iterator", ArgumentListExpression.EMPTY_ARGUMENTS);
         mce.setImplicitThis(false);
@@ -1765,7 +1744,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private ClassNode getTypeForListPropertyExpression(ClassNode testClass, ClassNode objectExpressionType, PropertyExpression pexp) {
+    private ClassNode getTypeForListPropertyExpression(final ClassNode testClass, final ClassNode objectExpressionType, final PropertyExpression pexp) {
         if (!implementsInterfaceOrIsSubclassOf(testClass, LIST_TYPE)) return null;
         ClassNode intf = GenericsUtils.parameterizeType(objectExpressionType, LIST_TYPE.getPlainNodeReference());
         GenericsType[] types = intf.getGenericsTypes();
@@ -1782,7 +1761,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private ClassNode getTypeForMapPropertyExpression(ClassNode testClass, ClassNode objectExpressionType, PropertyExpression pexp) {
+    private ClassNode getTypeForMapPropertyExpression(final ClassNode testClass, final ClassNode objectExpressionType, final PropertyExpression pexp) {
         if (!implementsInterfaceOrIsSubclassOf(testClass, MAP_TYPE)) return null;
         ClassNode intf;
         if (objectExpressionType.getGenericsTypes() != null) {
@@ -1824,7 +1803,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * non-static members is allowed.
      */
     @SuppressWarnings("unchecked")
-    private <T> T allowStaticAccessToMember(T member, boolean staticOnly) {
+    private <T> T allowStaticAccessToMember(final T member, final boolean staticOnly) {
         if (member == null) return null;
         if (!staticOnly) return member;
         boolean isStatic;
@@ -1845,7 +1824,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return member;
     }
 
-    private void storeWithResolve(ClassNode typeToResolve, ClassNode receiver, ClassNode declaringClass, boolean isStatic, PropertyExpression expressionToStoreOn) {
+    private void storeWithResolve(final ClassNode typeToResolve, final ClassNode receiver, final ClassNode declaringClass, final boolean isStatic, final PropertyExpression expressionToStoreOn) {
         ClassNode type = typeToResolve;
         if (getGenericsWithoutArray(type) != null) {
             Map<GenericsTypeName, GenericsType> resolvedPlaceholders = resolvePlaceHoldersFromDeclaration(receiver, declaringClass, null, isStatic);
@@ -1855,7 +1834,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         storeType(expressionToStoreOn, type);
     }
 
-    private boolean storeField(FieldNode field, PropertyExpression expressionToStoreOn, ClassNode receiver, ClassCodeVisitorSupport visitor, String delegationData, boolean lhsOfAssignment) {
+    private boolean storeField(final FieldNode field, final PropertyExpression expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData, final boolean lhsOfAssignment) {
         if (visitor != null) visitor.visitField(field);
         checkOrMarkPrivateAccess(expressionToStoreOn, field, lhsOfAssignment);
         storeWithResolve(field.getOriginType(), receiver, field.getDeclaringClass(), field.isStatic(), expressionToStoreOn);
@@ -1865,7 +1844,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return true;
     }
 
-    private boolean storeProperty(PropertyNode property, PropertyExpression expressionToStoreOn, ClassNode receiver, ClassCodeVisitorSupport visitor, String delegationData) {
+    private boolean storeProperty(final PropertyNode property, final PropertyExpression expressionToStoreOn, final ClassNode receiver, final ClassCodeVisitorSupport visitor, final String delegationData) {
         if (visitor != null) visitor.visitProperty(property);
         storeWithResolve(property.getOriginType(), receiver, property.getDeclaringClass(), property.isStatic(), expressionToStoreOn);
         if (delegationData != null) {
@@ -1877,9 +1856,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected void storeInferredTypeForPropertyExpression(final PropertyExpression pexp, final ClassNode flatInferredType) {
         if (pexp.isSpreadSafe()) {
             ClassNode list = LIST_TYPE.getPlainNodeReference();
-            list.setGenericsTypes(new GenericsType[]{
-                    new GenericsType(flatInferredType)
-            });
+            list.setGenericsTypes(new GenericsType[]{new GenericsType(flatInferredType)});
             storeType(pexp, list);
         } else {
             storeType(pexp, flatInferredType);
@@ -1887,7 +1864,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitProperty(PropertyNode node) {
+    public void visitProperty(final PropertyNode node) {
         final boolean osc = typeCheckingContext.isInStaticContext;
         try {
             typeCheckingContext.isInStaticContext = node.isInStaticContext();
@@ -2028,7 +2005,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
+    public void visitBitwiseNegationExpression(final BitwiseNegationExpression expression) {
         super.visitBitwiseNegationExpression(expression);
         ClassNode type = getType(expression);
         ClassNode typeRe = type.redirect();
@@ -2054,13 +2031,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
+    public void visitUnaryPlusExpression(final UnaryPlusExpression expression) {
         super.visitUnaryPlusExpression(expression);
         negativeOrPositiveUnary(expression, "positive");
     }
 
     @Override
-    public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
+    public void visitUnaryMinusExpression(final UnaryMinusExpression expression) {
         super.visitUnaryMinusExpression(expression);
         negativeOrPositiveUnary(expression, "negative");
     }
@@ -2118,7 +2095,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private static ClassNode getMathWideningClassNode(ClassNode type) {
+    private static ClassNode getMathWideningClassNode(final ClassNode type) {
         if (byte_TYPE.equals(type) || short_TYPE.equals(type) || int_TYPE.equals(type)) {
             return int_TYPE;
         }
@@ -2134,7 +2111,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return type;
     }
 
-    private void negativeOrPositiveUnary(Expression expression, String name) {
+    private void negativeOrPositiveUnary(final Expression expression, final String name) {
         ClassNode type = getType(expression);
         ClassNode typeRe = type.redirect();
         ClassNode resultType;
@@ -2154,7 +2131,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
+    protected void visitConstructorOrMethod(final MethodNode node, final boolean isConstructor) {
         typeCheckingContext.pushEnclosingMethod(node);
         if (!isSkipMode(node) && !shouldSkipMethodNode(node)) {
             super.visitConstructorOrMethod(node, isConstructor);
@@ -2166,12 +2143,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitReturnStatement(ReturnStatement statement) {
+    public void visitReturnStatement(final ReturnStatement statement) {
         super.visitReturnStatement(statement);
         returnListener.returnStatementAdded(statement);
     }
 
-    private ClassNode infer(ClassNode target, ClassNode source) {
+    private ClassNode infer(final ClassNode target, final ClassNode source) {
         DeclarationExpression virtualDecl = new DeclarationExpression(
                 varX("{target}", target),
                 Token.newSymbol(EQUAL, -1, -1),
@@ -2225,12 +2202,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return type;
     }
 
-    protected void addClosureReturnType(ClassNode returnType) {
+    protected void addClosureReturnType(final ClassNode returnType) {
         typeCheckingContext.getEnclosingClosure().addReturnType(returnType);
     }
 
     @Override
-    public void visitConstructorCallExpression(ConstructorCallExpression call) {
+    public void visitConstructorCallExpression(final ConstructorCallExpression call) {
         super.visitConstructorCallExpression(call);
         if (extension.beforeMethodCall(call)) {
             extension.afterMethodCall(call);
@@ -2277,12 +2254,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         extension.afterMethodCall(call);
     }
 
-    private boolean looksLikeNamedArgConstructor(ClassNode receiver, ClassNode[] args) {
+    private boolean looksLikeNamedArgConstructor(final ClassNode receiver, final ClassNode[] args) {
         return (args.length == 1 || args.length == 2 && isInnerConstructor(receiver, args[0]))
                 && implementsInterfaceOrIsSubclassOf(args[args.length - 1], MAP_TYPE);
     }
 
-    private boolean isInnerConstructor(ClassNode receiver, ClassNode parent) {
+    private boolean isInnerConstructor(final ClassNode receiver, final ClassNode parent) {
         return receiver.isRedirectNode() && receiver.redirect() instanceof InnerClassNode &&
                 receiver.redirect().getOuterClass().equals(parent);
     }
@@ -2309,36 +2286,28 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return node;
     }
 
-    protected ClassNode[] getArgumentTypes(ArgumentListExpression args) {
-        List<Expression> arglist = args.getExpressions();
-        ClassNode[] ret = new ClassNode[arglist.size()];
-        for (int i = 0; i < arglist.size(); i++) {
-            Expression exp = arglist.get(i);
-            if (isNullConstant(exp)) {
-                ret[i] = UNKNOWN_PARAMETER_TYPE;
-            } else {
-                ret[i] = getInferredTypeFromTempInfo(exp, getType(exp));
-            }
-        }
-        return ret;
+    protected ClassNode[] getArgumentTypes(final ArgumentListExpression args) {
+        return args.getExpressions().stream().map(exp ->
+            isNullConstant(exp) ? UNKNOWN_PARAMETER_TYPE : getInferredTypeFromTempInfo(exp, getType(exp))
+        ).toArray(ClassNode[]::new);
     }
 
-    private ClassNode getInferredTypeFromTempInfo(Expression exp, ClassNode result) {
-        Map<Object, List<ClassNode>> info = typeCheckingContext.temporaryIfBranchTypeInformation.empty() ? null : typeCheckingContext.temporaryIfBranchTypeInformation.peek();
-        if (exp instanceof VariableExpression && info != null) {
+    private ClassNode getInferredTypeFromTempInfo(final Expression exp, ClassNode result) {
+        if (exp instanceof VariableExpression && !typeCheckingContext.temporaryIfBranchTypeInformation.empty()) {
             List<ClassNode> classNodes = getTemporaryTypesForExpression(exp);
             if (classNodes != null && !classNodes.isEmpty()) {
-                ArrayList<ClassNode> arr = new ArrayList<>(classNodes.size() + 1);
-                if (result != null && !classNodes.contains(result)) arr.add(result);
-                arr.addAll(classNodes);
+                List<ClassNode> types = new ArrayList<>(classNodes.size() + 1);
+                if (result != null && !classNodes.contains(result)) types.add(result);
+                types.addAll(classNodes);
                 // GROOVY-7333: filter out Object
-                arr.removeIf(OBJECT_TYPE::equals);
-                if (arr.isEmpty()) {
+                types.removeIf(OBJECT_TYPE::equals);
+
+                if (types.isEmpty()) {
                     result = OBJECT_TYPE.getPlainNodeReference();
-                } else if (arr.size() == 1) {
-                    result = arr.get(0);
+                } else if (types.size() == 1) {
+                    result = types.get(0);
                 } else {
-                    result = new UnionTypeClassNode(arr.toArray(ClassNode.EMPTY_ARRAY));
+                    result = new UnionTypeClassNode(types.toArray(ClassNode.EMPTY_ARRAY));
                 }
             }
         }
@@ -2351,7 +2320,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         typeCheckingContext.isInStaticContext = false;
 
         // collect every variable expression used in the loop body
-        final Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
+        Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
         Statement code = expression.getCode();
         code.visit(new VariableExpressionTypeMemoizer(varOrigType));
         Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
@@ -2493,7 +2462,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         super.visitConstructor(node);
     }
 
-    protected void startMethodInference(final MethodNode node, ErrorCollector collector) {
+    protected void startMethodInference(final MethodNode node, final ErrorCollector collector) {
         if (isSkipMode(node)) return;
 
         // second, we must ensure that this method MUST be statically checked
@@ -2658,8 +2627,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * visit a method call target, to infer the type. Don't report errors right
-     * away, that will be done by a later visitMethod call
+     * Visits a method call target, to infer the type. Don't report errors right
+     * away, that will be done by a later visitMethod call.
      */
     protected void silentlyVisitMethodNode(final MethodNode directMethodCallCandidate) {
         // visit is authorized because the classnode belongs to the same source unit
@@ -2667,7 +2636,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         startMethodInference(directMethodCallCandidate, collector);
     }
 
-    protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListExpression arguments, boolean visitClosures, final MethodNode selectedMethod) {
+    protected void visitMethodCallArguments(final ClassNode receiver, final ArgumentListExpression arguments, final boolean visitClosures, final MethodNode selectedMethod) {
         Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
         List<Expression> expressions = new LinkedList<>(arguments.getExpressions());
         if (selectedMethod instanceof ExtensionMethodNode) {
@@ -2702,7 +2671,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void checkNamedParamsAnnotation(Parameter param, MapExpression args) {
+    private void checkNamedParamsAnnotation(final Parameter param, final MapExpression args) {
         if (!isOrImplements(param.getType(), MAP_TYPE)) return;
         List<MapEntryExpression> entryExpressions = args.getMapEntryExpressions();
         Map<Object, Expression> entries = new LinkedHashMap<>();
@@ -2743,7 +2712,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void processNamedParam(AnnotationConstantExpression value, Map<Object, Expression> entries, Expression expression, List<String> collectedNames) {
+    private void processNamedParam(final AnnotationConstantExpression value, final Map<Object, Expression> entries, final Expression expression, final List<String> collectedNames) {
         AnnotationNode namedParam = (AnnotationNode) value.getValue();
         if (!namedParam.getClassNode().getName().equals(NamedParam.class.getName())) return;
         String name = null;
@@ -2775,7 +2744,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private boolean isCompatibleType(ClassNode expectedType, boolean b, ClassNode type) {
+    private boolean isCompatibleType(final ClassNode expectedType, final boolean b, final ClassNode type) {
         return b && !isAssignableTo(type, expectedType);
     }
 
@@ -2809,7 +2778,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void inferSAMType(Parameter param, ClassNode receiver, MethodNode methodWithSAMParameter, ArgumentListExpression originalMethodCallArguments, ClosureExpression openBlock) {
+    private void inferSAMType(final Parameter param, final ClassNode receiver, final MethodNode methodWithSAMParameter, final ArgumentListExpression originalMethodCallArguments, final ClosureExpression openBlock) {
         // In a method call with SAM coercion the inference is to be
         // understood as a two phase process. We have the normal method call
         // to the target method with the closure argument and we have the
@@ -2889,9 +2858,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         openBlock.putNodeMetaData(CLOSURE_ARGUMENTS, blockParameterTypes);
     }
 
-    private void tryToInferUnresolvedBlockParameterType(ClassNode paramTypeWithReceiverInformation, MethodNode methodForSAM, ClassNode[] blockParameterTypes) {
+    private void tryToInferUnresolvedBlockParameterType(final ClassNode paramTypeWithReceiverInformation, final MethodNode methodForSAM, final ClassNode[] blockParameterTypes) {
         List<Integer> indexList = new LinkedList<>();
-        for (int i = 0, n = blockParameterTypes.length; i < n; i++) {
+        for (int i = 0, n = blockParameterTypes.length; i < n; i += 1) {
             ClassNode blockParameterType = blockParameterTypes[i];
             if (blockParameterType != null && blockParameterType.isGenericsPlaceHolder()) {
                 indexList.add(i);
@@ -2916,7 +2885,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private ClassNode typeOrNull(ClassNode[] parameterTypesForSAM, int i) {
+    private static ClassNode typeOrNull(final ClassNode[] parameterTypesForSAM, final int i) {
         return i < parameterTypesForSAM.length ? parameterTypesForSAM[i] : null;
     }
 
@@ -2939,7 +2908,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return closureSignatures;
     }
 
-    private List<ClassNode[]> resolveWithResolver(List<ClassNode[]> candidates, ClassNode receiver, Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression resolverClass, final Expression options) {
+    private List<ClassNode[]> resolveWithResolver(final List<ClassNode[]> candidates, final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression resolverClass, final Expression options) {
         // initialize resolver
         try {
             ClassLoader transformLoader = getTransformLoader();
@@ -2965,7 +2934,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return compilationUnit != null ? compilationUnit.getTransformLoader() : getSourceUnit().getClassLoader();
     }
 
-    private void doInferClosureParameterTypes(final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression hintClass, Expression resolverClass, final Expression options) {
+    private void doInferClosureParameterTypes(final ClassNode receiver, final Expression arguments, final ClosureExpression expression, final MethodNode selectedMethod, final Expression hintClass, final Expression resolverClass, final Expression options) {
         List<ClassNode[]> closureSignatures = getSignaturesFromHint(expression, selectedMethod, hintClass, options);
         List<ClassNode[]> candidates = new LinkedList<ClassNode[]>();
         Parameter[] closureParams = expression.getParameters();
@@ -3127,12 +3096,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         throw new IllegalArgumentException("Unexpected options for @ClosureParams:" + options);
     }
 
-    private void checkClosureWithDelegatesTo(final ClassNode receiver,
-                                             final MethodNode mn,
-                                             final ArgumentListExpression arguments,
-                                             final Parameter[] params,
-                                             final Expression expression,
-                                             final Parameter param) {
+    private void checkClosureWithDelegatesTo(final ClassNode receiver, final MethodNode mn, final ArgumentListExpression arguments, final Parameter[] params, final Expression expression, final Parameter param) {
         List<AnnotationNode> annotations = param.getAnnotations(DELEGATES_TO);
         if (annotations != null && !annotations.isEmpty()) {
             for (AnnotationNode annotation : annotations) {
@@ -3220,9 +3184,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    protected void addReceivers(final List<Receiver<String>> receivers,
-                                final Collection<Receiver<String>> owners,
-                                final boolean implicitThis) {
+    protected void addReceivers(final List<Receiver<String>> receivers, final Collection<Receiver<String>> owners, final boolean implicitThis) {
         if (!implicitThis || typeCheckingContext.delegationMetadata == null) {
             receivers.addAll(owners);
         } else {
@@ -3230,10 +3192,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private static void addReceivers(final List<Receiver<String>> receivers,
-                                     final Collection<Receiver<String>> owners,
-                                     final DelegationMetadata dmd,
-                                     final String path) {
+    private static void addReceivers(final List<Receiver<String>> receivers, final Collection<Receiver<String>> owners, final DelegationMetadata dmd, final String path) {
         int strategy = dmd.getStrategy();
         switch (strategy) {
             case Closure.DELEGATE_ONLY:
@@ -3271,8 +3230,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    public void visitMethodCallExpression(MethodCallExpression call) {
-        final String name = call.getMethodAsString();
+    public void visitMethodCallExpression(final MethodCallExpression call) {
+        String name = call.getMethodAsString();
         if (name == null) {
             addStaticTypeError("cannot resolve dynamic method name at compile time.", call.getMethod());
             return;
@@ -3282,7 +3241,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return;
         }
         typeCheckingContext.pushEnclosingMethodCall(call);
-        final Expression objectExpression = call.getObjectExpression();
+        Expression objectExpression = call.getObjectExpression();
 
         objectExpression.visit(this);
         call.getMethod().visit(this);
@@ -3323,11 +3282,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // for arguments, we need to visit closures *after* the method has been chosen
 
 
-        final ClassNode receiver = getType(objectExpression);
+        ClassNode receiver = getType(objectExpression);
         visitMethodCallArguments(receiver, argumentList, false, null);
 
         ClassNode[] args = getArgumentTypes(argumentList);
-        final boolean isCallOnClosure = isClosureCall(name, objectExpression, callArguments);
+        boolean isCallOnClosure = isClosureCall(name, objectExpression, callArguments);
 
         try {
             boolean callArgsVisited = false;
@@ -3548,7 +3507,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private void inferMethodReferenceType(MethodCallExpression call, ClassNode receiver, ArgumentListExpression argumentList) {
+    private void inferMethodReferenceType(final MethodCallExpression call, final ClassNode receiver, final ArgumentListExpression argumentList) {
         if (call == null) return;
         if (receiver == null) return;
         if (argumentList == null) return;
@@ -3599,21 +3558,22 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private LambdaExpression constructLambdaExpressionForMethodReference(ClassNode paramType) {
+    private LambdaExpression constructLambdaExpressionForMethodReference(final ClassNode paramType) {
         Parameter[] newParameters = createParametersForConstructedLambdaExpression(paramType);
         return new LambdaExpression(newParameters, block());
     }
 
-    private Parameter[] createParametersForConstructedLambdaExpression(ClassNode functionalInterfaceType) {
+    private Parameter[] createParametersForConstructedLambdaExpression(final ClassNode functionalInterfaceType) {
         MethodNode abstractMethodNode = findSAM(functionalInterfaceType);
+
         Parameter[] abstractMethodNodeParameters = abstractMethodNode.getParameters();
         if (abstractMethodNodeParameters == null) {
             abstractMethodNodeParameters = Parameter.EMPTY_ARRAY;
         }
 
         Parameter[] newParameters = new Parameter[abstractMethodNodeParameters.length];
-        for (int j = 0; j < newParameters.length; j++) {
-            newParameters[j] = new Parameter(DYNAMIC_TYPE, "p" + System.nanoTime());
+        for (int i = 0; i < newParameters.length; i += 1) {
+            newParameters[i] = new Parameter(DYNAMIC_TYPE, "p" + System.nanoTime());
         }
         return newParameters;
     }
@@ -3649,13 +3609,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     /**
-     * add various getAt and setAt methods for primitive arrays
+     * Adds various getAt and setAt methods for primitive arrays.
      *
      * @param receiver the receiver class
      * @param name     the name of the method
      * @param args     the argument classes
      */
-    private static void addArrayMethods(List<MethodNode> methods, ClassNode receiver, String name, ClassNode[] args) {
+    private static void addArrayMethods(final List<MethodNode> methods, final ClassNode receiver, final String name, final ClassNode[] args) {
         if (args.length != 1) return;
         if (!receiver.isArray()) return;
         if (!isIntCategory(getUnwrapper(args[0]))) return;
@@ -3677,7 +3637,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param callArguments the argument list from the <em>Object#with(Closure)</em> call, ie. a single closure expression
      * @return the inferred closure return type or <em>null</em>
      */
-    protected ClassNode getInferredReturnTypeFromWithClosureArgument(Expression callArguments) {
+    protected ClassNode getInferredReturnTypeFromWithClosureArgument(final Expression callArguments) {
         if (!(callArguments instanceof ArgumentListExpression)) return null;
 
         ArgumentListExpression argList = (ArgumentListExpression) callArguments;
@@ -3699,7 +3659,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @return the list of types the receiver may be
      */
     protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
-        final ClassNode receiver = getType(objectExpression);
+        ClassNode receiver = getType(objectExpression);
         List<Receiver<String>> owners = new LinkedList<>();
         owners.add(Receiver.make(receiver));
         if (isClassClassNodeWrappingConcreteType(receiver)) {
@@ -3742,7 +3702,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    protected void checkForbiddenSpreadArgument(ArgumentListExpression argumentList) {
+    protected void checkForbiddenSpreadArgument(final ArgumentListExpression argumentList) {
         for (Expression arg : argumentList.getExpressions()) {
             if (arg instanceof SpreadExpression) {
                 addStaticTypeError("The spread operator cannot be used as argument of method or closure calls with static type checking because the number of arguments cannot be determined at compile time", arg);
@@ -3754,7 +3714,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         List<ClassNode> classNodes = null;
         int depth = typeCheckingContext.temporaryIfBranchTypeInformation.size();
         while (classNodes == null && depth > 0) {
-            final Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.get(--depth);
+            Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.get(--depth);
             Object key = objectExpression instanceof ParameterVariableExpression
                     ? ((ParameterVariableExpression) objectExpression).parameter
                     : extractTemporaryTypeInfoKey(objectExpression);
@@ -3838,9 +3798,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-
-    protected void visitInstanceofNot(BinaryExpression be) {
-        final BlockStatement currentBlock = typeCheckingContext.enclosingBlocks.getFirst();
+    protected void visitInstanceofNot(final BinaryExpression be) {
+        BlockStatement currentBlock = typeCheckingContext.enclosingBlocks.getFirst();
         assert currentBlock != null;
         if (typeCheckingContext.blockStatements2Types.containsKey(currentBlock)) {
             // another instanceOf_not was before, no need store vars
@@ -3853,9 +3812,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         pushInstanceOfTypeInfo(be.getLeftExpression(), be.getRightExpression());
     }
 
-
     @Override
-    public void visitBlockStatement(BlockStatement block) {
+    public void visitBlockStatement(final BlockStatement block) {
         if (block != null) {
             typeCheckingContext.enclosingBlocks.addFirst(block);
         }
@@ -3865,7 +3823,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    public void visitClosingBlock(BlockStatement block) {
+    public void visitClosingBlock(final BlockStatement block) {
         BlockStatement peekBlock = typeCheckingContext.enclosingBlocks.removeFirst();
         boolean found = typeCheckingContext.blockStatements2Types.containsKey(peekBlock);
         if (found) {
@@ -3886,7 +3844,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * Return expression , which contains instanceOf (without not)
      * Return null, if not found
      */
-    protected BinaryExpression findInstanceOfNotReturnExpression(IfStatement ifElse) {
+    protected BinaryExpression findInstanceOfNotReturnExpression(final IfStatement ifElse) {
         Statement elseBlock = ifElse.getElseBlock();
         if (!(elseBlock instanceof EmptyStatement)) {
             return null;
@@ -3922,7 +3880,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * Return expression , which contains instanceOf (without not)
      * Return null, if not found
      */
-    protected BinaryExpression findNotInstanceOfReturnExpression(IfStatement ifElse) {
+    protected BinaryExpression findNotInstanceOfReturnExpression(final IfStatement ifElse) {
         Statement elseBlock = ifElse.getElseBlock();
         if (!(elseBlock instanceof EmptyStatement)) {
             return null;
@@ -3942,7 +3900,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return instanceOfExpression;
     }
 
-    private boolean notReturningBlock(Statement block) {
+    private boolean notReturningBlock(final Statement block) {
         if (!(block instanceof BlockStatement)) {
             return true;
         }
@@ -3973,7 +3931,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
-    protected void afterSwitchConditionExpressionVisited(SwitchStatement statement) {
+    protected void afterSwitchConditionExpressionVisited(final SwitchStatement statement) {
         Expression conditionExpression = statement.getExpression();
         conditionExpression.putNodeMetaData(TYPE, getType(conditionExpression));
     }
@@ -4035,7 +3993,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         storeType(expression, expression.getType());
     }
 
-    private boolean isDelegateOrOwnerInClosure(Expression exp) {
+    private boolean isDelegateOrOwnerInClosure(final Expression exp) {
         return typeCheckingContext.getEnclosingClosure() != null &&
                 exp instanceof VariableExpression &&
                 (("delegate".equals(((VariableExpression) exp).getName())) || ("owner".equals(((VariableExpression) exp).getName())));
@@ -4150,8 +4108,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private static boolean isEmptyCollection(final Expression expr) {
-        return (expr instanceof ListExpression && ((ListExpression) expr).getExpressions().size() == 0) ||
-                (expr instanceof MapExpression && ((MapExpression) expr).getMapEntryExpressions().size() == 0);
+        return (expr instanceof ListExpression && ((ListExpression) expr).getExpressions().size() == 0)
+                || (expr instanceof MapExpression && ((MapExpression) expr).getMapEntryExpressions().size() == 0);
     }
 
     private static boolean hasInferredReturnType(final Expression expression) {
@@ -4232,7 +4190,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    protected ClassNode getResultType(ClassNode left, int op, ClassNode right, BinaryExpression expr) {
+    protected ClassNode getResultType(ClassNode left, final int op, final ClassNode right, final BinaryExpression expr) {
         ClassNode leftRedirect = left.redirect();
         ClassNode rightRedirect = right.redirect();
 
@@ -4330,7 +4288,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private ClassNode getMathResultType(int op, ClassNode leftRedirect, ClassNode rightRedirect, String operationName) {
+    private ClassNode getMathResultType(final int op, final ClassNode leftRedirect, final ClassNode rightRedirect, final String operationName) {
         if (isNumberType(leftRedirect) && isNumberType(rightRedirect)) {
             if (isOperationInGroup(op)) {
                 if (isIntCategory(leftRedirect) && isIntCategory(rightRedirect)) return int_TYPE;
@@ -4383,7 +4341,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private ClassNode inferSAMTypeGenericsInAssignment(ClassNode samUsage, MethodNode sam, ClassNode closureType, ClosureExpression closureExpression) {
+    private ClassNode inferSAMTypeGenericsInAssignment(final ClassNode samUsage, final MethodNode sam, final ClassNode closureType, final ClosureExpression closureExpression) {
         // if the sam type or closure type do not provide generics information,
         // we cannot infer anything, thus we simply return the provided samUsage
         GenericsType[] samGt = samUsage.getGenericsTypes();
@@ -4409,7 +4367,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return applyGenericsContext(connections, samUsage.redirect());
     }
 
-    protected static ClassNode getGroupOperationResultType(ClassNode a, ClassNode b) {
+    protected static ClassNode getGroupOperationResultType(final ClassNode a, final ClassNode b) {
         if (isBigIntCategory(a) && isBigIntCategory(b)) return BigInteger_TYPE;
         if (isBigDecCategory(a) && isBigDecCategory(b)) return BigDecimal_TYPE;
         if (BigDecimal_TYPE.equals(a) || BigDecimal_TYPE.equals(b)) return BigDecimal_TYPE;
@@ -4453,9 +4411,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    protected MethodNode findMethodOrFail(
-            Expression expr,
-            ClassNode receiver, String name, ClassNode... args) {
+    protected MethodNode findMethodOrFail(final Expression expr, final ClassNode receiver, final String name, final ClassNode... args) {
         List<MethodNode> methods = findMethod(receiver, name, args);
         if (methods.isEmpty() && (expr instanceof BinaryExpression)) {
             BinaryExpression be = (BinaryExpression) expr;
@@ -4478,7 +4434,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return null;
     }
 
-    private List<MethodNode> disambiguateMethods(List<MethodNode> methods, ClassNode receiver, ClassNode[] argTypes, final Expression call) {
+    private List<MethodNode> disambiguateMethods(List<MethodNode> methods, final ClassNode receiver, final ClassNode[] argTypes, final Expression call) {
         if (methods.size() > 1 && receiver != null && argTypes != null) {
             List<MethodNode> filteredWithGenerics = new LinkedList<>();
             for (MethodNode methodNode : methods) {
@@ -4514,7 +4470,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return methods;
     }
 
-    protected static String prettyPrintMethodList(List<MethodNode> nodes) {
+    protected static String prettyPrintMethodList(final List<MethodNode> nodes) {
         StringBuilder sb = new StringBuilder("[");
         for (int i = 0, nodesSize = nodes.size(); i < nodesSize; i++) {
             final MethodNode node = nodes.get(i);
@@ -4553,12 +4509,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param name     the name of the methods to return
      * @return the methods that are defined on the receiver completed with stubs for future methods
      */
-    protected List<MethodNode> findMethodsWithGenerated(ClassNode receiver, String name) {
+    protected List<MethodNode> findMethodsWithGenerated(final ClassNode receiver, final String name) {
         List<MethodNode> methods = receiver.getMethods(name);
         if (methods.isEmpty() || receiver.isResolved()) return methods;
-        List<MethodNode> result = addGeneratedMethods(receiver, methods);
-
-        return result;
+        return addGeneratedMethods(receiver, methods);
     }
 
     private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
@@ -4617,8 +4571,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return result;
     }
 
-    protected List<MethodNode> findMethod(
-            ClassNode receiver, String name, ClassNode... args) {
+    protected List<MethodNode> findMethod(ClassNode receiver, final String name, final ClassNode... args) {
         if (isPrimitiveType(receiver)) receiver = getWrapper(receiver);
         List<MethodNode> methods;
         if (!receiver.isInterface() && "<init>".equals(name)) {
@@ -4757,7 +4710,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return EMPTY_METHODNODE_LIST;
     }
 
-    private List<MethodNode> filterMethodsByVisibility(List<MethodNode> methodNodeList) {
+    private List<MethodNode> filterMethodsByVisibility(final List<MethodNode> methodNodeList) {
         return StaticTypeCheckingSupport.filterMethodsByVisibility(methodNodeList, typeCheckingContext.getEnclosingClassNode());
     }
 
@@ -4771,7 +4724,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param methodName the method name
      * @return a property name if the prefix is found and the method matches the java beans rules, null otherwise
      */
-    public static String extractPropertyNameFromMethodName(String prefix, String methodName) {
+    public static String extractPropertyNameFromMethodName(final String prefix, final String methodName) {
         if (prefix == null || methodName == null) return null;
         if (methodName.startsWith(prefix) && prefix.length() < methodName.length()) {
             String result = methodName.substring(prefix.length());
@@ -4914,7 +4867,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return ((Expression) exp).getType();
     }
 
-    private ClassNode getTypeFromClosureArguments(Parameter parameter, TypeCheckingContext.EnclosingClosure enclosingClosure) {
+    private ClassNode getTypeFromClosureArguments(final Parameter parameter, final TypeCheckingContext.EnclosingClosure enclosingClosure) {
         ClosureExpression closureExpression = enclosingClosure.getClosureExpression();
         ClassNode[] closureParamTypes = closureExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
         if (closureParamTypes == null) return null;
@@ -4944,13 +4897,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param type the origin type
      * @return the new ClassNode with corrected generics
      */
-    private ClassNode getGenericsResolvedTypeOfFieldOrProperty(AnnotatedNode an, ClassNode type) {
+    private ClassNode getGenericsResolvedTypeOfFieldOrProperty(final AnnotatedNode an, final ClassNode type) {
         if (!type.isUsingGenerics()) return type;
         Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         //TODO: inner classes mean a different this-type. This is ignored here!
         extractGenericsConnections(connections, typeCheckingContext.getEnclosingClassNode(), an.getDeclaringClass());
-        type = applyGenericsContext(connections, type);
-        return type;
+        return applyGenericsContext(connections, type);
     }
 
     private ClassNode makeSuper() {
@@ -4975,7 +4927,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return ret;
     }
 
-    private static ClassNode makeSelf(ClassNode trait) {
+    private static ClassNode makeSelf(final ClassNode trait) {
         ClassNode ret = trait;
         LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<>();
         Traits.collectSelfTypes(ret, selfTypes);
@@ -5096,7 +5048,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param arguments the method call arguments
      * @return parameterized, infered, class node
      */
-    protected ClassNode inferReturnTypeGenerics(ClassNode receiver, MethodNode method, Expression arguments) {
+    protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final MethodNode method, final Expression arguments) {
         return inferReturnTypeGenerics(receiver, method, arguments, null);
     }
 
@@ -5111,11 +5063,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param explicitTypeHints explicit type hints as found for example in Collections.&lt;String&gt;emptyList()
      * @return parameterized, infered, class node
      */
-    protected ClassNode inferReturnTypeGenerics(
-            ClassNode receiver,
-            MethodNode method,
-            Expression arguments,
-            GenericsType[] explicitTypeHints) {
+    protected ClassNode inferReturnTypeGenerics(final ClassNode receiver, final MethodNode method, final Expression arguments, final GenericsType[] explicitTypeHints) {
         ClassNode returnType = method.getReturnType();
         if (method instanceof ExtensionMethodNode
                 && (isUsingGenericsOrIsArrayUsingGenerics(returnType))) {
@@ -5319,12 +5267,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return result;
     }
 
-    private ClassNode resolveGenericsWithContext(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, ClassNode currentType) {
+    private ClassNode resolveGenericsWithContext(final Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final ClassNode currentType) {
         Map<GenericsTypeName, GenericsType> placeholdersFromContext = extractGenericsParameterMapOfThis(typeCheckingContext.getEnclosingMethod());
         return resolveClassNodeGenerics(resolvedPlaceholders, placeholdersFromContext, currentType);
     }
 
-    private static ClassNode getDeclaringClass(MethodNode method, Expression arguments) {
+    private static ClassNode getDeclaringClass(final MethodNode method, final Expression arguments) {
         ClassNode declaringClass = method.getDeclaringClass();
 
         // correcting declaring class for extension methods:
@@ -5339,7 +5287,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return declaringClass;
     }
 
-    private Map<GenericsTypeName, GenericsType> resolvePlaceHoldersFromDeclaration(ClassNode receiver, ClassNode declaration, MethodNode method, boolean isStaticTarget) {
+    private Map<GenericsTypeName, GenericsType> resolvePlaceHoldersFromDeclaration(final ClassNode receiver, final ClassNode declaration, final MethodNode method, final boolean isStaticTarget) {
         Map<GenericsTypeName, GenericsType> resolvedPlaceholders;
         if (isStaticTarget && CLASS_Type.equals(receiver) &&
                 receiver.isUsingGenerics() &&
@@ -5352,12 +5300,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return resolvedPlaceholders;
     }
 
-    private static boolean isGenericsPlaceHolderOrArrayOf(ClassNode cn) {
+    private static boolean isGenericsPlaceHolderOrArrayOf(final ClassNode cn) {
         if (cn.isArray()) return isGenericsPlaceHolderOrArrayOf(cn.getComponentType());
         return cn.isGenericsPlaceHolder();
     }
 
-    private static Map<GenericsTypeName, GenericsType> extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode declaringClass) {
+    private static Map<GenericsTypeName, GenericsType> extractPlaceHolders(final MethodNode method, ClassNode receiver, final ClassNode declaringClass) {
         if (declaringClass.equals(OBJECT_TYPE)) {
             Map<GenericsTypeName, GenericsType> resolvedPlaceholders = new HashMap<>();
             if (method != null) addMethodLevelDeclaredGenerics(method, resolvedPlaceholders);
@@ -5424,7 +5372,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return resolvedPlaceholders;
     }
 
-    protected boolean typeCheckMethodsWithGenericsOrFail(ClassNode receiver, ClassNode[] arguments, MethodNode candidateMethod, Expression location) {
+    protected boolean typeCheckMethodsWithGenericsOrFail(final ClassNode receiver, final ClassNode[] arguments, final MethodNode candidateMethod, final Expression location) {
         if (!typeCheckMethodsWithGenerics(receiver, arguments, candidateMethod)) {
             Map<GenericsTypeName, GenericsType> classGTs = GenericsUtils.extractPlaceholders(receiver);
             ClassNode[] ptypes = new ClassNode[candidateMethod.getParameters().length];
@@ -5442,16 +5390,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return true;
     }
 
-    private static String toMethodGenericTypesString(MethodNode node) {
+    private static String toMethodGenericTypesString(final MethodNode node) {
         GenericsType[] genericsTypes = node.getGenericsTypes();
-
-        if (genericsTypes == null)
-            return "";
-
+        if (genericsTypes == null) return "";
         return toGenericTypesString(genericsTypes);
     }
 
-    protected static String formatArgumentList(ClassNode[] nodes) {
+    protected static String formatArgumentList(final ClassNode[] nodes) {
         if (nodes == null || nodes.length == 0) return "[]";
         StringBuilder sb = new StringBuilder(24 * nodes.length);
         sb.append("[");
@@ -5465,11 +5410,11 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return sb.toString();
     }
 
-    private static void putSetterInfo(Expression exp, SetterInfo info) {
+    private static void putSetterInfo(final Expression exp, final SetterInfo info) {
         exp.putNodeMetaData(SetterInfo.class, info);
     }
 
-    private static SetterInfo removeSetterInfo(Expression exp) {
+    private static SetterInfo removeSetterInfo(final Expression exp) {
         Object nodeMetaData = exp.getNodeMetaData(SetterInfo.class);
         if (nodeMetaData != null) {
             exp.removeNodeMetaData(SetterInfo.class);
@@ -5597,11 +5542,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected static ClassNode[] extractTypesFromParameters(final Parameter[] parameters) {
-        ClassNode[] params = new ClassNode[parameters.length];
-        for (int i = 0; i < params.length; i++) {
-            params[i] = parameters[i].getType();
-        }
-        return params;
+        return Arrays.stream(parameters).map(Parameter::getType).toArray(ClassNode[]::new);
     }
 
     /**
@@ -5611,12 +5552,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      *
      * @return the wrapped type
      */
-    protected static ClassNode wrapTypeIfNecessary(ClassNode type) {
+    protected static ClassNode wrapTypeIfNecessary(final ClassNode type) {
         if (isPrimitiveType(type)) return getWrapper(type);
         return type;
     }
 
-    protected static boolean isClassInnerClassOrEqualTo(ClassNode toBeChecked, ClassNode start) {
+    protected static boolean isClassInnerClassOrEqualTo(final ClassNode toBeChecked, final ClassNode start) {
         if (start == toBeChecked) return true;
         ClassNode outer = start.getOuterClass();
         if (outer != null) {
@@ -5625,33 +5566,10 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         return false;
     }
 
-    protected class VariableExpressionTypeMemoizer extends ClassCodeVisitorSupport {
-        private final Map<VariableExpression, ClassNode> varOrigType;
-
-        public VariableExpressionTypeMemoizer(final Map<VariableExpression, ClassNode> varOrigType) {
-            this.varOrigType = varOrigType;
-        }
-
-        @Override
-        protected SourceUnit getSourceUnit() {
-            return typeCheckingContext.source;
-        }
-
-        @Override
-        public void visitVariableExpression(final VariableExpression expression) {
-            super.visitVariableExpression(expression);
-            Variable var = findTargetVariable(expression);
-            if (var instanceof VariableExpression) {
-                VariableExpression ve = (VariableExpression) var;
-                varOrigType.put(ve, ve.getNodeMetaData(INFERRED_TYPE));
-            }
-        }
-    }
-
-    // ------------------- codecs for method return type signatures ------------------------------
+    //--------------------------------------------------------------------------
 
     public static class SignatureCodecFactory {
-        public static SignatureCodec getCodec(int version, final ClassLoader classLoader) {
+        public static SignatureCodec getCodec(final int version, final ClassLoader classLoader) {
             switch (version) {
                 case 1:
                     return new SignatureCodecVersion1(classLoader);
@@ -5687,7 +5605,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         private final Parameter parameter;
 
-        ParameterVariableExpression(Parameter parameter) {
+        ParameterVariableExpression(final Parameter parameter) {
             super(parameter);
             this.parameter = parameter;
             ClassNode inferred = parameter.getNodeMetaData(INFERRED_TYPE);
@@ -5698,18 +5616,37 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         }
 
+        private static ClassNode infer(final Variable variable) {
+            ClassNode originType = variable.getOriginType();
+
+            if (originType.isGenericsPlaceHolder()) {
+                GenericsType[] genericsTypes = originType.getGenericsTypes();
+
+                if (genericsTypes != null && genericsTypes.length > 0) {
+                    GenericsType gt = genericsTypes[0];
+                    ClassNode[] upperBounds = gt.getUpperBounds();
+
+                    if (upperBounds != null && upperBounds.length > 0) {
+                        return upperBounds[0];
+                    }
+                }
+            }
+
+            return originType;
+        }
+
         @Override
-        public void copyNodeMetaData(ASTNode other) {
+        public void copyNodeMetaData(final ASTNode other) {
             parameter.copyNodeMetaData(other);
         }
 
         @Override
-        public Object putNodeMetaData(Object key, Object value) {
+        public Object putNodeMetaData(final Object key, final Object value) {
             return parameter.putNodeMetaData(key, value);
         }
 
         @Override
-        public void removeNodeMetaData(Object key) {
+        public void removeNodeMetaData(final Object key) {
             parameter.removeNodeMetaData(key);
         }
 
@@ -5719,12 +5656,12 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
 
         @Override
-        public <T> T getNodeMetaData(Object key) {
+        public <T> T getNodeMetaData(final Object key) {
             return parameter.getNodeMetaData(key);
         }
 
         @Override
-        public void setNodeMetaData(Object key, Object value) {
+        public void setNodeMetaData(final Object key, final Object value) {
             parameter.setNodeMetaData(key, value);
         }
 
@@ -5734,27 +5671,31 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
 
         @Override
-        public boolean equals(Object other) {
+        public boolean equals(final Object other) {
             return parameter.equals(other);
         }
     }
 
-    private static ClassNode infer(Variable variable) {
-        ClassNode originType = variable.getOriginType();
+    protected class VariableExpressionTypeMemoizer extends ClassCodeVisitorSupport {
+        private final Map<VariableExpression, ClassNode> varOrigType;
 
-        if (originType.isGenericsPlaceHolder()) {
-            GenericsType[] genericsTypes = originType.getGenericsTypes();
+        public VariableExpressionTypeMemoizer(final Map<VariableExpression, ClassNode> varOrigType) {
+            this.varOrigType = varOrigType;
+        }
 
-            if (genericsTypes != null && genericsTypes.length > 0) {
-                GenericsType gt = genericsTypes[0];
-                ClassNode[] upperBounds = gt.getUpperBounds();
+        @Override
+        protected SourceUnit getSourceUnit() {
+            return typeCheckingContext.source;
+        }
 
-                if (upperBounds != null && upperBounds.length > 0) {
-                    return upperBounds[0];
-                }
+        @Override
+        public void visitVariableExpression(final VariableExpression expression) {
+            super.visitVariableExpression(expression);
+            Variable var = findTargetVariable(expression);
+            if (var instanceof VariableExpression) {
+                VariableExpression ve = (VariableExpression) var;
+                varOrigType.put(ve, ve.getNodeMetaData(INFERRED_TYPE));
             }
         }
-
-        return originType;
     }
 }


[groovy] 03/18: fixed style issues

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

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

commit 2ebfe812418cfc0056b2c5578e3fd059fd6c0335
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 11:48:54 2019 -0600

    fixed style issues
    
    (cherry picked from commit cedef0b2436901993c61edab115f03765fe24f21)
---
 .../codehaus/groovy/reflection/CachedClass.java    | 191 ++++++++++-----------
 .../org/codehaus/groovy/reflection/ClassInfo.java  |  72 ++++----
 2 files changed, 123 insertions(+), 140 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
index 9e26796..5752836 100644
--- a/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
+++ b/src/main/java/org/codehaus/groovy/reflection/CachedClass.java
@@ -31,9 +31,6 @@ import org.codehaus.groovy.util.FastArray;
 import org.codehaus.groovy.util.LazyReference;
 import org.codehaus.groovy.util.ReferenceBundle;
 
-import java.lang.reflect.Constructor;
-import java.lang.reflect.Field;
-import java.lang.reflect.Method;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
@@ -43,159 +40,139 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import static org.codehaus.groovy.reflection.ReflectionUtils.checkCanSetAccessible;
 
-
 public class CachedClass {
-    private static final Method[] EMPTY_METHOD_ARRAY = new Method[0];
-    private final Class cachedClass;
-    public ClassInfo classInfo;
-    
+
+    public static final CachedClass[] EMPTY_ARRAY = new CachedClass[0];
+
     private static ReferenceBundle softBundle = ReferenceBundle.getSoftBundle();
 
     private final LazyReference<CachedField[]> fields = new LazyReference<CachedField[]>(softBundle) {
         private static final long serialVersionUID = 5450437842165410025L;
 
+        @Override
         public CachedField[] initValue() {
-            final Field[] declaredFields = AccessController.doPrivileged((PrivilegedAction<Field[]>) () -> {
-                Field[] df = getTheClass().getDeclaredFields();
-                return Arrays.stream(df)
-                        .filter(f -> checkCanSetAccessible(f, CachedClass.class))
-                        .toArray(Field[]::new);
-            });
-            CachedField[] fields = new CachedField[declaredFields.length];
-            for (int i = 0; i != fields.length; ++i)
-                fields[i] = new CachedField(declaredFields[i]);
-            return fields;
+            PrivilegedAction<CachedField[]> action = () -> {
+                return Arrays.stream(getTheClass().getDeclaredFields())
+                    .filter(f -> checkCanSetAccessible(f, CachedClass.class))
+                    .map(CachedField::new).toArray(CachedField[]::new);
+            };
+            return AccessController.doPrivileged(action);
         }
     };
 
     private LazyReference<CachedConstructor[]> constructors = new LazyReference<CachedConstructor[]>(softBundle) {
         private static final long serialVersionUID = -5834446523983631635L;
 
+        @Override
         public CachedConstructor[] initValue() {
-            final Constructor[] declaredConstructors = AccessController.doPrivileged((PrivilegedAction<Constructor[]>) () -> {
-                Constructor[] dc = getTheClass().getDeclaredConstructors();
-                return Arrays.stream(dc)
-                        .filter(c -> checkCanSetAccessible(c, CachedClass.class))
-                        .toArray(Constructor[]::new);
-            });
-            CachedConstructor[] constructors = new CachedConstructor[declaredConstructors.length];
-            for (int i = 0; i != constructors.length; ++i)
-                constructors[i] = new CachedConstructor(CachedClass.this, declaredConstructors[i]);
-            return constructors;
+            PrivilegedAction<CachedConstructor[]> action = () -> {
+                return Arrays.stream(getTheClass().getDeclaredConstructors())
+                    .filter(c -> checkCanSetAccessible(c, CachedClass.class))
+                    .map(c -> new CachedConstructor(CachedClass.this, c))
+                    .toArray(CachedConstructor[]::new);
+            };
+            return AccessController.doPrivileged(action);
         }
     };
 
     private final LazyReference<CachedMethod[]> methods = new LazyReference<CachedMethod[]>(softBundle) {
         private static final long serialVersionUID = 6347586066597418308L;
 
+        @Override
         public CachedMethod[] initValue() {
-            final Method[] declaredMethods;
-            declaredMethods = AccessController.doPrivileged((PrivilegedAction<Method[]>) () -> {
+            PrivilegedAction<CachedMethod[]> action = () -> {
                 try {
-                    Method[] dm = getTheClass().getDeclaredMethods();
-                    return Arrays.stream(dm)
-                            .filter(m -> checkCanSetAccessible(m, CachedClass.class))
-                            .toArray(Method[]::new);
-                } catch (Throwable e) {
-                    // Typically, Android can throw ClassNotFoundException
-                    return EMPTY_METHOD_ARRAY;
+                    return Arrays.stream(getTheClass().getDeclaredMethods())
+                        // skip synthetic methods inserted by JDK 1.5+ compilers
+                        .filter(m -> !m.isBridge() && m.getName().indexOf('+') < 0)
+                        .filter(m -> checkCanSetAccessible(m, CachedClass.class))
+                        .map(m -> new CachedMethod(CachedClass.this, m))
+                        .toArray(CachedMethod[]::new);
+                } catch (LinkageError e) {
+                    return CachedMethod.EMPTY_ARRAY;
                 }
-            });
+            };
+            CachedMethod[] declaredMethods = AccessController.doPrivileged(action);
+
             List<CachedMethod> methods = new ArrayList<>(declaredMethods.length);
             List<CachedMethod> mopMethods = new ArrayList<>(declaredMethods.length);
-            for (int i = 0; i != declaredMethods.length; ++i) {
-                final CachedMethod cachedMethod = new CachedMethod(CachedClass.this, declaredMethods[i]);
-                final String name = cachedMethod.getName();
-
-                if (declaredMethods[i].isBridge() || name.indexOf('+') >= 0) {
-                    // Skip Synthetic methods inserted by JDK 1.5 compilers and later
-                    continue;
-                } /*else if (Modifier.isAbstract(reflectionMethod.getModifiers())) {
-                   continue;
-                }*/
-
-                if (name.startsWith("this$") || name.startsWith("super$"))
-                  mopMethods.add(cachedMethod);
-                else
-                  methods.add(cachedMethod);
+            for (CachedMethod method : declaredMethods) {
+                String name = method.getName();
+                if (name.startsWith("this$") || name.startsWith("super$")) {
+                    mopMethods.add(method);
+                } else {
+                    methods.add(method);
+                }
             }
-            CachedMethod[] resMethods = methods.toArray(CachedMethod.EMPTY_ARRAY);
-            Arrays.sort(resMethods);
+            Collections.sort(methods);
 
-            final CachedClass superClass = getCachedSuperClass();
+            CachedClass superClass = getCachedSuperClass();
             if (superClass != null) {
-                superClass.getMethods();
-                final CachedMethod[] superMopMethods = superClass.mopMethods;
-                mopMethods.addAll(Arrays.asList(superMopMethods));
+                superClass.getMethods(); // populate mopMethods
+                Collections.addAll(mopMethods, superClass.mopMethods);
             }
+            Collections.sort(mopMethods, CachedMethodComparatorByName.INSTANCE);
             CachedClass.this.mopMethods = mopMethods.toArray(CachedMethod.EMPTY_ARRAY);
-            Arrays.sort(CachedClass.this.mopMethods, CachedMethodComparatorByName.INSTANCE);
 
-            return resMethods;
+            return methods.toArray(CachedMethod.EMPTY_ARRAY);
         }
     };
 
     private LazyReference<CachedClass> cachedSuperClass = new LazyReference<CachedClass>(softBundle) {
         private static final long serialVersionUID = -4663740963306806058L;
 
+        @Override
         public CachedClass initValue() {
-            if (!isArray)
-              return ReflectionCache.getCachedClass(getTheClass().getSuperclass());
-            else
-              if (cachedClass.getComponentType().isPrimitive() || cachedClass.getComponentType() == Object.class)
+            if (!isArray) {
+                return ReflectionCache.getCachedClass(getTheClass().getSuperclass());
+            } else if (cachedClass.getComponentType().isPrimitive() || cachedClass.getComponentType() == Object.class) {
                 return ReflectionCache.OBJECT_CLASS;
-              else
+            } else {
                 return ReflectionCache.OBJECT_ARRAY_CLASS;
+            }
         }
     };
 
     private final LazyReference<CallSiteClassLoader> callSiteClassLoader = new LazyReference<CallSiteClassLoader>(softBundle) {
         private static final long serialVersionUID = 4410385968428074090L;
 
+        @Override
         public CallSiteClassLoader initValue() {
-            return
-               AccessController.doPrivileged((PrivilegedAction<CallSiteClassLoader>) () -> new CallSiteClassLoader(CachedClass.this.cachedClass));
+            return AccessController.doPrivileged((PrivilegedAction<CallSiteClassLoader>) () -> new CallSiteClassLoader(CachedClass.this.cachedClass));
         }
     };
 
-    private final LazyReference<LinkedList<ClassInfo>> hierarchy = new LazyReference<LinkedList<ClassInfo>>(softBundle) {
+    private final LazyReference<Collection<ClassInfo>> hierarchy = new LazyReference<Collection<ClassInfo>>(softBundle) {
         private static final long serialVersionUID = 7166687623678851596L;
 
-        public LinkedList<ClassInfo> initValue() {
+        @Override
+        public Collection<ClassInfo> initValue() {
             Set<ClassInfo> res = new LinkedHashSet<>();
-
             res.add(classInfo);
 
-            for (CachedClass iface : getDeclaredInterfaces())
-              res.addAll(iface.getHierarchy());
-
-            final CachedClass superClass = getCachedSuperClass();
-            if (superClass != null)
-              res.addAll(superClass.getHierarchy());
-
-            if (isInterface)
-              res.add(ReflectionCache.OBJECT_CLASS.classInfo);
-
-            return new LinkedList<>(res);
+            for (CachedClass iface : getDeclaredInterfaces()) {
+                res.addAll(iface.getHierarchy());
+            }
+            CachedClass superClass = getCachedSuperClass();
+            if (superClass != null) {
+                res.addAll(superClass.getHierarchy());
+            }
+            if (isInterface) {
+                res.add(ReflectionCache.OBJECT_CLASS.classInfo);
+            }
+            return res;
         }
     };
 
-    static final MetaMethod[] EMPTY = MetaMethod.EMPTY_ARRAY;
-
-    int hashCode;
-
-    public  CachedMethod[] mopMethods;
-    public static final CachedClass[] EMPTY_ARRAY = new CachedClass[0];
-
-    private final LazyReference<Set<CachedClass>> declaredInterfaces = new LazyReference<Set<CachedClass>> (softBundle) {
+    private final LazyReference<Set<CachedClass>> declaredInterfaces = new LazyReference<Set<CachedClass>>(softBundle) {
         private static final long serialVersionUID = 2139190436931329873L;
 
+        @Override
         public Set<CachedClass> initValue() {
             Set<CachedClass> res = new HashSet<>(0);
 
@@ -207,38 +184,43 @@ public class CachedClass {
         }
     };
 
-    private final LazyReference<Set<CachedClass>> interfaces = new LazyReference<Set<CachedClass>> (softBundle) {
+    private final LazyReference<Set<CachedClass>> interfaces = new LazyReference<Set<CachedClass>>(softBundle) {
         private static final long serialVersionUID = 4060471819464086940L;
 
+        @Override
         public Set<CachedClass> initValue() {
             Set<CachedClass> res = new HashSet<>(0);
 
-            if (getTheClass().isInterface())
-              res.add(CachedClass.this);
-
+            if (getTheClass().isInterface()) {
+                res.add(CachedClass.this);
+            }
             Class[] classes = getTheClass().getInterfaces();
             for (Class cls : classes) {
-                final CachedClass aClass = ReflectionCache.getCachedClass(cls);
+                CachedClass aClass = ReflectionCache.getCachedClass(cls);
                 if (!res.contains(aClass))
                     res.addAll(aClass.getInterfaces());
             }
 
-            final CachedClass superClass = getCachedSuperClass();
-            if (superClass != null)
-              res.addAll(superClass.getInterfaces());
-
+            CachedClass superClass = getCachedSuperClass();
+            if (superClass != null) {
+                res.addAll(superClass.getInterfaces());
+            }
             return res;
         }
     };
 
+    private final Class<?> cachedClass;
+    public ClassInfo classInfo;
     public final boolean isArray;
     public final boolean isPrimitive;
     public final int modifiers;
-    int distance = -1;
     public final boolean isInterface;
     public final boolean isNumber;
+    public CachedMethod[] mopMethods;
+    int distance = -1;
+    int hashCode;
 
-    public CachedClass(Class klazz, ClassInfo classInfo) {
+    public CachedClass(Class<?> klazz, ClassInfo classInfo) {
         cachedClass = klazz;
         this.classInfo = classInfo;
         isArray = klazz.isArray();
@@ -307,7 +289,7 @@ public class CachedClass {
 
         int distance = 0;
         for (Class klazz = getTheClass(); klazz != null; klazz = klazz.getSuperclass()) {
-            distance++;
+            distance += 1;
         }
         this.distance = distance;
         return distance;
@@ -329,7 +311,7 @@ public class CachedClass {
     public boolean isVoid() {
         return getTheClass() == void.class;
     }
-    
+
     public boolean isInterface() {
         return isInterface;
     }
@@ -513,6 +495,7 @@ public class CachedClass {
         }
     }
 
+    @Override
     public String toString() {
         return cachedClass.toString();
     }
diff --git a/src/main/java/org/codehaus/groovy/reflection/ClassInfo.java b/src/main/java/org/codehaus/groovy/reflection/ClassInfo.java
index c7d1a51..77b2c5f 100644
--- a/src/main/java/org/codehaus/groovy/reflection/ClassInfo.java
+++ b/src/main/java/org/codehaus/groovy/reflection/ClassInfo.java
@@ -94,25 +94,25 @@ public class ClassInfo implements Finalizable {
 
     private MetaClass strongMetaClass;
     private ManagedReference<MetaClass> weakMetaClass;
-    MetaMethod[] dgmMetaMethods = CachedClass.EMPTY;
-    MetaMethod[] newMetaMethods = CachedClass.EMPTY;
+    MetaMethod[] dgmMetaMethods = MetaMethod.EMPTY_ARRAY;
+    MetaMethod[] newMetaMethods = MetaMethod.EMPTY_ARRAY;
     private ManagedConcurrentMap<Object, MetaClass> perInstanceMetaClassMap;
-    
+
     private static final ReferenceBundle softBundle = ReferenceBundle.getSoftBundle();
     private static final ReferenceBundle weakBundle = ReferenceBundle.getWeakBundle();
-    
+
     private static final ManagedConcurrentLinkedQueue<ClassInfo> modifiedExpandos =
             new ManagedConcurrentLinkedQueue<ClassInfo>(weakBundle);
 
     private static final GroovyClassValue<ClassInfo> globalClassValue = GroovyClassValueFactory.createGroovyClassValue(new ComputeValue<ClassInfo>(){
-		@Override
-		public ClassInfo computeValue(Class<?> type) {
-			ClassInfo ret = new ClassInfo(type);
-			globalClassSet.add(ret);
-			return ret;
-		}
-	});
-    
+        @Override
+        public ClassInfo computeValue(Class<?> type) {
+            ClassInfo ret = new ClassInfo(type);
+            globalClassSet.add(ret);
+            return ret;
+        }
+    });
+
     private static final GlobalClassSet globalClassSet = new GlobalClassSet();
 
     ClassInfo(Class klazz) {
@@ -210,7 +210,7 @@ public class ClassInfo implements Finalizable {
         // safe value here to avoid multiple reads with possibly
         // differing values due to concurrency
         MetaClass strongRef = strongMetaClass;
-        
+
         if (strongRef instanceof ExpandoMetaClass) {
             ((ExpandoMetaClass)strongRef).inRegistry = false;
             for (Iterator<ClassInfo> itr = modifiedExpandos.iterator(); itr.hasNext(); ) {
@@ -274,11 +274,11 @@ public class ClassInfo implements Finalizable {
     private MetaClass getMetaClassUnderLock() {
         MetaClass answer = getStrongMetaClass();
         if (answer!=null) return answer;
-        
+
         answer = getWeakMetaClass();
         final MetaClassRegistry metaClassRegistry = GroovySystem.getMetaClassRegistry();
         MetaClassRegistry.MetaClassCreationHandle mccHandle = metaClassRegistry.getMetaClassCreationHandler();
-        
+
         if (isValidWeakMetaClass(answer, mccHandle)) {
             return answer;
         }
@@ -293,7 +293,7 @@ public class ClassInfo implements Finalizable {
         }
         return answer;
     }
-    
+
     private static boolean isValidWeakMetaClass(MetaClass metaClass) {
         return isValidWeakMetaClass(metaClass, GroovySystem.getMetaClassRegistry().getMetaClassCreationHandler());
     }
@@ -366,7 +366,7 @@ public class ClassInfo implements Finalizable {
                 cachedClass = new BigDecimalCachedClass(klazz, classInfo);
             } else if (klazz == Long.class || klazz == Long.TYPE) {
                 cachedClass = new LongCachedClass(klazz, classInfo, klazz==Long.class);
-            } else if (klazz == Float.class || klazz == Float.TYPE) { 
+            } else if (klazz == Float.class || klazz == Float.TYPE) {
                 cachedClass = new FloatCachedClass(klazz, classInfo, klazz==Float.class);
             } else if (klazz == Short.class || klazz == Short.TYPE) {
                 cachedClass = new ShortCachedClass(klazz, classInfo, klazz==Short.class);
@@ -398,7 +398,7 @@ public class ClassInfo implements Finalizable {
         }
         return cachedClass;
     }
-    
+
     private static boolean isSAM(Class<?> c) {
         return CachedSAMClass.getSAMMethod(c) !=null;
     }
@@ -423,7 +423,7 @@ public class ClassInfo implements Finalizable {
 
         if (metaClass != null) {
             if (perInstanceMetaClassMap == null)
-              perInstanceMetaClassMap = new ManagedConcurrentMap<Object, MetaClass>(ReferenceBundle.getWeakBundle()); 
+              perInstanceMetaClassMap = new ManagedConcurrentMap<Object, MetaClass>(ReferenceBundle.getWeakBundle());
 
             perInstanceMetaClassMap.put(obj, metaClass);
         }
@@ -474,24 +474,24 @@ public class ClassInfo implements Finalizable {
     }
 
     private static class GlobalClassSet {
-    	
-    	private final ManagedConcurrentLinkedQueue<ClassInfo> items = new ManagedConcurrentLinkedQueue<ClassInfo>(weakBundle);
-    	
-    	public int size(){
-		    return values().size();
-    	}
-    	
-    	public int fullSize(){
-		    return values().size();
-    	}
-    	
-    	public Collection<ClassInfo> values(){
-    	    return items.values();
-    	}
-    	
-    	public void add(ClassInfo value){
+
+        private final ManagedConcurrentLinkedQueue<ClassInfo> items = new ManagedConcurrentLinkedQueue<ClassInfo>(weakBundle);
+
+        public int size(){
+            return values().size();
+        }
+
+        public int fullSize(){
+            return values().size();
+        }
+
+        public Collection<ClassInfo> values(){
+            return items.values();
+        }
+
+        public void add(ClassInfo value){
             items.add(value);
-    	}
+        }
 
     }
 


[groovy] 12/18: GROOVY-9238: look again for collector annotations when anno list changes

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

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

commit 3a581dcd3c5c1e129ab8f579ac53779aae5e1f12
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 16:47:43 2019 -0600

    GROOVY-9238: look again for collector annotations when anno list changes
    
    (cherry picked from commit 2af190780bd33c7c12806297e8f548f52f1b7c2c)
---
 .../ASTTransformationCollectorCodeVisitor.java     | 40 ++++++++--------
 src/test/groovy/bugs/Groovy9238.groovy             | 53 ++++++++++++++++++++++
 2 files changed, 75 insertions(+), 18 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
index 5fb0418..8e38896 100644
--- a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
@@ -83,25 +83,29 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         if (nodeAnnotations.isEmpty()) return;
         super.visitAnnotations(node);
 
-        Map<Integer, AnnotationCollectorMode> modes = new LinkedHashMap<>();
-        Map<Integer, List<AnnotationNode>> existing = new LinkedHashMap<>();
-        Map<Integer, List<AnnotationNode>> replacements = new LinkedHashMap<>();
-        int index = 0;
-        for (AnnotationNode annotation : nodeAnnotations) {
-            findCollectedAnnotations(annotation, node, index, modes, existing, replacements);
-            index += 1;
-        }
-        for (Map.Entry<Integer, List<AnnotationNode>> entry : replacements.entrySet()) {
-            Integer replacementIndex = entry.getKey();
-            List<AnnotationNode> annotationNodeList = entry.getValue();
-            mergeCollectedAnnotations(modes.get(replacementIndex), existing, annotationNodeList);
-            existing.put(replacementIndex, annotationNodeList);
-        }
-        List<AnnotationNode> mergedList = new ArrayList<>();
-        existing.values().forEach(mergedList::addAll);
+        for (;;) {
+            Map<Integer, AnnotationCollectorMode> modes = new LinkedHashMap<>();
+            Map<Integer, List<AnnotationNode>> existing = new LinkedHashMap<>();
+            Map<Integer, List<AnnotationNode>> replacements = new LinkedHashMap<>();
+            int index = 0;
+            for (AnnotationNode annotation : nodeAnnotations) {
+                findCollectedAnnotations(annotation, node, index, modes, existing, replacements);
+                index += 1;
+            }
+            for (Map.Entry<Integer, List<AnnotationNode>> entry : replacements.entrySet()) {
+                Integer replacementIndex = entry.getKey();
+                List<AnnotationNode> annotationNodeList = entry.getValue();
+                mergeCollectedAnnotations(modes.get(replacementIndex), existing, annotationNodeList);
+                existing.put(replacementIndex, annotationNodeList);
+            }
+            List<AnnotationNode> mergedList = new ArrayList<>();
+            existing.values().forEach(mergedList::addAll);
+            if (mergedList.equals(nodeAnnotations)) break;
 
-        nodeAnnotations.clear();
-        nodeAnnotations.addAll(mergedList);
+            nodeAnnotations.clear();
+            nodeAnnotations.addAll(mergedList);
+            // GROOVY-9238: look again for collector annotations
+        }
 
         for (AnnotationNode annotation : nodeAnnotations) {
             addTransformsToClassNode(annotation);
diff --git a/src/test/groovy/bugs/Groovy9238.groovy b/src/test/groovy/bugs/Groovy9238.groovy
new file mode 100644
index 0000000..6730e3a
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9238.groovy
@@ -0,0 +1,53 @@
+/*
+ *  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.AnnotationCollector
+import groovy.transform.CompileStatic
+import groovy.transform.Immutable
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9238 {
+
+    @Test
+    void testAnnotationCollectorOfCollectedAnnotations() {
+        assertScript '''
+            import groovy.bugs.Groovy9238.Collector
+
+            @Collector
+            class Pogo9238 {
+              String string
+            }
+
+            def pogo = new Pogo9238('old')
+            pogo = pogo.copyWith(string: 'new')
+
+            assert pogo.string == 'new'
+        '''
+    }
+
+    @CompileStatic
+    @Immutable(copyWith=true) // this uses AnnotationCollector
+    @AnnotationCollector
+    @interface Collector {
+    }
+}


[groovy] 02/18: minor edits

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

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

commit 343188d77414f94f3a5895a987c8dae1526dfe08
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 17 18:35:06 2019 -0600

    minor edits
    
    (cherry picked from commit 0b2155dd202107b5dfca51a36ada20884c983d69)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 85 ++++++++++------------
 1 file changed, 40 insertions(+), 45 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 fa99933..acdd3d9 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -773,8 +773,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitBinaryExpression(final BinaryExpression expression) {
-        boolean isAssignment = expression.getOperation().isA(ASSIGNMENT_OPERATOR);
-
         BinaryExpression enclosingBinaryExpression = typeCheckingContext.getEnclosingBinaryExpression();
         typeCheckingContext.pushEnclosingBinaryExpression(expression);
         try {
@@ -851,6 +849,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 }
             }
 
+            boolean isAssignment = expression.getOperation().isA(ASSIGNMENT_OPERATOR);
             if (isAssignment && lType.isUsingGenerics() && missesGenericsTypes(resultType)) {
                 // unchecked assignment
                 // examples:
@@ -1006,7 +1005,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // because we need to check if a setter uses @DelegatesTo
         VariableExpression ve = varX("%", setterInfo.receiverType);
         // for compound assignment "x op= y" find type as if it was "x = (x op y)"
-        final Expression newRightExpression = isCompoundAssignment(expression)
+        Expression newRightExpression = isCompoundAssignment(expression)
                 ? binX(leftExpression, getOpWithoutEqual(expression), rightExpression)
                 : rightExpression;
         MethodCallExpression call = callX(ve, setterInfo.name, newRightExpression);
@@ -1865,7 +1864,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitProperty(final PropertyNode node) {
-        final boolean osc = typeCheckingContext.isInStaticContext;
+        boolean osc = typeCheckingContext.isInStaticContext;
         try {
             typeCheckingContext.isInStaticContext = node.isInStaticContext();
             currentProperty = node;
@@ -1878,7 +1877,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitField(final FieldNode node) {
-        final boolean osc = typeCheckingContext.isInStaticContext;
+        boolean osc = typeCheckingContext.isInStaticContext;
         try {
             typeCheckingContext.isInStaticContext = node.isInStaticContext();
             currentField = node;
@@ -1906,7 +1905,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     @Override
     public void visitForLoop(final ForStatement forLoop) {
         // collect every variable expression used in the loop body
-        final Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
+        Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
         forLoop.getLoopBlock().visit(new VariableExpressionTypeMemoizer(varOrigType));
 
         // visit body
@@ -1917,7 +1916,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             super.visitForLoop(forLoop);
         } else {
             collectionExpression.visit(this);
-            final ClassNode collectionType = getType(collectionExpression);
+            ClassNode collectionType = getType(collectionExpression);
             ClassNode forLoopVariableType = forLoop.getVariableType();
             ClassNode componentType;
             if (Character_TYPE.equals(getWrapper(forLoopVariableType)) && STRING_TYPE.equals(collectionType)) {
@@ -2480,7 +2479,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         typeCheckingContext.pushErrorCollector(collector);
 
-        final boolean osc = typeCheckingContext.isInStaticContext;
+        boolean osc = typeCheckingContext.isInStaticContext;
         try {
             typeCheckingContext.isInStaticContext = node.isStatic();
             super.visitMethod(node);
@@ -2527,7 +2526,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     @Override
     public void visitStaticMethodCallExpression(final StaticMethodCallExpression call) {
-        final String name = call.getMethod();
+        String name = call.getMethod();
         if (name == null) {
             addStaticTypeError("cannot resolve dynamic method name at compile time.", call);
             return;
@@ -2544,7 +2543,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         checkForbiddenSpreadArgument(argumentList);
 
-        final ClassNode receiver = call.getOwnerType();
+        ClassNode receiver = call.getOwnerType();
         visitMethodCallArguments(receiver, argumentList, false, null);
 
         ClassNode[] args = getArgumentTypes(argumentList);
@@ -2646,7 +2645,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         ArgumentListExpression newArgs = args(expressions);
 
         for (int i = 0, expressionsSize = expressions.size(); i < expressionsSize; i++) {
-            final Expression expression = expressions.get(i);
+            Expression expression = expressions.get(i);
             if (visitClosures && expression instanceof ClosureExpression
                     || !visitClosures && !(expression instanceof ClosureExpression)) {
                 if (i < params.length && visitClosures) {
@@ -2957,10 +2956,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             Iterator<ClassNode[]> candIt = candidates.iterator();
             while (candIt.hasNext()) {
                 ClassNode[] inferred = candIt.next();
-                final int length = closureParams.length;
-                for (int i = 0; i < length; i++) {
+                for (int i = 0, n = closureParams.length; i < n; i += 1) {
                     Parameter closureParam = closureParams[i];
-                    final ClassNode originType = closureParam.getOriginType();
+                    ClassNode originType = closureParam.getOriginType();
                     ClassNode inferredType;
                     if (i < inferred.length - 1 || inferred.length == closureParams.length) {
                         inferredType = inferred[i];
@@ -2973,7 +2971,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                             continue;
                         }
                     }
-                    if (!typeCheckMethodArgumentWithGenerics(originType, inferredType, i == length - 1)) {
+                    if (!typeCheckMethodArgumentWithGenerics(originType, inferredType, i == (n - 1))) {
                         candIt.remove();
                     }
                 }
@@ -2990,10 +2988,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             if (closureParams.length == 0 && inferred.length == 1) {
                 expression.putNodeMetaData(CLOSURE_ARGUMENTS, inferred);
             } else {
-                final int length = closureParams.length;
-                for (int i = 0; i < length; i++) {
+                for (int i = 0, n = closureParams.length; i < n; i += 1) {
                     Parameter closureParam = closureParams[i];
-                    final ClassNode originType = closureParam.getOriginType();
+                    ClassNode originType = closureParam.getOriginType();
                     ClassNode inferredType = OBJECT_TYPE;
                     if (i < inferred.length - 1 || inferred.length == closureParams.length) {
                         inferredType = inferred[i];
@@ -3005,7 +3002,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                             addError("Incorrect number of parameters. Expected " + inferred.length + " but found " + closureParams.length, expression);
                         }
                     }
-                    boolean lastArg = i == length - 1;
+                    boolean lastArg = i == (n - 1);
 
                     if (!typeCheckMethodArgumentWithGenerics(originType, inferredType, lastArg)) {
                         addError("Expected parameter of type " + inferredType.toString(false) + " but got " + originType.toString(false), closureParam.getType());
@@ -3019,8 +3016,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private ClassNode[] resolveGenericsFromTypeHint(final ClassNode receiver, final Expression arguments, final MethodNode selectedMethod, final ClassNode[] signature) {
         ClassNode dummyResultNode = new ClassNode("ClForInference$" + UNIQUE_LONG.incrementAndGet(), 0, OBJECT_TYPE).getPlainNodeReference();
-        final GenericsType[] genericTypes = new GenericsType[signature.length];
-        for (int i = 0; i < signature.length; i++) {
+        GenericsType[] genericTypes = new GenericsType[signature.length];
+        for (int i = 0, n = signature.length; i < n; i += 1) {
             genericTypes[i] = new GenericsType(signature[i]);
         }
         dummyResultNode.setGenericsTypes(genericTypes);
@@ -3134,13 +3131,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         }
                     }
                 } else {
-                    final List<Expression> expressions = arguments.getExpressions();
-                    final int expressionsSize = expressions.size();
+                    List<Expression> expressions = arguments.getExpressions();
+                    int expressionsSize = expressions.size();
                     Expression parameter = annotation.getMember("target");
                     String parameterName = parameter instanceof ConstantExpression ? parameter.getText() : "";
                     // todo: handle vargs!
                     for (int j = 0, paramsLength = params.length; j < paramsLength; j++) {
-                        final Parameter methodParam = params[j];
+                        Parameter methodParam = params[j];
                         List<AnnotationNode> targets = methodParam.getAnnotations(DELEGATES_TO_TARGET);
                         if (targets != null && targets.size() == 1) {
                             AnnotationNode targetAnnotation = targets.get(0); // @DelegatesTo.Target Obj foo
@@ -3756,8 +3753,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (allParametersAndArgumentsMatch(parameters, args) < 0 &&
                 lastArgMatchesVarg(parameters, args) < 0) {
             StringBuilder sb = new StringBuilder("[");
-            for (int i = 0, parametersLength = parameters.length; i < parametersLength; i++) {
-                final Parameter parameter = parameters[i];
+            for (int i = 0, parametersLength = parameters.length; i < parametersLength; i += 1) {
+                Parameter parameter = parameters[i];
                 sb.append(parameter.getType().getName());
                 if (i < parametersLength - 1) sb.append(", ");
             }
@@ -3994,9 +3991,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private boolean isDelegateOrOwnerInClosure(final Expression exp) {
-        return typeCheckingContext.getEnclosingClosure() != null &&
-                exp instanceof VariableExpression &&
-                (("delegate".equals(((VariableExpression) exp).getName())) || ("owner".equals(((VariableExpression) exp).getName())));
+        return typeCheckingContext.getEnclosingClosure() != null && exp instanceof VariableExpression
+                && (("delegate".equals(((VariableExpression) exp).getName())) || ("owner".equals(((VariableExpression) exp).getName())));
     }
 
     protected boolean checkCast(final ClassNode targetType, final Expression source) {
@@ -4393,7 +4389,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected ClassNode inferComponentType(final ClassNode containerType, final ClassNode indexType) {
-        final ClassNode componentType = containerType.getComponentType();
+        ClassNode componentType = containerType.getComponentType();
         if (componentType == null) {
             // GROOVY-5521
             // try to identify a getAt method
@@ -4472,14 +4468,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     protected static String prettyPrintMethodList(final List<MethodNode> nodes) {
         StringBuilder sb = new StringBuilder("[");
-        for (int i = 0, nodesSize = nodes.size(); i < nodesSize; i++) {
-            final MethodNode node = nodes.get(i);
+        for (int i = 0, n = nodes.size(); i < n; i += 1) {
+            MethodNode node = nodes.get(i);
             sb.append(node.getReturnType().toString(false));
             sb.append(" ");
             sb.append(node.getDeclaringClass().toString(false));
             sb.append("#");
             sb.append(toMethodParametersString(node.getName(), extractTypesFromParameters(node.getParameters())));
-            if (i < nodesSize - 1) sb.append(", ");
+            if (i < n - 1) sb.append(", ");
         }
         sb.append("]");
         return sb.toString();
@@ -4871,7 +4867,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         ClosureExpression closureExpression = enclosingClosure.getClosureExpression();
         ClassNode[] closureParamTypes = closureExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
         if (closureParamTypes == null) return null;
-        final Parameter[] parameters = closureExpression.getParameters();
+        Parameter[] parameters = closureExpression.getParameters();
         String name = parameter.getName();
 
         if (parameters != null) {
@@ -5227,9 +5223,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (expression.getNodeMetaData(CLOSURE_ARGUMENTS) != null) {
                     closureParamTypes = expression.getNodeMetaData(CLOSURE_ARGUMENTS);
                 }
-                final Parameter[] parameters = sam.getParameters();
-                for (int i = 0; i < parameters.length; i++) {
-                    final Parameter parameter = parameters[i];
+                Parameter[] parameters = sam.getParameters();
+                for (int i = 0, n = parameters.length; i < n; i += 1) {
+                    Parameter parameter = parameters[i];
                     if (parameter.getOriginType().isUsingGenerics() && closureParamTypes.length > i) {
                         genericsToConnect.add(new ClassNode[]{closureParamTypes[i], parameter.getOriginType()});
                     }
@@ -5252,8 +5248,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         GenericsType[] expectedGenericsTypes = expected.getGenericsTypes();
                         GenericsType[] foundGenericsTypes = generifiedType.getGenericsTypes();
 
-                        for (int i = 0; i < expectedGenericsTypes.length; i++) {
-                            final GenericsType type = expectedGenericsTypes[i];
+                        for (int i = 0, n = expectedGenericsTypes.length; i < n; i += 1) {
+                            GenericsType type = expectedGenericsTypes[i];
                             if (type.isPlaceholder()) {
                                 String name = type.getName();
                                 placeholders.put(new GenericsTypeName(name), foundGenericsTypes[i]);
@@ -5316,7 +5312,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (isPrimitiveType(receiver) && !isPrimitiveType(declaringClass)) {
             receiver = getWrapper(receiver);
         }
-        final List<ClassNode> queue;
+        List<ClassNode> queue;
         if (receiver instanceof UnionTypeClassNode) {
             queue = Arrays.asList(((UnionTypeClassNode) receiver).getDelegates());
         } else {
@@ -5376,15 +5372,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (!typeCheckMethodsWithGenerics(receiver, arguments, candidateMethod)) {
             Map<GenericsTypeName, GenericsType> classGTs = GenericsUtils.extractPlaceholders(receiver);
             ClassNode[] ptypes = new ClassNode[candidateMethod.getParameters().length];
-            final Parameter[] parameters = candidateMethod.getParameters();
-            for (int i = 0; i < parameters.length; i++) {
-                final Parameter parameter = parameters[i];
+            Parameter[] parameters = candidateMethod.getParameters();
+            for (int i = 0, n = parameters.length; i < n; i += 1) {
+                Parameter parameter = parameters[i];
                 ClassNode type = parameter.getType();
                 ptypes[i] = fullyResolveType(type, classGTs);
             }
             addStaticTypeError("Cannot call " + toMethodGenericTypesString(candidateMethod) + receiver.toString(false) + "#" +
-                    toMethodParametersString(candidateMethod.getName(), ptypes) +
-                    " with arguments " + formatArgumentList(arguments), location);
+                    toMethodParametersString(candidateMethod.getName(), ptypes) + " with arguments " + formatArgumentList(arguments), location);
             return false;
         }
         return true;


[groovy] 13/18: fix test suite isolation

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

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

commit 4af20f99be63a1e8cfc4b61a19192f710433a3d1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 21 15:46:09 2019 -0600

    fix test suite isolation
    
    (cherry picked from commit 751a89d12efee0231d057a2064c2cc1ecacc068c)
---
 src/test/groovy/grape/GrabResolverTest.groovy | 43 ++++++++++-----------------
 1 file changed, 15 insertions(+), 28 deletions(-)

diff --git a/src/test/groovy/grape/GrabResolverTest.groovy b/src/test/groovy/grape/GrabResolverTest.groovy
index f7e4429..7181ab5 100644
--- a/src/test/groovy/grape/GrabResolverTest.groovy
+++ b/src/test/groovy/grape/GrabResolverTest.groovy
@@ -18,12 +18,12 @@
  */
 package groovy.grape
 
+import groovy.transform.CompileDynamic
 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
 
 import static groovy.test.GroovyAssert.assertScript
@@ -39,7 +39,7 @@ final class GrabResolverTest {
         originalGrapeRoot = System.getProperty('grape.root')
     }
 
-    @Before
+    @Before @CompileDynamic
     void setUp() {
         Grape.@instance = null // isolate each test
 
@@ -48,6 +48,10 @@ final class GrabResolverTest {
         System.setProperty('grape.root', grapeRoot.path)
         assert grapeRoot.mkdir()
         grapeRoot.deleteOnExit()
+
+        Grape.instance.settings.getResolver('downloadGrapes').resolvers.removeAll {
+            it.name == 'jcenter' || it.name == 'localm2'
+        }
     }
 
     @AfterClass
@@ -61,32 +65,13 @@ final class GrabResolverTest {
         Grape.@instance = null // isolate these tests from other tests
     }
 
-    @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?)
-        shouldFail RuntimeException, '''
-            @Grab('org.mvel:mvel2:2.1.3.Final')
-            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
+    @Test
     void testResolverDefinitionIsRequired() {
         shouldFail CompilationFailedException, '''
             @Grab(group='org.restlet', module='org.restlet', version='1.1.6')
             import org.restlet.Application
-            class AnnotationHost {}
-            println 'hello world'
+
+            assert false : '"org.restlet:org.restlet:1.1.6" should not resolve without @GrabResolver'
         '''
     }
 
@@ -95,8 +80,9 @@ final class GrabResolverTest {
         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'
+            import org.restlet.Application
+
+            assert Application.simpleName == 'Application'
         '''
     }
 
@@ -105,8 +91,9 @@ final class GrabResolverTest {
         assertScript '''
             @GrabResolver('http://maven.restlet.org')
             @Grab('org.restlet:org.restlet:1.1.6')
-            class AnnotationHost {}
-            assert org.restlet.Application.class.simpleName == 'Application'
+            import org.restlet.Application
+
+            assert Application.simpleName == 'Application'
         '''
     }
 }


[groovy] 14/18: Tweak GROOVY-9126: Remove unnecessary checks (#1096)

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

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

commit dd6957ec646ea9b42e2892f940a022d00b46b02b
Author: Daniel.Sun <su...@apache.org>
AuthorDate: Fri Nov 22 07:41:59 2019 +0800

    Tweak GROOVY-9126: Remove unnecessary checks (#1096)
    
    * Tweak GROOVY-9126: Remove unnecessary checks
    
    * Check if block is empty
    
    (cherry picked from commit d787ddd244a8e8c805d4941366faa1aa3f369c2c)
---
 .../java/org/codehaus/groovy/classgen/asm/StatementWriter.java    | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 8459b89..ebe0428 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -97,7 +97,7 @@ public class StatementWriter {
 
         // GROOVY-7647
         if (block.getLastLineNumber() > 0
-                && !methodOrConstructorsLastReturnStatementExists(block) // GROOVY-9126
+                && !isMethodOrConstructorNonEmptyBlock(block) // GROOVY-9126
         ) {
             MethodVisitor mv = controller.getMethodVisitor();
             Label blockEnd = new Label();
@@ -108,7 +108,7 @@ public class StatementWriter {
         controller.getOperandStack().popDownTo(mark);
     }
 
-    private boolean methodOrConstructorsLastReturnStatementExists(BlockStatement block) {
+    private boolean isMethodOrConstructorNonEmptyBlock(BlockStatement block) {
         MethodNode methodNode = controller.getMethodNode();
         if (null == methodNode) {
             methodNode = controller.getConstructorNode();
@@ -118,9 +118,7 @@ public class StatementWriter {
             return false;
         }
 
-        List<Statement> statementList = block.getStatements();
-        final int size = statementList.size();
-        return size > 0 && statementList.get(size - 1) instanceof ReturnStatement;
+        return !block.getStatements().isEmpty();
     }
 
     public void writeForStatement(ForStatement loop) {


[groovy] 07/18: create parser-agnostic API for parsing snippet

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

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

commit d0f36130f3413051614e3d222afb72aff62a8cb8
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 21 02:51:53 2019 +0800

    create parser-agnostic API for parsing snippet
    
    (cherry picked from commit f6f55ab632fe451aa8fe98ca87ecdd26b06d659a)
---
 .../codehaus/groovy/ast/tools/GenericsUtils.java   |  3 +-
 .../org/codehaus/groovy/control/ParserPlugin.java  | 14 ++++----
 .../main/groovy/groovy/util/OptionAccessor.groovy  | 38 ----------------------
 .../MarkupTemplateTypeCheckingExtension.groovy     | 13 ++++++--
 4 files changed, 19 insertions(+), 49 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 1e084dc..c142de5 100644
--- a/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
+++ b/src/main/java/org/codehaus/groovy/ast/tools/GenericsUtils.java
@@ -18,6 +18,7 @@
  */
 package org.codehaus.groovy.ast.tools;
 
+import groovy.lang.GroovyRuntimeException;
 import groovy.lang.Tuple2;
 import groovy.transform.stc.IncorrectTypeHintException;
 import org.codehaus.groovy.GroovyBugError;
@@ -582,7 +583,7 @@ public class GenericsUtils {
 
     public static ClassNode[] parseClassNodesFromString(final String option, final SourceUnit sourceUnit, final CompilationUnit compilationUnit, final MethodNode mn, final ASTNode usage) {
         try {
-            ModuleNode moduleNode = ParserPlugin.buildAST("Dummy<" + option + "> dummy;", compilationUnit.getConfiguration(), compilationUnit.getClassLoader(), null);
+            ModuleNode moduleNode = ParserPlugin.buildAST("Dummy<" + option + "> dummy;", compilationUnit.getClassLoader(), compilationUnit.getConfiguration(), null);
             DeclarationExpression dummyDeclaration = (DeclarationExpression) ((ExpressionStatement) moduleNode.getStatementBlock().getStatements().get(0)).getExpression();
 
             // the returned node is DummyNode<Param1, Param2, Param3, ...)
diff --git a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
index ee02b95..1d4f488 100644
--- a/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/control/ParserPlugin.java
@@ -22,6 +22,7 @@ import groovy.lang.GroovyClassLoader;
 import org.codehaus.groovy.ast.ModuleNode;
 import org.codehaus.groovy.syntax.ParserException;
 import org.codehaus.groovy.syntax.Reduction;
+import org.codehaus.groovy.util.CharSequenceReader;
 
 import java.io.Reader;
 
@@ -34,12 +35,11 @@ public interface ParserPlugin {
 
     ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException;
 
-    static ModuleNode buildAST(CharSequence sourceText, CompilerConfiguration config, GroovyClassLoader loader, ErrorCollector errors) throws CompilationFailedException {
-        SourceUnit sourceUnit = new SourceUnit("Script" + System.nanoTime() + ".groovy", sourceText.toString(), config, loader, errors);
-        sourceUnit.parse();
-        sourceUnit.completePhase();
-        sourceUnit.nextPhase();
-        sourceUnit.convert();
-        return sourceUnit.getAST();
+    static ModuleNode buildAST(CharSequence source, GroovyClassLoader loader, CompilerConfiguration config, ErrorCollector errors) throws ParserException {
+        String scriptName = "Script" + System.nanoTime() + ".groovy";
+        SourceUnit sourceUnit = new SourceUnit(scriptName, source.toString(), config, loader, errors);
+
+        ParserPlugin parserPlugin = config.getPluginFactory().createParserPlugin();
+        return parserPlugin.buildAST(sourceUnit, loader, parserPlugin.parseCST(sourceUnit, new CharSequenceReader(source)));
     }
 }
diff --git a/subprojects/groovy-cli-commons/src/main/groovy/groovy/util/OptionAccessor.groovy b/subprojects/groovy-cli-commons/src/main/groovy/groovy/util/OptionAccessor.groovy
deleted file mode 100644
index 935cf10..0000000
--- a/subprojects/groovy-cli-commons/src/main/groovy/groovy/util/OptionAccessor.groovy
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- *  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.util
-
-/**
- * @deprecated use {@code groovy.cli.picocli.OptionAccessor} or {@link groovy.cli.commons.OptionAccessor}
- */
-@Deprecated
-class OptionAccessor {
-    @Delegate
-    groovy.cli.commons.OptionAccessor delegate
-
-    // explicit delegate since groovyObject methods ignored by @Delegate
-    def getProperty(String name) {
-        delegate.getProperty(name)
-    }
-
-    // explicit delegate since groovyObject methods ignored by @Delegate
-    def invokeMethod(String name, Object args) {
-        delegate.invokeMethod(name, args)
-    }
-}
diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
index 19e2d00..697e0b4 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
@@ -174,11 +174,18 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
 
     @CompileStatic
     private static ClassNode buildNodeFromString(String option, TypeCheckingContext ctx) {
-        ModuleNode moduleNode = ParserPlugin.buildAST("$option variable;", ctx.compilationUnit.configuration, ctx.compilationUnit.classLoader, ctx.errorCollector)
-        ClassNode optionNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
+        def moduleNode = ParserPlugin.buildAST("Dummy<$option> dummy;", ctx.compilationUnit.classLoader, ctx.compilationUnit.configuration, ctx.errorCollector)
+        ClassNode parsedNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
         ClassNode dummyClass = new ClassNode("dummy", 0, OBJECT_TYPE)
         dummyClass.setModule(new ModuleNode(ctx.source))
-        MethodNode dummyMN = new MethodNode("dummy", 0, optionNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE)
+        MethodNode dummyMN = new MethodNode(
+                "dummy",
+                0,
+                parsedNode,
+                Parameter.EMPTY_ARRAY,
+                ClassNode.EMPTY_ARRAY,
+                EmptyStatement.INSTANCE
+        )
         dummyClass.addMethod(dummyMN)
         ResolveVisitor visitor = new ResolveVisitor(ctx.compilationUnit) {
             @Override


[groovy] 09/18: remove outer class

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

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

commit 5951bb34127d3d9c4f55b1b2cfb2b76129de8fd2
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Nov 20 14:38:48 2019 -0600

    remove outer class
    
    (cherry picked from commit b668bac0f481dac82bb935cbe1110f2fc9645067)
---
 .../MarkupTemplateTypeCheckingExtension.groovy     | 26 ++++++++--------------
 1 file changed, 9 insertions(+), 17 deletions(-)

diff --git a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
index e52958c..ad3ad3b 100644
--- a/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
+++ b/subprojects/groovy-templates/src/main/groovy/groovy/text/markup/MarkupTemplateTypeCheckingExtension.groovy
@@ -41,7 +41,6 @@ import org.codehaus.groovy.ast.stmt.ExpressionStatement
 import org.codehaus.groovy.control.ParserPlugin
 import org.codehaus.groovy.control.ResolveVisitor
 import org.codehaus.groovy.control.SourceUnit
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage
 import org.codehaus.groovy.syntax.SyntaxException
 import org.codehaus.groovy.syntax.Types
 import org.codehaus.groovy.transform.stc.GroovyTypeCheckingExtensionSupport
@@ -174,30 +173,23 @@ class MarkupTemplateTypeCheckingExtension extends GroovyTypeCheckingExtensionSup
 
     @CompileStatic
     private static ClassNode buildNodeFromString(String option, TypeCheckingContext ctx) {
-        def moduleNode = ParserPlugin.buildAST("Dummy<$option> dummy;", ctx.compilationUnit.configuration, ctx.compilationUnit.classLoader, ctx.errorCollector)
-        ClassNode parsedNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
-        ClassNode dummyClass = new ClassNode("dummy", 0, OBJECT_TYPE)
-        dummyClass.setModule(new ModuleNode(ctx.source))
-        MethodNode dummyMN = new MethodNode(
-                "dummy",
-                0,
-                parsedNode,
-                Parameter.EMPTY_ARRAY,
-                ClassNode.EMPTY_ARRAY,
-                EmptyStatement.INSTANCE
-        )
-        dummyClass.addMethod(dummyMN)
+        ModuleNode moduleNode = ParserPlugin.buildAST("$option dummy;", ctx.compilationUnit.configuration, ctx.compilationUnit.classLoader, ctx.errorCollector)
+        ClassNode optionNode = ((DeclarationExpression) ((ExpressionStatement) moduleNode.statementBlock.statements[0]).expression).leftExpression.type
+        ClassNode dummyClass = new ClassNode('dummy', 0, OBJECT_TYPE)
+        dummyClass.module = new ModuleNode(ctx.source)
+        MethodNode dummyMethod = new MethodNode('dummy', 0, optionNode, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, EmptyStatement.INSTANCE)
+        dummyClass.addMethod(dummyMethod)
         ResolveVisitor visitor = new ResolveVisitor(ctx.compilationUnit) {
             @Override
             void addError(final String msg, final ASTNode expr) {
-                ctx.errorCollector.addErrorAndContinue(new SyntaxErrorMessage(
+                ctx.errorCollector.addErrorAndContinue(
                         new SyntaxException(msg + '\n', expr.lineNumber, expr.columnNumber, expr.lastLineNumber, expr.lastColumnNumber),
-                        ctx.source)
+                        ctx.source
                 )
             }
         }
         visitor.startResolving(dummyClass, ctx.source)
-        return dummyMN.returnType
+        return dummyMethod.returnType
     }
 
     private static class BuilderMethodReplacer extends ClassCodeExpressionTransformer {


[groovy] 11/18: GROOVY-8686: restrict instanceof flow type to enclosing statement

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

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

commit b6b0688ea748b685922a8714a95d49d61099bba1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 17 19:26:42 2019 -0600

    GROOVY-8686: restrict instanceof flow type to enclosing statement
    
    (cherry picked from commit 3fc5fa6949ce2d46c84325a6f295f42064554347)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   |  8 ++++
 src/test/groovy/bugs/Groovy8686.groovy             | 52 ++++++++++++++++++++++
 2 files changed, 60 insertions(+)

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 acdd3d9..79132b3 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -85,6 +85,7 @@ import org.codehaus.groovy.ast.stmt.BlockStatement;
 import org.codehaus.groovy.ast.stmt.CaseStatement;
 import org.codehaus.groovy.ast.stmt.CatchStatement;
 import org.codehaus.groovy.ast.stmt.EmptyStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
 import org.codehaus.groovy.ast.stmt.ForStatement;
 import org.codehaus.groovy.ast.stmt.IfStatement;
 import org.codehaus.groovy.ast.stmt.ReturnStatement;
@@ -2142,6 +2143,13 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     @Override
+    public void visitExpressionStatement(final ExpressionStatement statement) {
+        typeCheckingContext.pushTemporaryTypeInfo();
+        super.visitExpressionStatement(statement);
+        typeCheckingContext.popTemporaryTypeInfo();
+    }
+
+    @Override
     public void visitReturnStatement(final ReturnStatement statement) {
         super.visitReturnStatement(statement);
         returnListener.returnStatementAdded(statement);
diff --git a/src/test/groovy/bugs/Groovy8686.groovy b/src/test/groovy/bugs/Groovy8686.groovy
new file mode 100644
index 0000000..1977c35
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8686.groovy
@@ -0,0 +1,52 @@
+/*
+ *  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.shouldFail
+
+@CompileStatic
+final class Groovy8686 {
+
+    @Test
+    void testInstanceOfScope1() {
+        def err = shouldFail '''
+            @groovy.transform.TypeChecked
+            def m(obj) {
+                boolean isA = (obj instanceof String && obj.equalsIgnoreCase('a'))
+                obj.toLowerCase() // typeof(obj) should be Object, not String
+            }
+        '''
+        assert err =~ /Cannot find matching method java.lang.Object#toLowerCase/
+    }
+
+    @Test
+    void testInstanceOfScope2() {
+        def err = shouldFail '''
+            @groovy.transform.CompileStatic
+            def m(obj) {
+                boolean isA = (obj instanceof String && obj.equalsIgnoreCase('a'))
+                obj.toLowerCase() // typeof(obj) should be Object, not String
+            }
+        '''
+        assert err =~ /Cannot find matching method java.lang.Object#toLowerCase/
+    }
+}


[groovy] 15/18: GROOVY-9312: disable direct references to local .m2 repo jars

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

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

commit a206e4f36116bb63573dfa9717e7fa8db7562809
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 21 13:48:58 2019 -0600

    GROOVY-9312: disable direct references to local .m2 repo jars
    
    (cherry picked from commit 0fdcf6aaa20d129a80ad0e517a9036ec0151840d)
---
 src/resources/groovy/grape/defaultGrapeConfig.xml |  1 -
 src/test/groovy/grape/GrapeIvyTest.groovy         | 61 +++++++++++++++++++++++
 2 files changed, 61 insertions(+), 1 deletion(-)

diff --git a/src/resources/groovy/grape/defaultGrapeConfig.xml b/src/resources/groovy/grape/defaultGrapeConfig.xml
index 4d17a40..14a180f 100644
--- a/src/resources/groovy/grape/defaultGrapeConfig.xml
+++ b/src/resources/groovy/grape/defaultGrapeConfig.xml
@@ -19,7 +19,6 @@
 
 -->
 <ivysettings>
-  <caches useOrigin="true"/>
   <settings defaultResolver="downloadGrapes"/>
   <resolvers>
     <chain name="downloadGrapes" returnFirst="true">
diff --git a/src/test/groovy/grape/GrapeIvyTest.groovy b/src/test/groovy/grape/GrapeIvyTest.groovy
index 635e5b4..6238857 100644
--- a/src/test/groovy/grape/GrapeIvyTest.groovy
+++ b/src/test/groovy/grape/GrapeIvyTest.groovy
@@ -461,4 +461,65 @@ final class GrapeIvyTest {
 
         Grape.resolve([classLoader:loader], [], [groupId:'org.apache.poi', artifactId:'poi', version:'3.7'])
     }
+
+    @Test // GROOVY-9312
+    void testResolveSucceedsFromLocalMavenRepository() {
+        def tempDir = File.createTempDir()
+
+        new File(tempDir, 'pom.xml').write '''\
+            <?xml version="1.0" encoding="UTF-8"?>
+            <project
+              xmlns="http://maven.apache.org/POM/4.0.0"
+              xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+              xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+                <modelVersion>4.0.0</modelVersion>
+                <groupId>org.codehaus.groovy.tests</groupId>
+                <artifactId>maven-bootstrap</artifactId>
+                <version>1.0-SNAPSHOT</version>
+                <dependencies>
+                    <dependency>
+                        <groupId>net.jqwik</groupId>
+                        <artifactId>jqwik</artifactId>
+                        <version>1.2.1</version>
+                    </dependency>
+                    <dependency>
+                        <groupId>net.jqwik</groupId>
+                        <artifactId>jqwik-engine</artifactId>
+                        <version>1.2.1</version>
+                    </dependency>
+                </dependencies>
+            </project>
+        '''.stripIndent()
+
+        try {
+            // prime "${user.home}/.m2/repository" with jqwik
+            assertScript """
+                @Grab('org.apache.maven.shared:maven-invoker:3.0.1')
+                import org.apache.maven.shared.invoker.*
+
+                def request = new DefaultInvocationRequest(goals: ['compile'],
+                    baseDirectory: new File('${tempDir.absolutePath.replace('\\', '\\\\')}'))
+                def result = new DefaultInvoker().execute(request)
+                assert result.exitCode == 0
+            """
+
+            assertScript '''
+                @Grab('net.jqwik:jqwik:1.2.1')
+                import net.jqwik.api.ForAll
+                import net.jqwik.api.Property
+
+                @groovy.transform.CompileStatic
+                class Jsr308 {
+                    @Property
+                    boolean 'size zero or positive'(@ForAll List<Integer> items) {
+                        items.size() >= 0
+                    }
+                }
+
+                println 'success'
+            '''
+        } finally {
+            tempDir.deleteDir()
+        }
+    }
 }


[groovy] 04/18: rework checks for annotation collectors and fix generics warnings

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

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

commit 3fe1cf23bb8f016e8032df0e304864082c267965
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 18 16:05:29 2019 -0600

    rework checks for annotation collectors and fix generics warnings
    
    evaluateExpression handles aliasing of "mode" and "processor" values
    
    (cherry picked from commit d557787ac1ac8516d90d38b80726c4d57ac5d634)
---
 .../ASTTransformationCollectorCodeVisitor.java     | 241 ++++++++-------------
 1 file changed, 95 insertions(+), 146 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
index 0ed0f11..5369e31 100644
--- a/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/ASTTransformationCollectorCodeVisitor.java
@@ -25,21 +25,15 @@ import org.codehaus.groovy.ast.AnnotatedNode;
 import org.codehaus.groovy.ast.AnnotationNode;
 import org.codehaus.groovy.ast.ClassCodeVisitorSupport;
 import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.expr.ClassExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
 import org.codehaus.groovy.ast.expr.Expression;
-import org.codehaus.groovy.ast.expr.PropertyExpression;
 import org.codehaus.groovy.control.CompilePhase;
 import org.codehaus.groovy.control.SourceUnit;
 import org.codehaus.groovy.control.messages.ExceptionMessage;
 import org.codehaus.groovy.control.messages.SimpleMessage;
-import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
-import org.codehaus.groovy.syntax.SyntaxException;
 import org.codehaus.groovy.transform.trait.TraitASTTransformation;
 import org.codehaus.groovy.transform.trait.Traits;
 
 import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
 import java.util.ArrayList;
 import java.util.Arrays;
@@ -48,53 +42,54 @@ import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
-import java.util.TreeMap;
+import java.util.Optional;
+
+import static org.codehaus.groovy.transform.stc.StaticTypeCheckingSupport.evaluateExpression;
 
 /**
- * This visitor walks the AST tree and collects references to Annotations that
- * are annotated themselves by {@link GroovyASTTransformation}. Each such
- * annotation is added.
+ * Walks the AST and collects references to annotations that are annotated
+ * themselves by {@link GroovyASTTransformation}. Each such annotation is added.
  * <p>
  * This visitor is only intended to be executed once, during the
- * SEMANTIC_ANALYSIS phase of compilation.
+ * {@code SEMANTIC_ANALYSIS} phase of compilation.
  */
 public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSupport {
-    private final SourceUnit source;
+
     private ClassNode classNode;
+    private final SourceUnit source;
     private final GroovyClassLoader transformLoader;
 
-    public ASTTransformationCollectorCodeVisitor(SourceUnit source, GroovyClassLoader transformLoader) {
+    public ASTTransformationCollectorCodeVisitor(final SourceUnit source, final GroovyClassLoader transformLoader) {
         this.source = source;
         this.transformLoader = transformLoader;
     }
 
+    @Override
     protected SourceUnit getSourceUnit() {
         return source;
     }
 
-    public void visitClass(ClassNode klassNode) {
-        ClassNode oldClass = classNode;
-        classNode = klassNode;
+    @Override
+    public void visitClass(final ClassNode classNode) {
+        ClassNode oldClass = this.classNode;
+        this.classNode = classNode;
         super.visitClass(classNode);
-        classNode = oldClass;
+        this.classNode = oldClass;
     }
 
-    /**
-     * If the annotation is annotated with {@link GroovyASTTransformation}
-     * the annotation is added to <code>stageVisitors</code> at the appropriate processor visitor.
-     *
-     * @param node the node to process
-     */
-    public void visitAnnotations(AnnotatedNode node) {
+    @Override
+    public void visitAnnotations(final AnnotatedNode node) {
+        List<AnnotationNode> nodeAnnotations = node.getAnnotations();
+        if (nodeAnnotations.isEmpty()) return;
         super.visitAnnotations(node);
 
-        Map<Integer, List<AnnotationNode>> existing = new TreeMap<Integer, List<AnnotationNode>>();
-        Map<Integer, List<AnnotationNode>> replacements = new LinkedHashMap<Integer, List<AnnotationNode>>();
-        Map<Integer, AnnotationCollectorMode> modes = new LinkedHashMap<Integer, AnnotationCollectorMode>();
+        Map<Integer, AnnotationCollectorMode> modes = new LinkedHashMap<>();
+        Map<Integer, List<AnnotationNode>> existing = new LinkedHashMap<>();
+        Map<Integer, List<AnnotationNode>> replacements = new LinkedHashMap<>();
         int index = 0;
-        for (AnnotationNode annotation : node.getAnnotations()) {
+        for (AnnotationNode annotation : nodeAnnotations) {
             findCollectedAnnotations(annotation, node, index, modes, existing, replacements);
-            index++;
+            index += 1;
         }
         for (Map.Entry<Integer, List<AnnotationNode>> entry : replacements.entrySet()) {
             Integer replacementIndex = entry.getKey();
@@ -102,26 +97,22 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
             mergeCollectedAnnotations(modes.get(replacementIndex), existing, annotationNodeList);
             existing.put(replacementIndex, annotationNodeList);
         }
-        List<AnnotationNode> mergedList = new ArrayList<AnnotationNode>();
-        for (List<AnnotationNode> next : existing.values()) {
-            mergedList.addAll(next);
-        }
+        List<AnnotationNode> mergedList = new ArrayList<>();
+        existing.values().forEach(mergedList::addAll);
 
-        node.getAnnotations().clear();
-        node.getAnnotations().addAll(mergedList);
+        nodeAnnotations.clear();
+        nodeAnnotations.addAll(mergedList);
 
-        for (AnnotationNode annotation : node.getAnnotations()) {
+        for (AnnotationNode annotation : nodeAnnotations) {
             Annotation transformClassAnnotation = getTransformClassAnnotation(annotation.getClassNode());
-            if (transformClassAnnotation == null) {
-                // skip if there is no such annotation
-                continue;
+            if (transformClassAnnotation != null) {
+                addTransformsToClassNode(annotation, transformClassAnnotation);
             }
-            addTransformsToClassNode(annotation, transformClassAnnotation);
         }
     }
 
-    private static void mergeCollectedAnnotations(AnnotationCollectorMode mode, Map<Integer, List<AnnotationNode>> existing, List<AnnotationNode> replacements) {
-        switch(mode) {
+    private static void mergeCollectedAnnotations(final AnnotationCollectorMode mode, final Map<Integer, List<AnnotationNode>> existing, final List<AnnotationNode> replacements) {
+        switch (mode) {
             case PREFER_COLLECTOR:
                 deleteExisting(false, existing, replacements);
                 break;
@@ -139,36 +130,33 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         }
     }
 
-    private static void deleteExisting(boolean mergeParams, Map<Integer, List<AnnotationNode>> existingMap, List<AnnotationNode> replacements) {
+    private static void deleteExisting(final boolean mergeParams, final Map<Integer, List<AnnotationNode>> existing, final List<AnnotationNode> replacements) {
         for (AnnotationNode replacement : replacements) {
-            for (Map.Entry<Integer, List<AnnotationNode>> entry : existingMap.entrySet()) {
-                Integer key = entry.getKey();
-                List<AnnotationNode> annotationNodes = new ArrayList<AnnotationNode>(entry.getValue());
-                Iterator<AnnotationNode> iterator = annotationNodes.iterator();
-                while (iterator.hasNext()) {
-                    AnnotationNode existing = iterator.next();
-                    if (replacement.getClassNode().getName().equals(existing.getClassNode().getName())) {
+            for (Map.Entry<Integer, List<AnnotationNode>> entry : existing.entrySet()) {
+                List<AnnotationNode> annotationNodes = new ArrayList<>(entry.getValue());
+                for (Iterator<AnnotationNode> iterator = annotationNodes.iterator(); iterator.hasNext();) {
+                    AnnotationNode annotation = iterator.next();
+                    if (replacement.getClassNode().getName().equals(annotation.getClassNode().getName())) {
                         if (mergeParams) {
-                            mergeParameters(replacement, existing);
+                            mergeParameters(replacement, annotation);
                         }
                         iterator.remove();
                     }
                 }
-                existingMap.put(key, annotationNodes);
+                existing.put(entry.getKey(), annotationNodes);
             }
         }
     }
 
-    private static void deleteReplacement(boolean mergeParams, Map<Integer, List<AnnotationNode>> existingMap, List<AnnotationNode> replacements) {
-        Iterator<AnnotationNode> nodeIterator = replacements.iterator();
-        while (nodeIterator.hasNext()) {
+    private static void deleteReplacement(final boolean mergeParams, final Map<Integer, List<AnnotationNode>> existing, final List<AnnotationNode> replacements) {
+        for (Iterator<AnnotationNode> nodeIterator = replacements.iterator(); nodeIterator.hasNext();) {
             boolean remove = false;
             AnnotationNode replacement = nodeIterator.next();
-            for (Map.Entry<Integer, List<AnnotationNode>> entry : existingMap.entrySet()) {
-                for (AnnotationNode existing : entry.getValue()) {
-                    if (replacement.getClassNode().getName().equals(existing.getClassNode().getName())) {
+            for (Map.Entry<Integer, List<AnnotationNode>> entry : existing.entrySet()) {
+                for (AnnotationNode annotation : entry.getValue()) {
+                    if (replacement.getClassNode().getName().equals(annotation.getClassNode().getName())) {
                         if (mergeParams) {
-                            mergeParameters(existing, replacement);
+                            mergeParameters(annotation, replacement);
                         }
                         remove = true;
                     }
@@ -180,7 +168,7 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         }
     }
 
-    private static void mergeParameters(AnnotationNode to, AnnotationNode from) {
+    private static void mergeParameters(final AnnotationNode to, final AnnotationNode from) {
         for (String name : from.getMembers().keySet()) {
             if (to.getMember(name) == null) {
                 to.setMember(name, from.getMember(name));
@@ -188,40 +176,25 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         }
     }
 
-    private void assertStringConstant(Expression exp) {
-        if (exp == null) return;
-        if (!(exp instanceof ConstantExpression)) {
-            source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException(
-                    "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()),
-                    source));
-        }
-        ConstantExpression ce = (ConstantExpression) exp;
-        if (!(ce.getValue() instanceof String)) {
-            source.getErrorCollector().addErrorAndContinue(new SyntaxErrorMessage(new SyntaxException(
-                    "Expected a String constant.", exp.getLineNumber(), exp.getColumnNumber()),
-                    source));
-        }
-    }
-
-    private void findCollectedAnnotations(AnnotationNode aliasNode, AnnotatedNode origin, Integer index, Map<Integer, AnnotationCollectorMode> modes, Map<Integer, List<AnnotationNode>> existing, Map<Integer, List<AnnotationNode>> replacements) {
-        ClassNode classNode = aliasNode.getClassNode();
-        for (AnnotationNode annotation : classNode.getAnnotations()) {
+    private void findCollectedAnnotations(final AnnotationNode alias, final AnnotatedNode origin, final Integer index, final Map<Integer, AnnotationCollectorMode> modes, final Map<Integer, List<AnnotationNode>> existing, final Map<Integer, List<AnnotationNode>> replacements) {
+        for (AnnotationNode annotation : alias.getClassNode().getAnnotations()) {
             if (annotation.getClassNode().getName().equals(AnnotationCollector.class.getName())) {
-                AnnotationCollectorMode mode = getMode(annotation);
-                if (mode == null) {
-                    mode = AnnotationCollectorMode.DUPLICATE;
-                }
-                modes.put(index, mode);
-                Expression processorExp = annotation.getMember("processor");
+                Expression mode = annotation.getMember("mode");
+                modes.put(index, Optional.ofNullable(mode)
+                    .map(exp -> evaluateExpression(exp, source.getConfiguration()))
+                    .map(val -> (AnnotationCollectorMode) val)
+                    .orElse(AnnotationCollectorMode.DUPLICATE)
+                );
+
+                Expression processor = annotation.getMember("processor");
                 AnnotationCollectorTransform act = null;
-                assertStringConstant(processorExp);
-                if (processorExp != null) {
-                    String className = (String) ((ConstantExpression) processorExp).getValue();
-                    Class klass = loadTransformClass(className, aliasNode);
+                if (processor != null) {
+                    String className = (String) evaluateExpression(processor, source.getConfiguration());
+                    Class<?> klass = loadTransformClass(className, alias);
                     if (klass != null) {
                         try {
                             act = (AnnotationCollectorTransform) klass.getDeclaredConstructor().newInstance();
-                        } catch (InstantiationException | IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
+                        } catch (ReflectiveOperationException e) {
                             source.getErrorCollector().addErrorAndContinue(new ExceptionMessage(e, true, source));
                         }
                     }
@@ -229,104 +202,83 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
                     act = new AnnotationCollectorTransform();
                 }
                 if (act != null) {
-                    replacements.put(index, act.visit(annotation, aliasNode, origin, source));
+                    replacements.put(index, act.visit(annotation, alias, origin, source));
                     return;
                 }
             }
         }
         if (!replacements.containsKey(index)) {
-            existing.put(index, Collections.singletonList(aliasNode));
+            existing.put(index, Collections.singletonList(alias));
         }
     }
 
-    private static AnnotationCollectorMode getMode(AnnotationNode node) {
-        final Expression member = node.getMember("mode");
-        if (member instanceof PropertyExpression) {
-            PropertyExpression prop = (PropertyExpression) member;
-            Expression oe = prop.getObjectExpression();
-            if (oe instanceof ClassExpression) {
-                ClassExpression ce = (ClassExpression) oe;
-                if (ce.getType().getName().equals("groovy.transform.AnnotationCollectorMode")) {
-                    return AnnotationCollectorMode.valueOf(prop.getPropertyAsString());
-                }
-            }
-        }
-        return null;
-    }
-
-    private void addTransformsToClassNode(AnnotationNode annotation, Annotation transformClassAnnotation) {
+    private void addTransformsToClassNode(final AnnotationNode annotation, final Annotation transformClassAnnotation) {
         List<String> transformClassNames = getTransformClassNames(annotation, transformClassAnnotation);
 
         if (transformClassNames.isEmpty()) {
-            source.getErrorCollector().addError(new SimpleMessage("@GroovyASTTransformationClass in " +
-                    annotation.getClassNode().getName() + " does not specify any transform class names/classes", source));
+            String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " does not specify any transform class names/classes";
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
         }
 
         for (String transformClass : transformClassNames) {
-            Class klass = loadTransformClass(transformClass, annotation);
+            Class<?> klass = loadTransformClass(transformClass, annotation);
             if (klass != null) {
                 verifyAndAddTransform(annotation, klass);
             }
         }
     }
 
-    private Class loadTransformClass(String transformClass, AnnotationNode annotation) {
+    private Class<?> loadTransformClass(final String transformClass, final AnnotationNode annotation) {
         try {
             return transformLoader.loadClass(transformClass, false, true, false);
-        } catch (ClassNotFoundException e) {
-            source.getErrorCollector().addErrorAndContinue(
-                    new SimpleMessage(
-                            "Could not find class for Transformation Processor " + transformClass
-                                    + " declared by " + annotation.getClassNode().getName(),
-                            source));
+        } catch (ReflectiveOperationException | LinkageError e) {
+            String error = "Could not find class for Transformation Processor " + transformClass + " declared by " + annotation.getClassNode().getName();
+            source.getErrorCollector().addErrorAndContinue(new SimpleMessage(error, source));
         }
         return null;
     }
 
-    private void verifyAndAddTransform(AnnotationNode annotation, Class klass) {
+    private void verifyAndAddTransform(final AnnotationNode annotation, final Class<?> klass) {
         verifyClass(annotation, klass);
         verifyCompilePhase(annotation, klass);
         addTransform(annotation, klass);
     }
 
-    private void verifyCompilePhase(AnnotationNode annotation, Class<?> klass) {
+    private void verifyClass(final AnnotationNode annotation, final Class<?> klass) {
+        if (!ASTTransformation.class.isAssignableFrom(klass)) {
+            String error = "Not an ASTTransformation: " + klass.getName() + " declared by " + annotation.getClassNode().getName();
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
+        }
+    }
+
+    private void verifyCompilePhase(final AnnotationNode annotation, final Class<?> klass) {
         GroovyASTTransformation transformationClass = klass.getAnnotation(GroovyASTTransformation.class);
         if (transformationClass != null) {
             CompilePhase specifiedCompilePhase = transformationClass.phase();
             if (specifiedCompilePhase.getPhaseNumber() < CompilePhase.SEMANTIC_ANALYSIS.getPhaseNumber()) {
-                source.getErrorCollector().addError(
-                        new SimpleMessage(
-                                annotation.getClassNode().getName() + " is defined to be run in compile phase " + specifiedCompilePhase + ". Local AST transformations must run in " + CompilePhase.SEMANTIC_ANALYSIS + " or later!",
-                                source));
+                String error = annotation.getClassNode().getName() + " is defined to be run in compile phase " + specifiedCompilePhase + ". Local AST transformations must run in " + CompilePhase.SEMANTIC_ANALYSIS + " or later!";
+                source.getErrorCollector().addError(new SimpleMessage(error, source));
             }
-
         } else {
-            source.getErrorCollector().addError(
-                    new SimpleMessage("AST transformation implementation classes must be annotated with " + GroovyASTTransformation.class.getName() + ". " + klass.getName() + " lacks this annotation.", source));
-        }
-    }
-
-    private void verifyClass(AnnotationNode annotation, Class klass) {
-        if (!ASTTransformation.class.isAssignableFrom(klass)) {
-            source.getErrorCollector().addError(new SimpleMessage("Not an ASTTransformation: " +
-                    klass.getName() + " declared by " + annotation.getClassNode().getName(), source));
+            String error = "AST transformation implementation classes must be annotated with " + GroovyASTTransformation.class.getName() + ". " + klass.getName() + " lacks this annotation.";
+            source.getErrorCollector().addError(new SimpleMessage(error, source));
         }
     }
 
     @SuppressWarnings("unchecked")
-    private void addTransform(AnnotationNode annotation, Class klass) {
+    private void addTransform(final AnnotationNode annotation, final Class<?> klass) {
         boolean apply = !Traits.isTrait(classNode) || klass == TraitASTTransformation.class;
         if (apply) {
-            classNode.addTransform(klass, annotation);
+            classNode.addTransform((Class<? extends ASTTransformation>) klass, annotation);
         }
     }
 
-    private static Annotation getTransformClassAnnotation(ClassNode annotatedType) {
+    private static Annotation getTransformClassAnnotation(final ClassNode annotatedType) {
         if (!annotatedType.isResolved()) return null;
 
         for (Annotation ann : annotatedType.getTypeClass().getAnnotations()) {
             // because compiler clients are free to choose any GroovyClassLoader for
-            // resolving ClassNodeS such as annotatedType, we have to compare by name,
+            // resolving ClassNodes such as annotatedType, we have to compare by name,
             // and cannot cast the return value to GroovyASTTransformationClass
             if (ann.annotationType().getName().equals(GroovyASTTransformationClass.class.getName())) {
                 return ann;
@@ -336,29 +288,26 @@ public class ASTTransformationCollectorCodeVisitor extends ClassCodeVisitorSuppo
         return null;
     }
 
-    private List<String> getTransformClassNames(AnnotationNode annotation, Annotation transformClassAnnotation) {
-        List<String> result = new ArrayList<String>();
-
+    private List<String> getTransformClassNames(final AnnotationNode annotation, final Annotation transformClassAnnotation) {
+        List<String> result = new ArrayList<>();
         try {
             Method valueMethod = transformClassAnnotation.getClass().getMethod("value");
             String[] names = (String[]) valueMethod.invoke(transformClassAnnotation);
             result.addAll(Arrays.asList(names));
 
             Method classesMethod = transformClassAnnotation.getClass().getMethod("classes");
-            Class[] classes = (Class[]) classesMethod.invoke(transformClassAnnotation);
-            for (Class klass : classes) {
+            Class<?>[] classes = (Class[]) classesMethod.invoke(transformClassAnnotation);
+            for (Class<?> klass : classes) {
                 result.add(klass.getName());
             }
 
             if (names.length > 0 && classes.length > 0) {
-                source.getErrorCollector().addError(new SimpleMessage("@GroovyASTTransformationClass in " +
-                        annotation.getClassNode().getName() +
-                        " should specify transforms only by class names or by classes and not by both", source));
+                String error = "@GroovyASTTransformationClass in " + annotation.getClassNode().getName() + " should specify transforms only by class names or by classes and not by both";
+                source.getErrorCollector().addError(new SimpleMessage(error, source));
             }
         } catch (Exception e) {
             source.addException(e);
         }
-
         return result;
     }
 }


[groovy] 10/18: GROOVY-9126: Unreachable line numbers after ARETURN in bytecode (#1095)

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

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

commit 5396ef77a94e579ffa0b669816b7605f3daef00d
Author: Daniel.Sun <su...@apache.org>
AuthorDate: Thu Nov 21 15:44:47 2019 +0800

    GROOVY-9126: Unreachable line numbers after ARETURN in bytecode (#1095)
    
    (cherry picked from commit ecb6c331edf08a0b41ac3ff4b63aae99b85a4b76)
---
 .../groovy/classgen/asm/StatementWriter.java       | 23 +++++++++-
 src/test/groovy/bugs/Groovy9126.groovy             | 51 ++++++++++++++++++++++
 2 files changed, 72 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
index 072d9ed..8459b89 100644
--- a/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
+++ b/src/main/java/org/codehaus/groovy/classgen/asm/StatementWriter.java
@@ -20,6 +20,7 @@ package org.codehaus.groovy.classgen.asm;
 
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.MethodNode;
 import org.codehaus.groovy.ast.Parameter;
 import org.codehaus.groovy.ast.expr.ArgumentListExpression;
 import org.codehaus.groovy.ast.expr.BooleanExpression;
@@ -88,13 +89,16 @@ public class StatementWriter {
         int mark = controller.getOperandStack().getStackLength();
         CompileStack compileStack = controller.getCompileStack();
         compileStack.pushVariableScope(block.getVariableScope());
-        for (Statement statement : block.getStatements()) {
+        List<Statement> statementList = block.getStatements();
+        for (Statement statement : statementList) {
             statement.visit(controller.getAcg());
         }
         compileStack.pop();
 
         // GROOVY-7647
-        if (block.getLastLineNumber() > 0) {
+        if (block.getLastLineNumber() > 0
+                && !methodOrConstructorsLastReturnStatementExists(block) // GROOVY-9126
+        ) {
             MethodVisitor mv = controller.getMethodVisitor();
             Label blockEnd = new Label();
             mv.visitLabel(blockEnd);
@@ -104,6 +108,21 @@ public class StatementWriter {
         controller.getOperandStack().popDownTo(mark);
     }
 
+    private boolean methodOrConstructorsLastReturnStatementExists(BlockStatement block) {
+        MethodNode methodNode = controller.getMethodNode();
+        if (null == methodNode) {
+            methodNode = controller.getConstructorNode();
+        }
+
+        if (null == methodNode || block != methodNode.getCode()) { // check if the block is method/constructor's code
+            return false;
+        }
+
+        List<Statement> statementList = block.getStatements();
+        final int size = statementList.size();
+        return size > 0 && statementList.get(size - 1) instanceof ReturnStatement;
+    }
+
     public void writeForStatement(ForStatement loop) {
         Parameter loopVar = loop.getVariable();
         if (loopVar == ForStatement.FOR_LOOP_DUMMY) {
diff --git a/src/test/groovy/bugs/Groovy9126.groovy b/src/test/groovy/bugs/Groovy9126.groovy
new file mode 100644
index 0000000..3df9633
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9126.groovy
@@ -0,0 +1,51 @@
+/*
+ *  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.codehaus.groovy.classgen.asm.AbstractBytecodeTestCase
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy9126 extends AbstractBytecodeTestCase {
+
+    @Test
+    void testUnreachableBytecode() {
+        def bytecode = compile([method:'nonVoidMethod'],'''
+            @groovy.transform.CompileStatic
+            int nonVoidMethod() {
+                1 * 1
+            }
+        ''')
+
+        assert bytecode.hasStrictSequence(
+                ['public nonVoidMethod()I',
+                 'L0',
+                 'LINENUMBER 4 L0',
+                 'ICONST_1',
+                 'ICONST_1',
+                 'IMUL',
+                 'IRETURN',
+                 'L1',
+                 'FRAME FULL [] [java/lang/Throwable]']
+        )
+    }
+}