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/17 08:53:55 UTC

[groovy] branch GROOVY_3_0_X updated (7785567 -> 5c93020)

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 7785567  Refactor code (closes #1076)
     new 32f6b78  GROOVY-9307: Bump javaparser to 3.15.5 (#1079)
     new d1f9977  minor edits
     new 7b86d85  add notes on joint compiler arguments and refactor minor stuff
     new bc6ee3b  minor edits
     new 3425ba7  fix generics and other minor edits
     new 7b749c2  GROOVY-8423: Do not adjust access modifiers for inner class table
     new 3401515  GROOVY-8310: STC: check closure return type when method type has generic
     new c7894e0  Trivial refactoring: Remove redundant type arguments
     new 7c35699  Trivial refactoring: Remove redundant type cast
     new 2deb426  Trivial refactoring: Remove redundant `if` statement
     new 816195b  Ant: add support for more joint compilation options
     new 45d974a  updated docs for groovyc ant task
     new 58d6ef4  GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
     new 557f889  GROOVY-8955: prevent Matcher.find()'s side-effect on Matcher.asBoolean()
     new abfcecf  consolidate calls to ClassNode#makeArray() and other minor edits
     new 193267d  GROOVY-8446: Antlr2: syntax error for void[] or void...
     new 9f9ea84  Improve the robustness of closing resources
     new 5c93020  GROOVY-8579, GROOVY-8930: check static interface method for direct calls

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:
 build.gradle                                       |   2 +-
 src/main/java/groovy/lang/GroovyClassLoader.java   |   7 +-
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   | 341 ++++------
 .../groovy/antlr/AntlrParserPluginFactory.java     |   3 +-
 .../groovy/classgen/AsmClassGenerator.java         | 686 ++++++++++-----------
 .../groovy/runtime/DefaultGroovyMethods.java       |  16 +-
 .../groovy/runtime/StringGroovyMethods.java        |  34 +-
 .../codehaus/groovy/tools/FileSystemCompiler.java  |  53 +-
 .../groovy/tools/javac/JavacJavaCompiler.java      |  79 +--
 .../transform/stc/StaticTypeCheckingSupport.java   | 179 +++---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 270 ++++----
 src/spec/doc/core-operators.adoc                   |   8 +-
 src/spec/doc/tools-groovyc.adoc                    |  70 ++-
 src/test/gls/innerClass/InnerClassTest.groovy      |  54 +-
 src/test/groovy/RegularExpressionsTest.groovy      |  53 +-
 src/test/groovy/bugs/Groovy8310.groovy             | 118 ++++
 .../bugs/{Groovy9265.groovy => Groovy8439.groovy}  |  31 +-
 src/test/groovy/bugs/Groovy8439Bug.groovy          |  51 --
 .../bugs/{Groovy5318.groovy => Groovy8446.groovy}  |  42 +-
 .../bugs/{Groovy9031.groovy => Groovy9197.groovy}  |  49 +-
 .../groovy/classgen/asm/sc/bugs/Groovy7276.groovy  |  20 +-
 .../groovy/runtime/StringGroovyMethodsTest.java    |  39 +-
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 366 ++++++-----
 .../org/codehaus/groovy/ant/GroovycTest.xml        |  42 +-
 .../org/codehaus/groovy/ant/GroovycTest2.java      |   6 +-
 ...oovycTest2.java => MakesExternalReference.java} |  17 +-
 .../org/codehaus/groovy/ant/commons-lang3-3.4.jar  | Bin 0 -> 434678 bytes
 .../org/codehaus/groovy/ant/GroovycTest.java       |  69 ++-
 .../apache/groovy/parser/antlr4/AstBuilder.java    |  63 +-
 .../test/groovy/groovy/bugs/vm8/Groovy8579.groovy  |  38 +-
 .../groovy/groovy/bugs/vm8/Groovy8579Bug.groovy    |  36 --
 31 files changed, 1472 insertions(+), 1370 deletions(-)
 create mode 100644 src/test/groovy/bugs/Groovy8310.groovy
 copy src/test/groovy/bugs/{Groovy9265.groovy => Groovy8439.groovy} (61%)
 delete mode 100644 src/test/groovy/bugs/Groovy8439Bug.groovy
 copy src/test/groovy/bugs/{Groovy5318.groovy => Groovy8446.groovy} (54%)
 copy src/test/groovy/bugs/{Groovy9031.groovy => Groovy9197.groovy} (52%)
 copy subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/{GroovycTest2.java => MakesExternalReference.java} (70%)
 create mode 100644 subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar
 copy src/test/groovy/bugs/Groovy8223.groovy => subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579.groovy (66%)
 delete mode 100644 subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579Bug.groovy


[groovy] 15/18: consolidate calls to ClassNode#makeArray() and other 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 abfcecf701d690e7f602ebbe4544638d7b5db6a5
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Nov 15 17:08:34 2019 -0600

    consolidate calls to ClassNode#makeArray() and other minor edits
    
    (cherry picked from commit 159e1a9d879e68431cd9d8895d372e598d2d7463)
---
 .../groovy/antlr/AntlrParserPluginFactory.java     |  3 +-
 .../apache/groovy/parser/antlr4/AstBuilder.java    | 60 ++++++++--------------
 2 files changed, 23 insertions(+), 40 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPluginFactory.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPluginFactory.java
index 61bab21..f0f3f9e 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPluginFactory.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPluginFactory.java
@@ -21,10 +21,9 @@ package org.codehaus.groovy.antlr;
 import org.codehaus.groovy.control.ParserPlugin;
 import org.codehaus.groovy.control.ParserPluginFactory;
 
-/**
- */
 @Deprecated
 public class AntlrParserPluginFactory extends ParserPluginFactory {
+    @Deprecated
     public ParserPlugin createParserPlugin() {
         return new AntlrParserPlugin();
     }
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 c6efdec..580f23d 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
@@ -3085,9 +3085,8 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
             if (asBoolean(ctx.arrayInitializer())) {
                 ClassNode elementType = classNode;
                 allDimList = this.visitDims(ctx.dims());
-
-                for (int i = 0, n = allDimList.size() - 1; i < n; i++) {
-                    elementType = elementType.makeArray();
+                for (int i = 0, n = allDimList.size() - 1; i < n; i += 1) {
+                    elementType = this.createArrayType(elementType);
                 }
 
                 arrayExpression =
@@ -3124,7 +3123,7 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
                 Collections.reverse(allDimList);
             }
 
-            arrayExpression.setType(createArrayType(classNode, allDimList));
+            arrayExpression.setType(this.createArrayType(classNode, allDimList));
 
             return configureAST(arrayExpression, ctx);
         }
@@ -3132,15 +3131,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         throw createParsingFailedException("Unsupported creator: " + ctx.getText(), ctx);
     }
 
-    private ClassNode createArrayType(ClassNode classNode, List<List<AnnotationNode>> dimList) {
-        ClassNode arrayType = classNode;
-        for (int i = 0, n = dimList.size(); i < n; i++) {
-            arrayType = arrayType.makeArray();
-            arrayType.addAnnotations(dimList.get(i));
-        }
-        return arrayType;
-    }
-
     private static String nextAnonymousClassName(ClassNode outerClass) {
         int anonymousClassCount = 0;
         for (Iterator<InnerClassNode> it = outerClass.getInnerClasses(); it.hasNext();) {
@@ -4114,6 +4104,19 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         return this.createClassNode(ctx);
     }
 
+    private ClassNode createArrayType(ClassNode elementType, List<List<AnnotationNode>> dimsList) {
+        ClassNode arrayType = elementType;
+        for (int i = 0, n = dimsList.size(); i < n; i += 1) {
+            arrayType = this.createArrayType(arrayType);
+            arrayType.addAnnotations(dimsList.get(i));
+        }
+        return arrayType;
+    }
+
+    private ClassNode createArrayType(ClassNode elementType) {
+        return elementType.makeArray();
+    }
+
     private ClassNode createClassNode(GroovyParserRuleContext ctx) {
         ClassNode result = ClassHelper.make(ctx.getText());
 
@@ -4200,7 +4203,12 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         ClassNode classNode = this.visitType(typeContext);
 
         if (asBoolean(ellipsis)) {
-            classNode = configureAST(classNode.makeArray(), classNode);
+            classNode = this.createArrayType(classNode);
+            if (!asBoolean(typeContext)) {
+                configureAST(classNode, ellipsis);
+            } else {
+                configureAST(classNode, typeContext, configureAST(new ConstantExpression("..."), ellipsis));
+            }
         }
 
         Parameter parameter =
@@ -4411,17 +4419,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         );
     }
 
-    /*
-    private org.codehaus.groovy.syntax.Token createGroovyToken(String text, int startLine, int startColumn) {
-        return new org.codehaus.groovy.syntax.Token(
-                Types.lookup(text, Types.ANY),
-                text,
-                startLine,
-                startColumn
-        );
-    }
-    */
-
     /**
      * set the script source position
      */
@@ -4553,18 +4550,6 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
         parser.addErrorListener(this.createANTLRErrorListener());
     }
 
-    /*
-    private String createExceptionMessage(Throwable t) {
-        StringWriter sw = new StringWriter();
-
-        try (PrintWriter pw = new PrintWriter(sw)) {
-            t.printStackTrace(pw);
-        }
-
-        return sw.toString();
-    }
-    */
-
     private static class DeclarationListStatement extends Statement {
         private final List<ExpressionStatement> declarationStatements;
 
@@ -4678,4 +4663,3 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
 
     private static final String CLASS_NAME = "_CLASS_NAME";
 }
-


[groovy] 16/18: GROOVY-8446: Antlr2: syntax error for void[] or void...

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 193267de8021367537654c6b05d3601d31788ba1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 16 21:00:47 2019 -0600

    GROOVY-8446: Antlr2: syntax error for void[] or void...
    
    NOTE: Antlr4 parser does not recognize "void[]" or "void..." as types;
    the JUnit tests can be switched to the new parser if/when it does.
    
    (cherry picked from commit d99605b902ab3748641e44c3e768cfd072e5e75f)
---
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   | 341 ++++++++-------------
 src/test/groovy/bugs/Groovy8446.groovy             |  67 ++++
 .../apache/groovy/parser/antlr4/AstBuilder.java    |   3 +
 3 files changed, 204 insertions(+), 207 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
index e36d5ca..bf722ef 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
@@ -127,14 +127,14 @@ import java.security.PrivilegedAction;
 import java.util.ArrayList;
 import java.util.HashSet;
 import java.util.Iterator;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Set;
 
 import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
 
 /**
- * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime
+ * A parser plugin which adapts the JSR Antlr Parser to the Groovy runtime.
  */
 @Deprecated
 public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
@@ -142,6 +142,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     private static class AnonymousInnerClassCarrier extends Expression {
         ClassNode innerClass;
 
+        @Override
         public Expression transformExpression(ExpressionTransformer transformer) {
             return null;
         }
@@ -180,15 +181,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected AST ast;
     private ClassNode classNode;
     private MethodNode methodNode;
-    private String[] tokenNames;
-    private boolean enumConstantBeingDef = false;
-    private boolean forStatementBeingDef = false;
-    private boolean annotationBeingDef = false;
-    private boolean firstParamIsVarArg = false;
-    private boolean firstParam = false;
-
-    public /*final*/ Reduction parseCST(final SourceUnit sourceUnit, Reader reader) throws CompilationFailedException {
-        final SourceBuffer sourceBuffer = new SourceBuffer();
+    protected String[] tokenNames;
+    private boolean enumConstantBeingDef;
+    private boolean forStatementBeingDef;
+    private boolean annotationBeingDef;
+    private boolean firstParamIsVarArg;
+    private boolean firstParam;
+
+    public Reduction parseCST(SourceUnit sourceUnit, Reader reader) throws CompilationFailedException {
+        SourceBuffer sourceBuffer = new SourceBuffer();
         transformCSTIntoAST(sourceUnit, reader, sourceBuffer);
         processAST();
         return outputAST(sourceUnit, sourceBuffer);
@@ -199,8 +200,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
         setController(sourceUnit);
 
-        // TODO find a way to inject any GroovyLexer/GroovyRecognizer
-
         UnicodeEscapingReader unicodeReader = new UnicodeEscapingReader(reader, sourceBuffer);
         UnicodeLexerSharedInputState inputState = new UnicodeLexerSharedInputState(unicodeReader);
         GroovyLexer lexer = new GroovyLexer(inputState);
@@ -238,12 +237,10 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     public Reduction outputAST(final SourceUnit sourceUnit, final SourceBuffer sourceBuffer) {
-        AccessController.doPrivileged((PrivilegedAction) () -> {
+        return AccessController.doPrivileged((PrivilegedAction<Reduction>) () -> {
             outputASTInVariousFormsIfNeeded(sourceUnit, sourceBuffer);
             return null;
         });
-
-        return null; //new Reduction(Tpken.EOF);
     }
 
     private void outputASTInVariousFormsIfNeeded(SourceUnit sourceUnit, SourceBuffer sourceBuffer) {
@@ -251,7 +248,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         String formatProp = System.getProperty("ANTLR.AST".toLowerCase()); // uppercase to hide from jarjar
 
         if ("xml".equals(formatProp)) {
-            saveAsXML(sourceUnit.getName(), ast);
+            XStreamUtils.serialize(sourceUnit.getName() + ".antlr", ast);
         }
 
         // 'pretty printer' output of AST
@@ -307,10 +304,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         }
     }
 
-    private static void saveAsXML(String name, AST ast) {
-        XStreamUtils.serialize(name+".antlr", ast);
-    }
-
     public ModuleNode buildAST(SourceUnit sourceUnit, ClassLoader classLoader, Reduction cst) throws ParserException {
         setClassLoader(classLoader);
         makeModule();
@@ -321,7 +314,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             }
 
             // set the script source position
-
             ClassNode scriptClassNode = output.getScriptClassDummy();
             if (scriptClassNode != null) {
                 List<Statement> statements = output.getStatementBlock().getStatements();
@@ -334,15 +326,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                     scriptClassNode.setLastLineNumber(lastStatement.getLastLineNumber());
                 }
             }
-        }
-        catch (ASTRuntimeException e) {
+        } catch (ASTRuntimeException e) {
             throw new ASTParserException(e.getMessage() + ". File: " + sourceUnit.getName(), e);
         }
+        ast = null;
         return output;
     }
 
     /**
-     * Converts the Antlr AST to the Groovy AST
+     * Converts the Antlr AST to the Groovy AST.
      */
     protected void convertGroovy(AST node) {
         while (node != null) {
@@ -378,10 +370,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                     annotationDef(node);
                     break;
 
-                default: {
-                    Statement statement = statement(node);
-                    output.addStatement(statement);
-                }
+                default:
+                    output.addStatement(statement(node));
             }
             node = node.getNextSibling();
         }
@@ -397,9 +387,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             processAnnotations(annotations, node);
             node = node.getNextSibling();
         }
-        String name = qualifiedName(node);
-        // TODO should we check package node doesn't already exist? conflict?
-        PackageNode packageNode = setPackage(name, annotations);
+        PackageNode packageNode = setPackage(qualifiedName(node), annotations);
         configureAST(packageNode, packageDef);
     }
 
@@ -417,11 +405,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 node = node.getNextSibling();
             }
 
+            ImportNode imp;
             String alias = null;
+            AST aliasNode = null;
             if (isType(LITERAL_as, node)) {
                 //import is like "import Foo as Bar"
                 node = node.getFirstChild();
-                AST aliasNode = node.getNextSibling();
+                aliasNode = node.getNextSibling();
                 alias = identifier(aliasNode);
             }
 
@@ -431,6 +421,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 ClassNode type = ClassHelper.make(name);
                 configureAST(type, importNode);
                 addImport(type, name, alias, annotations);
+                imp = last(output.getImports());
+                configureAST(imp, importNode);
                 return;
             }
 
@@ -444,14 +436,17 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                     ClassNode type = ClassHelper.make(packageName);
                     configureAST(type, importNode);
                     addStaticStarImport(type, packageName, annotations);
+                    imp = output.getStaticStarImports().get(packageName);
+                    configureAST(imp, importNode);
                 } else {
                     // import is like "import foo.*"
                     addStarImport(packageName, annotations);
+                    imp = last(output.getStarImports());
+                    configureAST(imp, importNode);
                 }
 
-                if (alias != null) throw new GroovyBugError(
-                        "imports like 'import foo.* as Bar' are not " +
-                                "supported and should be caught by the grammar");
+                if (alias != null)
+                    throw new GroovyBugError("imports like 'import foo.* as Bar' are not supported and should be caught by the grammar");
             } else {
                 String name = identifier(nameNode);
                 if (isStatic) {
@@ -460,18 +455,22 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                     ClassNode type = ClassHelper.make(packageName);
                     configureAST(type, importNode);
                     addStaticImport(type, name, alias, annotations);
+                    imp = output.getStaticImports().get(alias == null ? name : alias);
+                    configureAST(imp, importNode);
                 } else {
                     // import is like "import foo.Bar"
                     ClassNode type = ClassHelper.make(packageName + "." + name);
                     configureAST(type, importNode);
                     addImport(type, name, alias, annotations);
+                    imp = last(output.getImports());
+                    configureAST(imp, importNode);
                 }
             }
         } finally {
             // we're using node metadata here in order to fix GROOVY-6094
             // without breaking external APIs
             Object node = output.getNodeMetaData(ImportNode.class);
-            if (node!=null && node!=ImportNode.class) {
+            if (node != null && node != ImportNode.class) {
                 configureAST((ImportNode)node, importNode);
             }
             output.removeNodeMetaData(ImportNode.class);
@@ -607,7 +606,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected Expression anonymousInnerClassDef(AST node) {
         ClassNode oldNode = classNode;
         ClassNode outerClass = getClassOrScript(oldNode);
-        String innerClassName = outerClass.getName() + '$' + (anonymousClassCount(outerClass) + 1);
+        String innerClassName = outerClass.getName() + "$" + (anonymousClassCount(outerClass) + 1);
         if (enumConstantBeingDef) {
             classNode = new EnumConstantClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
         } else {
@@ -615,14 +614,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         }
         ((InnerClassNode) classNode).setAnonymous(true);
         classNode.setEnclosingMethod(methodNode);
+        configureAST(classNode, node);
 
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
-        output.addClass(classNode);
+
         AnonymousInnerClassCarrier ret = new AnonymousInnerClassCarrier();
         ret.innerClass = classNode;
+        output.addClass(classNode);
         classNode = oldNode;
-
         return ret;
     }
 
@@ -768,10 +768,11 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         String enumName = (classNode != null ? name : dot(getPackageName(), name));
         ClassNode enumClass = EnumHelper.makeEnumNode(enumName, modifiers, interfaces, classNode);
         enumClass.setSyntheticPublic(syntheticPublic);
-        ClassNode oldNode = classNode;
         enumClass.addAnnotations(annotations);
+        configureAST(enumClass, enumNode);
+
+        ClassNode oldNode = classNode;
         classNode = enumClass;
-        configureAST(classNode, enumNode);
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
         classNode = oldNode;
@@ -923,9 +924,10 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         if ((modifiers & Opcodes.ACC_ABSTRACT) == 0) {
             if (node == null) {
                 throw new ASTRuntimeException(methodDef, "You defined a method without a body. Try adding a body, or declare it abstract.");
+            } else {
+                assertNodeType(SLIST, node);
+                code = statementList(node);
             }
-            assertNodeType(SLIST, node);
-            code = statementList(node);
         } else if (node != null) {
             if (classNode != null && classNode.isAnnotationDefinition()) {
                 code = statement(node);
@@ -1046,7 +1048,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             initialValue = getDefaultValueForPrimitive(type);
         }
 
-
         FieldNode fieldNode = new FieldNode(name, modifiers, type, classNode, initialValue);
         fieldNode.addAnnotations(annotations);
         configureAST(fieldNode, fieldDef);
@@ -1162,7 +1163,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         ClassNode type = ClassHelper.DYNAMIC_TYPE;
         if (isType(TYPE, node)) {
             type = makeTypeWithArguments(node);
-            if (variableParameterDef) type = type.makeArray();
+            if (variableParameterDef)
+                type = makeArray(type, node);
             node = node.getNextSibling();
         }
 
@@ -1289,8 +1291,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected AnnotationNode annotation(AST annotationNode) {
         annotationBeingDef = true;
         AST node = annotationNode.getFirstChild();
-        String name = qualifiedName(node);
-        AnnotationNode annotatedNode = new AnnotationNode(ClassHelper.make(name));
+        AnnotationNode annotatedNode = new AnnotationNode(ClassHelper.make(qualifiedName(node)));
         configureAST(annotatedNode, annotationNode);
         while (true) {
             node = node.getNextSibling();
@@ -1310,7 +1311,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return annotatedNode;
     }
 
-
     // Statements
     //-------------------------------------------------------------------------
 
@@ -1396,10 +1396,10 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected Statement statementListNoChild(AST node, AST alternativeConfigureNode) {
         BlockStatement block = siblingsToBlockStatement(node);
         // alternativeConfigureNode is used only to set the source position
-        if (node != null) {
-            configureAST(block, node);
-        } else {
+        if (alternativeConfigureNode != null) {
             configureAST(block, alternativeConfigureNode);
+        } else if (node != null) {
+            configureAST(block, node);
         }
         return block;
     }
@@ -1606,15 +1606,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         Expression expression = expression(node);
         Statement defaultStatement = EmptyStatement.INSTANCE;
 
-        List list = new ArrayList();
+        List<CaseStatement> caseStatements = new ArrayList<>();
         for (node = node.getNextSibling(); isType(CASE_GROUP, node); node = node.getNextSibling()) {
             Statement tmpDefaultStatement;
             AST child = node.getFirstChild();
             if (isType(LITERAL_case, child)) {
-                List cases = new LinkedList();
                 // default statement can be grouped with previous case
-                tmpDefaultStatement = caseStatements(child, cases);
-                list.addAll(cases);
+                tmpDefaultStatement = caseStatements(child, caseStatements);
             } else {
                 tmpDefaultStatement = statement(child.getNextSibling());
             }
@@ -1629,13 +1627,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         if (node != null) {
             unknownAST(node);
         }
-        SwitchStatement switchStatement = new SwitchStatement(expression, list, defaultStatement);
+        SwitchStatement switchStatement = new SwitchStatement(expression, caseStatements, defaultStatement);
         configureAST(switchStatement, switchNode);
         return switchStatement;
     }
 
-    protected Statement caseStatements(AST node, List cases) {
-        List<Expression> expressions = new LinkedList<>();
+    protected Statement caseStatements(AST node, List<CaseStatement> cases) {
+        List<Expression> expressions = new ArrayList<>();
         Statement statement = EmptyStatement.INSTANCE;
         Statement defaultStatement = EmptyStatement.INSTANCE;
         AST nextSibling = node;
@@ -1652,10 +1650,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 statement = statement(nextSibling);
             }
         }
-        Iterator iterator = expressions.iterator();
-        while (iterator.hasNext()) {
-            Expression expr = (Expression) iterator.next();
-            Statement stmt;
+        for (Iterator<Expression> iterator = expressions.iterator(); iterator.hasNext(); ) {
+            Expression expr = iterator.next();
+            CaseStatement stmt;
             if (iterator.hasNext()) {
                 stmt = new CaseStatement(expr, EmptyStatement.INSTANCE);
             } else {
@@ -1721,9 +1718,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected List<CatchStatement> catchStatement(AST catchNode) {
         AST node = catchNode.getFirstChild();
-        List<CatchStatement> catches = new LinkedList<>();
+        List<CatchStatement> catches = new ArrayList<>();
         if (MULTICATCH == node.getType()) {
-            final AST multicatches = node.getFirstChild();
+            AST multicatches = node.getFirstChild();
             if (multicatches.getType() != MULTICATCH_TYPES) {
                 // catch (e)
                 // catch (def e)
@@ -1734,7 +1731,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 catches.add(answer);
             } else {
                 // catch (Exception e)
-                // catch (Exception1 | Exception2 e)
+                // catch (java.lang.Exception e)
+                // catch (Exception1 | foo.bar.Exception2 e)
                 AST exceptionNodes = multicatches.getFirstChild();
                 String variable = identifier(multicatches.getNextSibling());
                 while (exceptionNodes != null) {
@@ -1772,7 +1770,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return whileStatement;
     }
 
-
     // Expressions
     //-------------------------------------------------------------------------
 
@@ -1800,7 +1797,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         int type = node.getType();
         switch (type) {
             case EXPR:
-                return expression(node.getFirstChild());
+                Expression expression = expression(node.getFirstChild());
+                return expression;
 
             case ELIST:
                 return expressionList(node);
@@ -1861,10 +1859,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case SPREAD_MAP_ARG:
                 return spreadMapExpression(node);
 
-            // commented out of groovy.g due to non determinisms
-            //case MEMBER_POINTER_DEFAULT:
-            //    return defaultMethodPointerExpression(node);
-
             case MEMBER_POINTER:
                 return methodPointerExpression(node);
 
@@ -1880,14 +1874,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case TYPECAST:
                 return castExpression(node);
 
-            // literals
-
             case LITERAL_true:
                 return literalExpression(node, Boolean.TRUE);
+
             case LITERAL_false:
                 return literalExpression(node, Boolean.FALSE);
+
             case LITERAL_null:
                 return literalExpression(node, null);
+
             case STRING_LITERAL:
                 return literalExpression(node, node.getText());
 
@@ -1921,23 +1916,19 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case UNARY_PLUS:
                 return unaryPlusExpression(node);
 
-            // Prefix expressions
             case INC:
                 return prefixExpression(node, Types.PLUS_PLUS);
 
             case DEC:
                 return prefixExpression(node, Types.MINUS_MINUS);
 
-            // Postfix expressions
             case POST_INC:
                 return postfixExpression(node, Types.PLUS_PLUS);
 
             case POST_DEC:
                 return postfixExpression(node, Types.MINUS_MINUS);
 
-
             // Binary expressions
-
             case ASSIGN:
                 return binaryExpression(Types.ASSIGN, node);
 
@@ -1968,18 +1959,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case GE:
                 return binaryExpression(Types.COMPARE_GREATER_THAN_EQUAL, node);
 
-            /**
-             * TODO treble equal?
-             return binaryExpression(Types.COMPARE_IDENTICAL, node);
-
-             case ???:
-             return binaryExpression(Types.LOGICAL_AND_EQUAL, node);
-
-             case ???:
-             return binaryExpression(Types.LOGICAL_OR_EQUAL, node);
-
-             */
-
             case LAND:
                 return binaryExpression(Types.LOGICAL_AND, node);
 
@@ -2004,42 +1983,36 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case BXOR_ASSIGN:
                 return binaryExpression(Types.BITWISE_XOR_EQUAL, node);
 
-
             case PLUS:
                 return binaryExpression(Types.PLUS, node);
 
             case PLUS_ASSIGN:
                 return binaryExpression(Types.PLUS_EQUAL, node);
 
-
             case MINUS:
                 return binaryExpression(Types.MINUS, node);
 
             case MINUS_ASSIGN:
                 return binaryExpression(Types.MINUS_EQUAL, node);
 
-
             case STAR:
                 return binaryExpression(Types.MULTIPLY, node);
 
             case STAR_ASSIGN:
                 return binaryExpression(Types.MULTIPLY_EQUAL, node);
 
-
             case STAR_STAR:
                 return binaryExpression(Types.POWER, node);
 
             case STAR_STAR_ASSIGN:
                 return binaryExpression(Types.POWER_EQUAL, node);
 
-
             case DIV:
                 return binaryExpression(Types.DIVIDE, node);
 
             case DIV_ASSIGN:
                 return binaryExpression(Types.DIVIDE_EQUAL, node);
 
-
             case MOD:
                 return binaryExpression(Types.MOD, node);
 
@@ -2074,7 +2047,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case REGEX_MATCH:
                 return binaryExpression(Types.MATCH_REGEX, node);
 
-
             // Ranges
             case RANGE_INCLUSIVE:
                 return rangeExpression(node, true);
@@ -2089,7 +2061,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 return binaryExpression(Types.KEYWORD_IN, node);
 
             case ANNOTATION:
-                return new AnnotationConstantExpression(annotation(node));
+                expression = new AnnotationConstantExpression(annotation(node));
+                configureAST(expression, node);
+                return expression;
 
             case CLOSURE_LIST:
                 return closureListExpression(node);
@@ -2125,7 +2099,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     private ClosureListExpression closureListExpression(AST node) {
         isClosureListExpressionAllowedHere(node);
         AST exprNode = node.getFirstChild();
-        List<Expression> list = new LinkedList<>();
+        List<Expression> list = new ArrayList<>();
         while (exprNode != null) {
             if (isType(EXPR, exprNode)) {
                 Expression expr = expression(exprNode);
@@ -2184,7 +2158,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return variableExpression;
     }
 
-    protected Expression literalExpression(AST node, Object value) {
+    protected ConstantExpression literalExpression(AST node, Object value) {
         ConstantExpression constantExpression = new ConstantExpression(value, value instanceof Boolean);
         configureAST(constantExpression, node);
         return constantExpression;
@@ -2232,16 +2206,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return methodPointerExpression;
     }
 
-/*  commented out due to groovy.g non-determinisms
-  protected Expression defaultMethodPointerExpression(AST node) {
-        AST exprNode = node.getFirstChild();
-        String methodName = exprNode.toString();
-        MethodPointerExpression methodPointerExpression = new MethodPointerExpression(null, methodName);
-        configureAST(methodPointerExpression, node);
-        return methodPointerExpression;
-    }
-*/
-
     protected Expression listExpression(AST listNode) {
         List<Expression> expressions = new ArrayList<>();
         AST elist = listNode.getFirstChild();
@@ -2264,11 +2228,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return listExpression;
     }
 
-    /**
-     * Typically only used for map constructors I think?
-     */
     protected Expression mapExpression(AST mapNode) {
-        List expressions = new ArrayList();
+        List<MapEntryExpression> entryExpressions = new ArrayList<>();
         AST elist = mapNode.getFirstChild();
         if (elist != null) {  // totally empty in the case of [:]
             assertNodeType(ELIST, elist);
@@ -2279,15 +2240,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                         break;  // legal cases
                     case SPREAD_ARG:
                         assertNodeType(SPREAD_MAP_ARG, node);
-                        break;  // helpful error
+                        break;
                     default:
                         assertNodeType(LABELED_ARG, node);
-                        break;  // helpful error
+                        break;
                 }
-                expressions.add(mapEntryExpression(node));
+                entryExpressions.add(mapEntryExpression(node));
             }
         }
-        MapExpression mapExpression = new MapExpression(expressions);
+        MapExpression mapExpression = new MapExpression(entryExpressions);
         configureAST(mapExpression, mapNode);
         return mapExpression;
     }
@@ -2311,7 +2272,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         }
     }
 
-
     protected Expression instanceofExpression(AST node) {
         AST leftNode = node.getFirstChild();
         Expression leftExpression = expression(leftNode);
@@ -2340,7 +2300,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         AST rightNode = leftNode.getNextSibling();
         ClassNode type = makeTypeWithArguments(rightNode);
 
-        return CastExpression.asExpression(type, leftExpression);
+        CastExpression asExpression = CastExpression.asExpression(type, leftExpression);
+        configureAST(asExpression, node);
+        return asExpression;
     }
 
     protected Expression castExpression(AST castNode) {
@@ -2356,7 +2318,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return castExpression;
     }
 
-
     protected Expression indexExpression(AST indexNode) {
         AST bracket = indexNode.getFirstChild();
         AST leftNode = bracket.getNextSibling();
@@ -2476,6 +2437,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 if (property instanceof VariableExpression) {
                     VariableExpression ve = (VariableExpression) property;
                     property = new ConstantExpression(ve.getName());
+                    property.setSourcePosition(ve);
                 }
 
                 PropertyExpression propertyExpression = new PropertyExpression(leftExpression, property, node.getType() != DOT);
@@ -2531,8 +2493,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 objectExpression = VariableExpression.SUPER_EXPRESSION;
             }
         } else if (isPrimitiveTypeLiteral(selector)) {
-            throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText()
-                    + " cannot be used as a method name");
+            throw new ASTRuntimeException(selector, "Primitive type literal: " + selector.getText() + " cannot be used as a method name");
         } else if (isType(SELECT_SLOT, selector)) {
             Expression field = expression(selector.getFirstChild(), true);
             AttributeExpression attributeExpression = new AttributeExpression(objectExpression, field, node.getType() != DOT);
@@ -2551,7 +2512,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             objectExpression = expression(selector, true);
         }
 
-        // if node text is found to be "super"/"this" when a method call is being processed, it is a 
+        // if node text is found to be "super"/"this" when a method call is being processed, it is a
         // call like this(..)/super(..) after the first statement, which shouldn't be allowed. GROOVY-2836
         if (selector.getText().equals("this") || selector.getText().equals("super")) {
             if (!(annotationBeingDef && selector.getText().equals("super"))) {
@@ -2606,7 +2567,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             if (expressionNode == null) {
                 throw new ASTRuntimeException(elist, "No expression for the array constructor call");
             }
-            List size = arraySizeExpression(expressionNode);
+            List<Expression> size = arraySizeExpression(expressionNode);
             ArrayExpression arrayExpression = new ArrayExpression(type, null, size);
             configureAST(arrayExpression, constructorCallNode);
             return arrayExpression;
@@ -2643,8 +2604,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return null;
     }
 
-    protected List arraySizeExpression(AST node) {
-        List list;
+    protected List<Expression> arraySizeExpression(AST node) {
+        List<Expression> list;
         Expression size = null;
         if (isType(ARRAY_DECLARATOR, node)) {
             AST right = node.getNextSibling();
@@ -2660,7 +2621,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             list = arraySizeExpression(child);
         } else {
             size = expression(node);
-            list = new ArrayList();
+            list = new ArrayList<>();
         }
         list.add(size);
         return list;
@@ -2678,7 +2639,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected Expression arguments(AST elist) {
-        List expressionList = new ArrayList();
+        List expressionList = new ArrayList<>();
         // FIXME: all labeled arguments should follow any unlabeled arguments
         boolean namedArguments = false;
         for (AST node = elist; node != null; node = node.getNextSibling()) {
@@ -2724,19 +2685,17 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         }
     }
 
-    private static void checkDuplicateNamedParams(AST elist, List expressionList) {
+    private static void checkDuplicateNamedParams(AST elist, List<MapEntryExpression> expressionList) {
         if (expressionList.isEmpty()) return;
 
         Set<String> namedArgumentNames = new HashSet<>();
-        for (Object expression : expressionList) {
-            MapEntryExpression meExp = (MapEntryExpression) expression;
+        for (MapEntryExpression meExp : expressionList) {
             if (meExp.getKeyExpression() instanceof ConstantExpression) {
                 String argName = meExp.getKeyExpression().getText();
                 if (!namedArgumentNames.contains(argName)) {
                     namedArgumentNames.add(argName);
                 } else {
-                    throw new ASTRuntimeException(elist, "Duplicate named parameter '" + argName
-                            + "' found.");
+                    throw new ASTRuntimeException(elist, "Duplicate named parameter '" + argName + "' found.");
                 }
             }
         }
@@ -2835,6 +2794,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected Expression unaryPlusExpression(AST unaryPlusExpr) {
         AST node = unaryPlusExpr.getFirstChild();
+        UnaryPlusExpression unaryPlusExpression = new UnaryPlusExpression(expression(node));
+        configureAST(unaryPlusExpression, unaryPlusExpr);
         switch (node.getType()) {
             case NUM_DOUBLE:
             case NUM_FLOAT:
@@ -2842,11 +2803,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case NUM_BIG_INT:
             case NUM_INT:
             case NUM_LONG:
-                return expression(node);
+                return unaryPlusExpression.getExpression();
 
             default:
-                UnaryPlusExpression unaryPlusExpression = new UnaryPlusExpression(expression(node));
-                configureAST(unaryPlusExpression, unaryPlusExpr);
                 return unaryPlusExpression;
         }
     }
@@ -2870,8 +2829,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected Expression gstring(AST gstringNode) {
-        List strings = new ArrayList();
-        List values = new ArrayList();
+        List<ConstantExpression> strings = new ArrayList<>();
+        List<Expression> values = new ArrayList<>();
 
         StringBuilder buffer = new StringBuilder();
 
@@ -2908,12 +2867,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return gStringExpression;
     }
 
-    protected ClassNode type(AST typeNode) {
-        // TODO intern types?
-        // TODO configureAST(...)
-        return buildName(typeNode.getFirstChild());
-    }
-
     public static String qualifiedName(AST qualifiedNameNode) {
         if (isType(IDENT, qualifiedNameNode)) {
             return qualifiedNameNode.getText();
@@ -3000,7 +2953,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     private List<GenericsType> getTypeArgumentsList(AST node) {
         assertNodeType(TYPE_ARGUMENTS, node);
-        List<GenericsType> typeArgumentList = new LinkedList<>();
+        List<GenericsType> typeArgumentList = new ArrayList<>();
         AST typeArgument = node.getFirstChild();
 
         while (typeArgument != null) {
@@ -3016,58 +2969,60 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         AST boundsRoot = rn.getNextSibling();
         if (boundsRoot == null) return null;
         assertNodeType(boundType, boundsRoot);
-        LinkedList bounds = new LinkedList();
-        for (AST boundsNode = boundsRoot.getFirstChild();
-             boundsNode != null;
-             boundsNode = boundsNode.getNextSibling()
-                ) {
-            ClassNode bound = null;
-            bound = makeTypeWithArguments(boundsNode);
+        List<ClassNode> bounds = new ArrayList<>();
+        for (AST boundsNode = boundsRoot.getFirstChild(); boundsNode != null; boundsNode = boundsNode.getNextSibling()) {
+            ClassNode bound = makeTypeWithArguments(boundsNode);
             configureAST(bound, boundsNode);
             bounds.add(bound);
         }
         if (bounds.isEmpty()) return null;
-        return (ClassNode[]) bounds.toArray(ClassNode.EMPTY_ARRAY);
+        return bounds.toArray(ClassNode.EMPTY_ARRAY);
     }
 
     protected GenericsType[] makeGenericsType(AST rootNode) {
         AST typeParameter = rootNode.getFirstChild();
-        LinkedList ret = new LinkedList();
+        List<GenericsType> generics = new ArrayList<>();
         assertNodeType(TYPE_PARAMETER, typeParameter);
 
         while (isType(TYPE_PARAMETER, typeParameter)) {
-            AST typeNode = typeParameter.getFirstChild();
-            ClassNode type = makeType(typeParameter);
-
-            GenericsType gt = new GenericsType(type, makeGenericsBounds(typeNode, TYPE_UPPER_BOUNDS), null);
+            GenericsType gt = new GenericsType(makeType(typeParameter), makeGenericsBounds(typeParameter.getFirstChild(), TYPE_UPPER_BOUNDS), null);
             configureAST(gt, typeParameter);
+            generics.add(gt);
 
-            ret.add(gt);
             typeParameter = typeParameter.getNextSibling();
         }
-        return (GenericsType[]) ret.toArray(GenericsType.EMPTY_ARRAY);
+        return generics.toArray(GenericsType.EMPTY_ARRAY);
     }
 
     protected ClassNode makeType(AST typeNode) {
         ClassNode answer = ClassHelper.DYNAMIC_TYPE;
         AST node = typeNode.getFirstChild();
         if (node != null) {
-            if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
-                answer = makeType(node).makeArray();
+            if (isType(ARRAY_DECLARATOR, node) || isType(INDEX_OP, node)) {
+                answer = makeArray(makeTypeWithArguments(node), node);
             } else {
                 checkTypeArgs(node, false);
                 answer = ClassHelper.make(qualifiedName(node));
                 if (answer.isUsingGenerics()) {
-                    ClassNode newAnswer = ClassHelper.makeWithoutCaching(answer.getName());
-                    newAnswer.setRedirect(answer);
-                    answer = newAnswer;
+                    ClassNode proxy = ClassHelper.makeWithoutCaching(answer.getName());
+                    proxy.setRedirect(answer);
+                    answer = proxy;
                 }
+                configureAST(answer, node);
             }
-            configureAST(answer, node);
         }
         return answer;
     }
 
+    private ClassNode makeArray(ClassNode elementType, AST node) {
+        if (elementType.equals(ClassHelper.VOID_TYPE)) {
+            throw new ASTRuntimeException(node.getFirstChild(), "void[] is an invalid type");
+        }
+        ClassNode arrayType = elementType.makeArray();
+        configureAST(arrayType, node);
+        return arrayType;
+    }
+
     private boolean checkTypeArgs(AST node, boolean seenTypeArgs) {
         if (isType(IDENT, node) && seenTypeArgs) {
             throw new ASTRuntimeException(node, "Unexpected type arguments found prior to: " + qualifiedName(node));
@@ -3083,44 +3038,22 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return seenTypeArgs;
     }
 
-    /**
-     * Performs a name resolution to see if the given name is a type from imports,
-     * aliases or newly created classes
-     */
-    /*protected String resolveTypeName(String name, boolean safe) {
-        if (name == null) {
-            return null;
-        }
-        return resolveNewClassOrName(name, safe);
-    }*/
-
-    /**
-     * Extracts an identifier from the Antlr AST and then performs a name resolution
-     * to see if the given name is a type from imports, aliases or newly created classes
-     */
     protected ClassNode buildName(AST node) {
         if (isType(TYPE, node)) {
             node = node.getFirstChild();
         }
-        ClassNode answer = null;
-        if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
-            answer = ClassHelper.make(qualifiedName(node));
-        } else if (isPrimitiveTypeLiteral(node)) {
-            answer = ClassHelper.make(node.getText());
-        } else if (isType(INDEX_OP, node) || isType(ARRAY_DECLARATOR, node)) {
-            AST child = node.getFirstChild();
-            answer = buildName(child).makeArray();
-            configureAST(answer, node);
-            return answer;
+        String name;
+        if (isType(ARRAY_DECLARATOR, node) || isType(INDEX_OP, node)) {
+            return makeArray(buildName(node.getFirstChild()), node);
+        } else if (isType(DOT, node) || isType(OPTIONAL_DOT, node)) {
+            name = qualifiedName(node);
         } else {
-            String identifier = node.getText();
-            answer = ClassHelper.make(identifier);
+            name = node.getText();
         }
+        ClassNode answer = ClassHelper.make(name);
         AST nextSibling = node.getNextSibling();
-        if (isType(INDEX_OP, nextSibling) || isType(ARRAY_DECLARATOR, node)) {
-            answer = answer.makeArray();
-            configureAST(answer, node);
-            return answer;
+        if (isType(ARRAY_DECLARATOR, nextSibling) || isType(INDEX_OP, nextSibling)) {
+            return makeArray(answer, node);
         } else {
             configureAST(answer, node);
             return answer;
@@ -3161,11 +3094,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return identifier(node);
     }
 
-
     // Helper methods
     //-------------------------------------------------------------------------
 
-
     /**
      * Returns true if the modifiers flags contain a visibility modifier
      */
@@ -3175,16 +3106,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected void configureAST(ASTNode node, AST ast) {
         if (ast == null)
-            throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure " + node.getClass().getName() + " with null Node");
-        node.setColumnNumber(ast.getColumn());
+            throw new ASTRuntimeException(ast, "PARSER BUG: Tried to configure " + node.getClass().getName() + " with null AST");
         node.setLineNumber(ast.getLine());
+        node.setColumnNumber(ast.getColumn());
         if (ast instanceof GroovySourceAST) {
-            node.setLastColumnNumber(((GroovySourceAST) ast).getColumnLast());
             node.setLastLineNumber(((GroovySourceAST) ast).getLineLast());
+            node.setLastColumnNumber(((GroovySourceAST) ast).getColumnLast());
         }
-
-        // TODO we could one day store the Antlr AST on the Groovy AST
-        // node.setCSTNode(ast);
     }
 
     protected static Token makeToken(int typeCode, AST node) {
@@ -3196,7 +3124,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return child != null ? child.getText() : null;
     }
 
-
     public static boolean isType(int typeCode, AST node) {
         return node != null && node.getType() == typeCode;
     }
diff --git a/src/test/groovy/bugs/Groovy8446.groovy b/src/test/groovy/bugs/Groovy8446.groovy
new file mode 100644
index 0000000..a6a9ccd
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8446.groovy
@@ -0,0 +1,67 @@
+/*
+ *  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.antlr.AntlrParserPluginFactory
+import org.codehaus.groovy.control.CompilerConfiguration
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy8446 {
+
+    private GroovyShell shell = new GroovyShell(
+        new CompilerConfiguration(pluginFactory: new AntlrParserPluginFactory()))
+
+    @Test
+    void testVoidArray0() {
+        shell.evaluate '''
+            class C {
+                Void[] m() {}
+            }
+            println 'parsed'
+        '''
+    }
+
+    @Test
+    void testVoidArray1() {
+        def err = shouldFail {
+            shell.evaluate '''
+                class C {
+                    void[] m() {}
+                }
+            '''
+        }
+        assert err =~ /void\[\] is an invalid type/
+    }
+
+    @Test
+    void testVoidArray2() {
+        def err = shouldFail {
+            shell.evaluate '''
+                class C {
+                    def meth(void... args) {}
+                }
+            '''
+        }
+        assert err =~ /void\[\] is an invalid type|void is not allowed here/
+    }
+}
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 580f23d..33e794e 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
@@ -4114,6 +4114,9 @@ public class AstBuilder extends GroovyParserBaseVisitor<Object> implements Groov
     }
 
     private ClassNode createArrayType(ClassNode elementType) {
+        if (ClassHelper.VOID_TYPE.equals(elementType)) {
+            throw this.createParsingFailedException("void[] is an invalid type", elementType);
+        }
         return elementType.makeArray();
     }
 


[groovy] 05/18: fix generics and other 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 3425ba7eb7b8df670e9fec50fa501f739fb2ef83
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 14 16:20:02 2019 -0600

    fix generics and other minor edits
    
    (cherry picked from commit 175bd3b0c0d56e0a1a0658b87d3183957c26c846)
---
 .../groovy/classgen/AsmClassGenerator.java         | 678 ++++++++++-----------
 1 file changed, 333 insertions(+), 345 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index bf46031..a528d3b 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -110,32 +110,27 @@ import org.objectweb.asm.ClassVisitor;
 import org.objectweb.asm.FieldVisitor;
 import org.objectweb.asm.Label;
 import org.objectweb.asm.MethodVisitor;
-import org.objectweb.asm.Opcodes;
 import org.objectweb.asm.Type;
 import org.objectweb.asm.util.TraceMethodVisitor;
 
 import java.io.PrintWriter;
 import java.io.Writer;
-import java.lang.reflect.Modifier;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import static org.apache.groovy.util.BeanUtils.capitalize;
 
 /**
  * Generates Java class versions of Groovy classes using ASM.
- *
  */
 public class AsmClassGenerator extends ClassGenerator {
 
-    private ClassVisitor cv;
-    private final GeneratorContext context;
-    private final String sourceFile;
-
     // fields and properties
     public static final MethodCallerMultiAdapter setField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "setField", false, false);
     public static final MethodCallerMultiAdapter getField = MethodCallerMultiAdapter.newStatic(ScriptBytecodeAdapter.class, "getField", false, false);
@@ -164,7 +159,7 @@ public class AsmClassGenerator extends ClassGenerator {
     static final MethodCaller createPojoWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createPojoWrapper");
     static final MethodCaller createGroovyObjectWrapperMethod = MethodCaller.newStatic(ScriptBytecodeAdapter.class, "createGroovyObjectWrapper");
 
-    // exception blocks list
+    private final Map<String, GenericsType> genericParameterNames = new HashMap<>();
     private final Map<String,ClassNode> referencedClasses = new HashMap<>();
     private boolean passingParams;
 
@@ -173,22 +168,22 @@ public class AsmClassGenerator extends ClassGenerator {
     public static final boolean ASM_DEBUG = false; // add marker in the bytecode to show source-bytecode relationship
     public static final String MINIMUM_BYTECODE_VERSION = "_MINIMUM_BYTECODE_VERSION";
 
-    private ASTNode currentASTNode = null;
-    private final Map genericParameterNames;
-    private final SourceUnit source;
     private WriterController controller;
+    private ASTNode currentASTNode;
+
+    private final SourceUnit source;
+    private final GeneratorContext context;
+    private ClassVisitor classVisitor;
+    private final String sourceFile;
 
-    public AsmClassGenerator(
-            SourceUnit source, GeneratorContext context,
-            ClassVisitor classVisitor, String sourceFile
-    ) {
+    public AsmClassGenerator(SourceUnit source, GeneratorContext context, ClassVisitor classVisitor, String sourceFile) {
         this.source = source;
         this.context = context;
-        this.cv = classVisitor;
+        this.classVisitor = classVisitor;
         this.sourceFile = sourceFile;
-        genericParameterNames = new HashMap();
     }
 
+    @Override
     public SourceUnit getSourceUnit() {
         return source;
     }
@@ -198,20 +193,22 @@ public class AsmClassGenerator extends ClassGenerator {
     }
 
     // GroovyClassVisitor interface
-    //-------------------------------------------------------------------------
+    //--------------------------------------------------------------------------
+
+    @Override
     public void visitClass(ClassNode classNode) {
         referencedClasses.clear();
         WriterControllerFactory factory = classNode.getNodeMetaData(WriterControllerFactory.class);
         WriterController normalController = new WriterController();
-        if (factory!=null) {
+        if (factory != null) {
             this.controller = factory.makeController(normalController);
         } else {
             this.controller = normalController;
         }
-        this.controller.init(this, context, cv, classNode);
-        this.cv = this.controller.getClassVisitor();
+        this.controller.init(this, context, classVisitor, classNode);
+        this.classVisitor = this.controller.getClassVisitor();
 
-        if (controller.shouldOptimizeForInt() || factory!=null) {
+        if (controller.shouldOptimizeForInt() || factory != null) {
             OptimizingStatementWriter.setNodeMeta(controller.getTypeChooser(),classNode);
         }
 
@@ -220,11 +217,11 @@ public class AsmClassGenerator extends ClassGenerator {
             Object min = classNode.getNodeMetaData(MINIMUM_BYTECODE_VERSION);
             if (min instanceof Integer) {
                 int minVersion = (int) min;
-                if ((bytecodeVersion ^ Opcodes.V_PREVIEW) < minVersion) {
+                if ((bytecodeVersion ^ V_PREVIEW) < minVersion) {
                     bytecodeVersion = minVersion;
                 }
             }
-            cv.visit(
+            classVisitor.visit(
                     bytecodeVersion,
                     adjustedClassModifiersForClassWriting(classNode),
                     controller.getInternalClassName(),
@@ -232,25 +229,25 @@ public class AsmClassGenerator extends ClassGenerator {
                     controller.getInternalBaseClassName(),
                     BytecodeHelper.getClassInternalNames(classNode.getInterfaces())
             );
-            cv.visitSource(sourceFile, null);
+            classVisitor.visitSource(sourceFile, null);
             if (classNode instanceof InnerClassNode) {
                 InnerClassNode innerClass = (InnerClassNode) classNode;
                 MethodNode enclosingMethod = innerClass.getEnclosingMethod();
                 if (enclosingMethod != null) {
                     String outerClassName = BytecodeHelper.getClassInternalName(innerClass.getOuterClass().getName());
-                    cv.visitOuterClass(outerClassName, enclosingMethod.getName(), BytecodeHelper.getMethodDescriptor(enclosingMethod));
+                    classVisitor.visitOuterClass(outerClassName, enclosingMethod.getName(), BytecodeHelper.getMethodDescriptor(enclosingMethod));
                 }
             }
             if (classNode.getName().endsWith("package-info")) {
                 PackageNode packageNode = classNode.getPackage();
                 if (packageNode != null) {
                     // pull them out of package node but treat them like they were on class node
-                    visitAnnotations(classNode, packageNode, cv);
+                    visitAnnotations(classNode, packageNode, classVisitor);
                 }
-                cv.visitEnd();
+                classVisitor.visitEnd();
                 return;
             } else {
-                visitAnnotations(classNode, cv);
+                visitAnnotations(classNode, classVisitor);
             }
 
             if (classNode.isInterface()) {
@@ -269,7 +266,7 @@ public class AsmClassGenerator extends ClassGenerator {
             } else {
                 super.visitClass(classNode);
                 MopWriter.Factory mopWriterFactory = classNode.getNodeMetaData(MopWriter.Factory.class);
-                if (mopWriterFactory==null) {
+                if (mopWriterFactory == null) {
                     mopWriterFactory = MopWriter.FACTORY;
                 }
                 MopWriter mopWriter = mopWriterFactory.create(controller);
@@ -285,14 +282,14 @@ public class AsmClassGenerator extends ClassGenerator {
             }
             makeInnerClassEntry(classNode);
 
-            cv.visitEnd();
+            classVisitor.visitEnd();
         } catch (GroovyRuntimeException e) {
             e.setModule(classNode.getModule());
             throw e;
         } catch (NegativeArraySizeException nase) {
-            throw new GroovyRuntimeException("NegativeArraySizeException while processing "+sourceFile, nase);
+            throw new GroovyRuntimeException("NegativeArraySizeException while processing " + sourceFile, nase);
         } catch (NullPointerException npe) {
-            throw new GroovyRuntimeException("NPE while processing "+sourceFile, npe);
+            throw new GroovyRuntimeException("NPE while processing " + sourceFile, npe);
         }
     }
 
@@ -313,13 +310,11 @@ public class AsmClassGenerator extends ClassGenerator {
             if (innerClass.isAnonymous()) innerClassName = null;
         }
         int mods = adjustedClassModifiersForInnerClassTable(cn);
-
-
-        if (Modifier.isPrivate(mods)) {
-            mods = mods ^ Modifier.PRIVATE;
+        if ((mods & ACC_PRIVATE) != 0) {
+            mods ^= ACC_PRIVATE;
             innerClass.setModifiers(mods);
         }
-        cv.visitInnerClass(
+        classVisitor.visitInnerClass(
                 innerClassInternalName,
                 outerClassName,
                 innerClassName,
@@ -336,7 +331,6 @@ public class AsmClassGenerator extends ClassGenerator {
         int modifiers = classNode.getModifiers();
         modifiers = modifiers & ~ACC_SUPER;
         modifiers = fixInterfaceModifiers(classNode, modifiers);
-
         modifiers = fixInnerClassModifiers(classNode, modifiers);
         return modifiers;
     }
@@ -350,16 +344,16 @@ public class AsmClassGenerator extends ClassGenerator {
         return modifiers;
     }
 
-    private static int fixInnerClassModifiers(final ClassNode classNode, int modifiers) {
+    private static int fixInnerClassModifiers(ClassNode classNode, int modifiers) {
         // on the inner class node itself, private/protected are not allowed
-        if (classNode instanceof InnerClassNode) {
-            if (Modifier.isPrivate(modifiers)) {
-                // GROOVY-6357 : The JVM does not allow private modifier on inner classes: should be package private
-                modifiers = modifiers & ~Modifier.PRIVATE;
+        if (classNode.getOuterClass() != null) {
+            if ((modifiers & ACC_PRIVATE) != 0) {
+                // GROOVY-6357: The JVM does not allow private modifier on inner classes: should be package private
+                modifiers = (modifiers & ~ACC_PRIVATE);
             }
-            if (Modifier.isProtected(modifiers)) {
-                // GROOVY-6357 : Following Java's behavior for protected modifier on inner classes: should be public
-                modifiers = (modifiers & ~Modifier.PROTECTED) | Modifier.PUBLIC;
+            if ((modifiers & ACC_PROTECTED) != 0) {
+                // GROOVY-6357: Following Java's behavior for protected modifier on inner classes: should be public
+                modifiers = (modifiers & ~ACC_PROTECTED) | ACC_PUBLIC;
             }
         }
         return modifiers;
@@ -387,34 +381,26 @@ public class AsmClassGenerator extends ClassGenerator {
         genericParameterNames.put(type.getName(), genericsType);
     }
 
-    private static String[] buildExceptions(ClassNode[] exceptions) {
-        if (exceptions == null) return null;
-        String[] ret = new String[exceptions.length];
-        for (int i = 0; i < exceptions.length; i++) {
-            ret[i] = BytecodeHelper.getClassInternalName(exceptions[i]);
-        }
-        return ret;
-    }
-
+    @Override
     protected void visitConstructorOrMethod(MethodNode node, boolean isConstructor) {
         controller.resetLineNumber();
-    	Parameter[] parameters = node.getParameters();
+        Parameter[] parameters = node.getParameters();
         String methodType = BytecodeHelper.getMethodDescriptor(node.getReturnType(), parameters);
         String signature = BytecodeHelper.getGenericsMethodSignature(node);
         int modifiers = node.getModifiers();
-        if (isVargs(node.getParameters())) modifiers |= Opcodes.ACC_VARARGS;
-        MethodVisitor mv = cv.visitMethod(modifiers, node.getName(), methodType, signature, buildExceptions(node.getExceptions()));
+        if (isVargs(node.getParameters())) modifiers |= ACC_VARARGS;
+        MethodVisitor mv = classVisitor.visitMethod(modifiers, node.getName(), methodType, signature, buildExceptions(node.getExceptions()));
         controller.setMethodVisitor(mv);
 
         visitAnnotations(node, mv);
-        for (int i = 0; i < parameters.length; i++) {
+        for (int i = 0, n = parameters.length; i < n; i += 1) {
             visitParameterAnnotations(parameters[i], i, mv);
         }
 
-        // Add parameter names to the MethodVisitor (jdk8+ only)
+        // add parameter names to the MethodVisitor (jdk8+ only)
         if (getCompileUnit().getConfig().getParameters()) {
             for (Parameter parameter : parameters) {
-                // TODO handle ACC_SYNTHETIC for enum method parameters?
+                // TODO: handle ACC_SYNTHETIC for enum method parameters?
                 mv.visitParameter(parameter.getName(), 0);
             }
         }
@@ -424,15 +410,12 @@ public class AsmClassGenerator extends ClassGenerator {
         } else if (!node.isAbstract()) {
             Statement code = node.getCode();
             mv.visitCode();
-
             // fast path for getter/setters etc.
             if (code instanceof BytecodeSequence && ((BytecodeSequence)code).getInstructions().size() == 1 && ((BytecodeSequence)code).getInstructions().get(0) instanceof BytecodeInstruction) {
                ((BytecodeInstruction)((BytecodeSequence)code).getInstructions().get(0)).visit(mv);
             } else {
                 visitStdMethod(node, isConstructor, parameters, code);
             }
-            // we use this NOP to have a valid jump target for the various labels
-            //mv.visitInsn(NOP);
             try {
                 mv.visitMaxs(0, 0);
             } catch (Exception e) {
@@ -444,16 +427,16 @@ public class AsmClassGenerator extends ClassGenerator {
                     tracer.p.print(p);
                     p.flush();
                 }
-                StringBuilder outBuffer = new StringBuilder(64);
-                outBuffer.append("ASM reporting processing error for ");
-                outBuffer.append(controller.getClassNode().toString()).append("#").append(node.getName());
-                outBuffer.append(" with signature ").append(node.getTypeDescriptor());
-                outBuffer.append(" in ").append(sourceFile).append(":").append(node.getLineNumber());
+                StringBuilder message = new StringBuilder(64);
+                message.append("ASM reporting processing error for ");
+                message.append(controller.getClassNode().toString()).append("#").append(node.getName());
+                message.append(" with signature ").append(node.getTypeDescriptor());
+                message.append(" in ").append(sourceFile).append(":").append(node.getLineNumber());
                 if (writer != null) {
-                    outBuffer.append("\nLast known generated bytecode in last generated method or constructor:\n");
-                    outBuffer.append(writer);
+                    message.append("\nLast known generated bytecode in last generated method or constructor:\n");
+                    message.append(writer);
                 }
-                throw new GroovyRuntimeException(outBuffer.toString(), e);
+                throw new GroovyRuntimeException(message.toString(), e);
             }
         }
         mv.visitEnd();
@@ -514,7 +497,7 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    void visitAnnotationDefaultExpression(AnnotationVisitor av, ClassNode type, Expression exp) {
+    private void visitAnnotationDefaultExpression(AnnotationVisitor av, ClassNode type, Expression exp) {
         if (exp instanceof ClosureExpression) {
             ClassNode closureClass = controller.getClosureWriter().getOrAddClosureClass((ClosureExpression) exp, ACC_PUBLIC);
             Type t = Type.getType(BytecodeHelper.getTypeDescription(closureClass));
@@ -561,22 +544,19 @@ public class AsmClassGenerator extends ClassGenerator {
         visitAnnotationDefaultExpression(av,node.getReturnType(),exp);
     }
 
-    private static boolean isVargs(Parameter[] p) {
-        if (p.length==0) return false;
-        ClassNode clazz = p[p.length-1].getType();
-        return (clazz.isArray());
-    }
-
+    @Override
     public void visitConstructor(ConstructorNode node) {
         controller.setConstructorNode(node);
         super.visitConstructor(node);
     }
 
+    @Override
     public void visitMethod(MethodNode node) {
         controller.setMethodNode(node);
         super.visitMethod(node);
     }
 
+    @Override
     public void visitField(FieldNode fieldNode) {
         onLineNumber(fieldNode, "visitField: " + fieldNode.getName());
         ClassNode t = fieldNode.getType();
@@ -587,12 +567,10 @@ public class AsmClassGenerator extends ClassGenerator {
         if (cexp!=null) {
             cexp = Verifier.transformToPrimitiveConstantIfPossible(cexp);
         }
-        Object value = cexp!=null && ClassHelper.isStaticConstantInitializerType(cexp.getType())
-                && cexp.getType().equals(t)
-                && fieldNode.isStatic() && fieldNode.isFinal()
-                ?cexp.getValue() // GROOVY-5150
-                :null;
-        if (value!=null) {
+        Object value = cexp != null && ClassHelper.isStaticConstantInitializerType(cexp.getType())
+                && cexp.getType().equals(t) && fieldNode.isStatic() && fieldNode.isFinal()
+                ? cexp.getValue() : null; // GROOVY-5150
+        if (value != null) {
             // byte, char and short require an extra cast
             if (ClassHelper.byte_TYPE.equals(t) || ClassHelper.short_TYPE.equals(t)) {
                 value = ((Number) value).intValue();
@@ -600,7 +578,7 @@ public class AsmClassGenerator extends ClassGenerator {
                 value = Integer.valueOf((Character)value);
             }
         }
-        FieldVisitor fv = cv.visitField(
+        FieldVisitor fv = classVisitor.visitField(
                 fieldNode.getModifiers(),
                 fieldNode.getName(),
                 BytecodeHelper.getTypeDescription(t),
@@ -610,6 +588,7 @@ public class AsmClassGenerator extends ClassGenerator {
         fv.visitEnd();
     }
 
+    @Override
     public void visitProperty(PropertyNode statement) {
         // the verifier created the field and the setter/getter methods, so here is
         // not really something to do
@@ -623,6 +602,7 @@ public class AsmClassGenerator extends ClassGenerator {
     // Statements
     //-------------------------------------------------------------------------
 
+    @Override
     protected void visitStatement(Statement statement) {
         throw new GroovyBugError("visitStatement should not be visited here.");
     }
@@ -632,60 +612,76 @@ public class AsmClassGenerator extends ClassGenerator {
         statement.getCode().visit(this);
     }
 
-    public void visitBlockStatement(BlockStatement block) {
-        controller.getStatementWriter().writeBlockStatement(block);
+    @Override
+    public void visitBlockStatement(BlockStatement statement) {
+        controller.getStatementWriter().writeBlockStatement(statement);
     }
 
-    public void visitForLoop(ForStatement loop) {
-        controller.getStatementWriter().writeForStatement(loop);
+    @Override
+    public void visitForLoop(ForStatement statement) {
+        controller.getStatementWriter().writeForStatement(statement);
     }
 
-    public void visitWhileLoop( WhileStatement loop) {
-        controller.getStatementWriter().writeWhileLoop(loop);
+    @Override
+    public void visitWhileLoop( WhileStatement statement) {
+        controller.getStatementWriter().writeWhileLoop(statement);
     }
 
-    public void visitDoWhileLoop(DoWhileStatement loop) {
-        controller.getStatementWriter().writeDoWhileLoop(loop);
+    @Override
+    public void visitDoWhileLoop(DoWhileStatement statement) {
+        controller.getStatementWriter().writeDoWhileLoop(statement);
     }
 
-    public void visitIfElse(IfStatement ifElse) {
-        controller.getStatementWriter().writeIfElse(ifElse);
+    @Override
+    public void visitIfElse(IfStatement statement) {
+        controller.getStatementWriter().writeIfElse(statement);
     }
 
+    @Override
     public void visitAssertStatement(AssertStatement statement) {
         controller.getStatementWriter().writeAssert(statement);
     }
 
+    @Override
     public void visitTryCatchFinally(TryCatchStatement statement) {
         controller.getStatementWriter().writeTryCatchFinally(statement);
     }
 
+    @Override
     public void visitSwitch(SwitchStatement statement) {
         controller.getStatementWriter().writeSwitch(statement);
     }
 
-    public void visitCaseStatement(CaseStatement statement) {}
+    @Override
+    public void visitCaseStatement(CaseStatement statement) {
+    }
 
+    @Override
     public void visitBreakStatement(BreakStatement statement) {
         controller.getStatementWriter().writeBreak(statement);
     }
 
+    @Override
     public void visitContinueStatement(ContinueStatement statement) {
         controller.getStatementWriter().writeContinue(statement);
     }
 
+    @Override
     public void visitSynchronizedStatement(SynchronizedStatement statement) {
         controller.getStatementWriter().writeSynchronized(statement);
     }
 
+    @Override
     public void visitThrowStatement(ThrowStatement statement) {
         controller.getStatementWriter().writeThrow(statement);
     }
 
+    @Override
     public void visitReturnStatement(ReturnStatement statement) {
         controller.getStatementWriter().writeReturn(statement);
     }
 
+    @Override
     public void visitExpressionStatement(ExpressionStatement statement) {
         controller.getStatementWriter().writeExpressionStatement(statement);
     }
@@ -693,36 +689,38 @@ public class AsmClassGenerator extends ClassGenerator {
     // Expressions
     //-------------------------------------------------------------------------
 
+    @Override
     public void visitTernaryExpression(TernaryExpression expression) {
         onLineNumber(expression, "visitTernaryExpression");
         controller.getBinaryExpressionHelper().evaluateTernary(expression);
     }
 
+    @Override
     public void visitDeclarationExpression(DeclarationExpression expression) {
         onLineNumber(expression, "visitDeclarationExpression: \"" + expression.getText() + "\"");
         controller.getBinaryExpressionHelper().evaluateEqual(expression,true);
     }
 
+    @Override
     public void visitBinaryExpression(BinaryExpression expression) {
         onLineNumber(expression, "visitBinaryExpression: \"" + expression.getOperation().getText() + "\" ");
         controller.getBinaryExpressionHelper().eval(expression);
         controller.getAssertionWriter().record(expression.getOperation());
     }
 
+    @Override
     public void visitPostfixExpression(PostfixExpression expression) {
         controller.getBinaryExpressionHelper().evaluatePostfixMethod(expression);
         controller.getAssertionWriter().record(expression);
     }
 
-    public void throwException(String s) {
-        throw new RuntimeParserException(s, currentASTNode);
-    }
-
+    @Override
     public void visitPrefixExpression(PrefixExpression expression) {
         controller.getBinaryExpressionHelper().evaluatePrefixMethod(expression);
         controller.getAssertionWriter().record(expression);
     }
 
+    @Override
     public void visitClosureExpression(ClosureExpression expression) {
         controller.getClosureWriter().writeClosure(expression);
     }
@@ -744,10 +742,11 @@ public class AsmClassGenerator extends ClassGenerator {
     }
 
     /**
-     * Generate byte code for constants
+     * Generates byte code for constants.
      *
      * @see <a href="http://java.sun.com/docs/books/vmspec/2nd-edition/html/ClassFile.doc.html#14152">Class field types</a>
      */
+    @Override
     public void visitConstantExpression(ConstantExpression expression) {
         final String constantName = expression.getConstantName();
         if (controller.isStaticConstructor() || constantName == null) {
@@ -758,10 +757,12 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
+    @Override
     public void visitSpreadExpression(SpreadExpression expression) {
         throw new GroovyBugError("SpreadExpression should not be visited here");
     }
 
+    @Override
     public void visitSpreadMapExpression(SpreadMapExpression expression) {
         Expression subExpression = expression.getExpression();
         // to not record the underlying MapExpression twice,
@@ -785,18 +786,22 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getMethodReferenceExpressionWriter().writeMethodReferenceExpression(expression);
     }
 
+    @Override
     public void visitUnaryMinusExpression(UnaryMinusExpression expression) {
         controller.getUnaryExpressionHelper().writeUnaryMinus(expression);
     }
 
+    @Override
     public void visitUnaryPlusExpression(UnaryPlusExpression expression) {
         controller.getUnaryExpressionHelper().writeUnaryPlus(expression);
     }
 
+    @Override
     public void visitBitwiseNegationExpression(BitwiseNegationExpression expression) {
         controller.getUnaryExpressionHelper().writeBitwiseNegate(expression);
     }
 
+    @Override
     public void visitCastExpression(CastExpression castExpression) {
         ClassNode type = castExpression.getType();
         Expression subExpression = castExpression.getExpression();
@@ -820,15 +825,12 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
+    @Override
     public void visitNotExpression(NotExpression expression) {
         controller.getUnaryExpressionHelper().writeNotExpression(expression);
     }
 
-    /**
-     * return a primitive boolean value of the BooleanExpression.
-     *
-     * @param expression
-     */
+    @Override
     public void visitBooleanExpression(BooleanExpression expression) {
         controller.getCompileStack().pushBooleanExpression();
         int mark = controller.getOperandStack().getStackLength();
@@ -838,52 +840,21 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getCompileStack().pop();
     }
 
+    @Override
     public void visitMethodCallExpression(MethodCallExpression call) {
         onLineNumber(call, "visitMethodCallExpression: \"" + call.getMethod() + "\":");
         controller.getInvocationWriter().writeInvokeMethod(call);
         controller.getAssertionWriter().record(call.getMethod());
     }
 
-    protected boolean emptyArguments(Expression arguments) {
-        return argumentSize(arguments) == 0;
-    }
-
-    public static boolean containsSpreadExpression(Expression arguments) {
-        List args = null;
-        if (arguments instanceof TupleExpression) {
-            TupleExpression tupleExpression = (TupleExpression) arguments;
-            args = tupleExpression.getExpressions();
-        } else if (arguments instanceof ListExpression) {
-            ListExpression le = (ListExpression) arguments;
-            args = le.getExpressions();
-        } else {
-            return arguments instanceof SpreadExpression;
-        }
-        for (Object arg : args) {
-            if (arg instanceof SpreadExpression) return true;
-        }
-        return false;
-    }
-
-    public static int argumentSize(Expression arguments) {
-        if (arguments instanceof TupleExpression) {
-            TupleExpression tupleExpression = (TupleExpression) arguments;
-            int size = tupleExpression.getExpressions().size();
-            return size;
-        }
-        return 1;
-    }
-
+    @Override
     public void visitStaticMethodCallExpression(StaticMethodCallExpression call) {
         onLineNumber(call, "visitStaticMethodCallExpression: \"" + call.getMethod() + "\":");
         controller.getInvocationWriter().writeInvokeStaticMethod(call);
         controller.getAssertionWriter().record(call);
     }
 
-    public static boolean isNullConstant(Expression expr) {
-        return expr instanceof ConstantExpression && ((ConstantExpression) expr).getValue()==null;
-    }
-
+    @Override
     public void visitConstructorCallExpression(ConstructorCallExpression call) {
         onLineNumber(call, "visitConstructorCallExpression: \"" + call.getType().getName() + "\":");
 
@@ -898,7 +869,7 @@ public class AsmClassGenerator extends ClassGenerator {
     private static String makeFieldClassName(ClassNode type) {
         String internalName = BytecodeHelper.getClassInternalName(type);
         StringBuilder ret = new StringBuilder(internalName.length());
-        for (int i = 0; i < internalName.length(); i++) {
+        for (int i = 0, n = internalName.length(); i < n; i += 1) {
             char c = internalName.charAt(i);
             if (c == '/') {
                 ret.append('$');
@@ -922,21 +893,14 @@ public class AsmClassGenerator extends ClassGenerator {
         return name;
     }
 
-    public static boolean samePackages(final String pkg1, final String pkg2) {
-        return (
-                (pkg1 ==null && pkg2 ==null)
-                        || pkg1 !=null && pkg1.equals(pkg2)
-        );
-    }
-
     private static boolean isValidFieldNodeForByteCodeAccess(FieldNode fn, ClassNode accessingNode) {
         if (fn == null) return false;
         ClassNode declaringClass = fn.getDeclaringClass();
         // same class is always allowed access
-        if (Modifier.isPublic(fn.getModifiers()) || declaringClass.equals(accessingNode)) return true;
+        if (fn.isPublic() || declaringClass.equals(accessingNode)) return true;
         boolean samePackages = samePackages(declaringClass.getPackageName(), accessingNode.getPackageName());
         // protected means same class or same package, or subclass
-        if (Modifier.isProtected(fn.getModifiers()) && (samePackages || accessingNode.isDerivedFrom(declaringClass))) {
+        if (fn.isProtected() && (samePackages || accessingNode.isDerivedFrom(declaringClass))) {
             return true;
         }
         if (!fn.isPrivate()) {
@@ -951,7 +915,7 @@ public class AsmClassGenerator extends ClassGenerator {
             FieldNode currentClassField = current.getDeclaredField(name);
             if (isValidFieldNodeForByteCodeAccess(currentClassField, accessingNode)) return currentClassField;
         }
-        for (ClassNode node = current.getSuperClass(); node!=null; node = node.getSuperClass()) {
+        for (ClassNode node = current.getSuperClass(); node != null; node = node.getSuperClass()) {
             FieldNode fn = node.getDeclaredField(name);
             if (isValidFieldNodeForByteCodeAccess(fn, accessingNode)) return fn;
         }
@@ -977,50 +941,49 @@ public class AsmClassGenerator extends ClassGenerator {
                 boolean privateSuperField = false;
                 if (isSuperExpression(objectExpression)) {
                     field = classNode.getSuperClass().getDeclaredField(name);
-                    if (field != null && ((field.getModifiers() & ACC_PRIVATE) != 0)) {
+                    if (field != null && field.isPrivate()) {
                         privateSuperField = true;
                     }
-                } else {
-                	if (controller.isNotExplicitThisInClosure(expression.isImplicitThis())) {
-                        field = classNode.getDeclaredField(name);
-                        if (field==null && classNode instanceof InnerClassNode) {
-                            ClassNode outer = classNode.getOuterClass();
-                            FieldNode outerClassField;
-                            while (outer!=null) {
-                                outerClassField = outer.getDeclaredField(name);
-                                if (outerClassField!=null && outerClassField.isStatic() && outerClassField.isFinal()) {
-                                    if (outer!=classNode.getOuterClass() && outerClassField.isPrivate()) {
-                                        throw new GroovyBugError("Trying to access private constant field ["+outerClassField.getDeclaringClass()+"#"+outerClassField.getName()+"] from inner class");
-                                    }
-                                    PropertyExpression pexp = new PropertyExpression(
-                                            new ClassExpression(outer),
-                                            expression.getProperty()
-                                    );
-                                    pexp.getObjectExpression().setSourcePosition(objectExpression);
-                                    pexp.visit(controller.getAcg());
-                                    return;
+                } else if (controller.isNotExplicitThisInClosure(expression.isImplicitThis())) {
+                    field = classNode.getDeclaredField(name);
+                    ClassNode outer = classNode.getOuterClass();
+                    if (field == null && outer != null) {
+                        FieldNode outerClassField;
+                        do {
+                            outerClassField = outer.getDeclaredField(name);
+                            if (outerClassField!=null && outerClassField.isStatic() && outerClassField.isFinal()) {
+                                if (outer != classNode.getOuterClass() && outerClassField.isPrivate()) {
+                                    throw new GroovyBugError("Trying to access private constant field [" + outerClassField.getDeclaringClass() + "#" + outerClassField.getName() + "] from inner class");
                                 }
-                                outer = outer.getSuperClass();
-                            }
-                        }
-                        if (field==null
-                                && expression instanceof AttributeExpression
-                                && isThisExpression(objectExpression)
-                                && controller.isStaticContext()) {
-                            // GROOVY-6183
-                            ClassNode current = classNode.getSuperClass();
-                            while (field==null && current!=null) {
-                                field = current.getDeclaredField(name);
-                                current = current.getSuperClass();
-                            }
-                            if (field!=null && (field.isProtected() || field.isPublic())) {
-                                visitFieldExpression(new FieldExpression(field));
+                                PropertyExpression pexp = new PropertyExpression(
+                                        new ClassExpression(outer),
+                                        expression.getProperty()
+                                );
+                                pexp.getObjectExpression().setSourcePosition(objectExpression);
+                                pexp.visit(controller.getAcg());
                                 return;
                             }
+                            outer = outer.getSuperClass();
+                        } while (outer != null);
+                    }
+                    if (field == null
+                            && expression instanceof AttributeExpression
+                            && isThisExpression(objectExpression)
+                            && controller.isStaticContext()) {
+                        // GROOVY-6183
+                        ClassNode current = classNode.getSuperClass();
+                        while (field==null && current!=null) {
+                            field = current.getDeclaredField(name);
+                            current = current.getSuperClass();
+                        }
+                        if (field!=null && (field.isProtected() || field.isPublic())) {
+                            visitFieldExpression(new FieldExpression(field));
+                            return;
                         }
-                	}
+                    }
                 }
-                if (field != null && !privateSuperField) {//GROOVY-4497: don't visit super field if it is private
+                if (field != null && !privateSuperField) {
+                    // GROOVY-4497: don't visit super field if it is private
                     visitFieldExpression(new FieldExpression(field));
                     return;
                 }
@@ -1028,7 +991,6 @@ public class AsmClassGenerator extends ClassGenerator {
                     String prefix;
                     if (controller.getCompileStack().isLHS()) {
                         setPropertyOfSuperClass(classNode, expression, mv);
-
                         return;
                     } else {
                         prefix = "get";
@@ -1040,17 +1002,15 @@ public class AsmClassGenerator extends ClassGenerator {
             }
         }
 
-        final String propName = expression.getPropertyAsString();
-        //TODO: add support for super here too
-        if (expression.getObjectExpression() instanceof ClassExpression &&
-            propName!=null && propName.equals("this"))
-        {
+        String propName = expression.getPropertyAsString();
+        // TODO: add support for super here too
+        if (expression.getObjectExpression() instanceof ClassExpression && "this".equals(propName)) {
             // we have something like A.B.this, and need to make it
             // into this.this$0.this$0, where this.this$0 returns
             // A.B and this.this$0.this$0 return A.
             ClassNode type = objectExpression.getType();
             ClassNode iterType = classNode;
-            if (controller.getCompileStack().isInSpecialConstructorCall() && classNode instanceof InnerClassNode) {
+            if (controller.getCompileStack().isInSpecialConstructorCall() && classNode.getOuterClass() != null) {
                 boolean staticInnerClass = classNode.isStaticClass();
                 // Outer.this in a special constructor call
                 if (classNode.getOuterClass().equals(type)) {
@@ -1064,7 +1024,7 @@ public class AsmClassGenerator extends ClassGenerator {
             mv.visitVarInsn(ALOAD, 0);
             while (!iterType.equals(type)) {
                 String ownerName = BytecodeHelper.getClassInternalName(iterType);
-                if (iterType.getOuterClass()==null) break;
+                if (iterType.getOuterClass() == null) break;
                 FieldNode thisField = iterType.getField("this$0");
                 iterType = iterType.getOuterClass();
                 if (thisField == null) {
@@ -1141,19 +1101,17 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    private boolean getterAndSetterExists(MethodNode setter, MethodNode getter) {
+    private static boolean getterAndSetterExists(MethodNode setter, MethodNode getter) {
         return null != setter && null != getter && setter.getDeclaringClass().equals(getter.getDeclaringClass());
     }
 
-    private MethodNode findSetterOfSuperClass(ClassNode classNode, FieldNode fieldNode) {
+    private static MethodNode findSetterOfSuperClass(ClassNode classNode, FieldNode fieldNode) {
         String setterMethodName = "set" + capitalize(fieldNode.getName());
-
         return classNode.getSuperClass().getSetterMethod(setterMethodName);
     }
 
-    private MethodNode findGetterOfSuperClass(ClassNode classNode, FieldNode fieldNode) {
+    private static MethodNode findGetterOfSuperClass(ClassNode classNode, FieldNode fieldNode) {
         String getterMethodName = "get" + capitalize(fieldNode.getName());
-
         return classNode.getSuperClass().getGetterMethod(getterMethodName);
     }
 
@@ -1197,14 +1155,13 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
+    @Override
     public void visitAttributeExpression(AttributeExpression expression) {
         Expression objectExpression = expression.getObjectExpression();
         ClassNode classNode = controller.getClassNode();
         // TODO: checking for isThisOrSuper is enough for AttributeExpression, but if this is moved into
         // visitAttributeOrProperty to handle attributes and properties equally, then the extended check should be done
-        if (isThisOrSuper(objectExpression) /*&&
-            !(expression.isImplicitThis() && controller.isInClosure()) */
-                ) {
+        if (isThisOrSuper(objectExpression)) {
             // let's use the field expression if it's available
             String name = expression.getPropertyAsString();
             if (name != null) {
@@ -1220,7 +1177,7 @@ public class AsmClassGenerator extends ClassGenerator {
 
         MethodCallerMultiAdapter adapter;
         OperandStack operandStack = controller.getOperandStack();
-        int mark = operandStack.getStackLength()-1;
+        int mark = operandStack.getStackLength() - 1;
         if (controller.getCompileStack().isLHS()) {
             adapter = setField;
             if (isGroovyObject(objectExpression)) adapter = setGroovyObjectField;
@@ -1248,9 +1205,9 @@ public class AsmClassGenerator extends ClassGenerator {
         return false;
     }
 
+    @Override
     public void visitFieldExpression(FieldExpression expression) {
         FieldNode field = expression.getField();
-
         if (field.isStatic()) {
             if (controller.getCompileStack().isLHS()) {
                 storeStaticField(expression);
@@ -1267,9 +1224,6 @@ public class AsmClassGenerator extends ClassGenerator {
         if (controller.getCompileStack().isLHS()) controller.getAssertionWriter().record(expression);
     }
 
-    /**
-     * @param fldExp
-     */
     public void loadStaticField(FieldExpression fldExp) {
         MethodVisitor mv = controller.getMethodVisitor();
         FieldNode field = fldExp.getField();
@@ -1291,8 +1245,6 @@ public class AsmClassGenerator extends ClassGenerator {
 
     /**
      * RHS instance field. should move most of the code in the BytecodeHelper
-     *
-     * @param fldExp
      */
     public void loadInstanceField(FieldExpression fldExp) {
         MethodVisitor mv = controller.getMethodVisitor();
@@ -1319,8 +1271,8 @@ public class AsmClassGenerator extends ClassGenerator {
         FieldNode field = expression.getField();
 
         boolean setReferenceFromReference = field.isHolder() && expression.isUseReferenceDirectly();
-        String ownerName = (field.getOwner().equals(controller.getClassNode())) ?
-                controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
+        String ownerName = (field.getOwner().equals(controller.getClassNode()))
+                ? controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
         OperandStack operandStack = controller.getOperandStack();
 
         if (setReferenceFromReference) {
@@ -1329,7 +1281,7 @@ public class AsmClassGenerator extends ClassGenerator {
             operandStack.push(controller.getClassNode());
             operandStack.swap();
             mv.visitFieldInsn(PUTFIELD, ownerName, field.getName(), BytecodeHelper.getTypeDescription(field.getType()));
-        } else if (field.isHolder()){
+        } else if (field.isHolder()) {
             // rhs is normal value, set the value in the Reference
             operandStack.doGroovyCast(field.getOriginType());
             operandStack.box();
@@ -1354,8 +1306,8 @@ public class AsmClassGenerator extends ClassGenerator {
         boolean holder = field.isHolder() && !controller.isInClosureConstructor();
         controller.getOperandStack().doGroovyCast(field);
 
-        String ownerName = (field.getOwner().equals(controller.getClassNode())) ?
-                controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
+        String ownerName = (field.getOwner().equals(controller.getClassNode()))
+                ? controller.getInternalClassName() : BytecodeHelper.getClassInternalName(field.getOwner());
         if (holder) {
             controller.getOperandStack().box();
             mv.visitFieldInsn(GETSTATIC, ownerName, expression.getFieldName(), BytecodeHelper.getTypeDescription(field.getType()));
@@ -1370,6 +1322,7 @@ public class AsmClassGenerator extends ClassGenerator {
     /**
      * Visits a bare (unqualified) variable expression.
      */
+    @Override
     public void visitVariableExpression(VariableExpression expression) {
         String variableName = expression.getName();
 
@@ -1378,9 +1331,8 @@ public class AsmClassGenerator extends ClassGenerator {
 
         // "this" for static methods is the Class instance
         ClassNode classNode = controller.getClassNode();
-        //if (controller.isInClosure()) classNode = controller.getOutermostClass();
 
-        if (variableName.equals("this")) {
+        if (expression.isThisExpression()) {
             if (controller.isStaticMethod() || (!controller.getCompileStack().isImplicitThis() && controller.isStaticContext())) {
                 if (controller.isInClosure()) classNode = controller.getOutermostClass();
                 visitClassExpression(new ClassExpression(classNode));
@@ -1391,7 +1343,7 @@ public class AsmClassGenerator extends ClassGenerator {
         }
 
         // "super" also requires special handling
-        if (variableName.equals("super")) {
+        if (expression.isSuperExpression()) {
             if (controller.isStaticMethod()) {
                 visitClassExpression(new ClassExpression(classNode.getSuperClass()));
             } else {
@@ -1463,7 +1415,8 @@ public class AsmClassGenerator extends ClassGenerator {
         }
 
         addInnerClass(icl);
-        for (Map.Entry<String, ClassNode> entry : referencedClasses.entrySet()) {            // generate a field node
+        for (Map.Entry<String, ClassNode> entry : referencedClasses.entrySet()) {
+            // generate a field node
             String staticFieldName = entry.getKey();
             ClassNode cn = entry.getValue();
             icl.addField(staticFieldName, ACC_STATIC + ACC_SYNTHETIC, ClassHelper.CLASS_Type.getPlainNodeReference(), new ClassExpression(cn));
@@ -1481,23 +1434,21 @@ public class AsmClassGenerator extends ClassGenerator {
             // generate a field node
             FieldNode fn = controller.getClassNode().getDeclaredField(staticFieldName);
             if (fn != null) {
-                boolean type = fn.getType().redirect() == ClassHelper.CLASS_Type;
+                boolean type = fn.getType().equals(ClassHelper.CLASS_Type);
                 boolean modifiers = fn.getModifiers() == ACC_STATIC + ACC_SYNTHETIC;
                 if (!type || !modifiers) {
                     String text = "";
                     if (!type) text = " with wrong type: " + fn.getType() + " (java.lang.Class needed)";
                     if (!modifiers)
                         text = " with wrong modifiers: " + fn.getModifiers() + " (" + (ACC_STATIC + ACC_SYNTHETIC) + " needed)";
-                    throwException(
-                            "tried to set a static synthetic field " + staticFieldName + " in " + controller.getClassNode().getName() +
-                                    " for class resolving, but found already a node of that" +
-                                    " name " + text);
+                    throwException("tried to set a static synthetic field " + staticFieldName + " in " + controller.getClassNode().getName() +
+                            " for class resolving, but found already a node of that name " + text);
                 }
             } else {
-                cv.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, staticFieldName, "Ljava/lang/Class;", null, null);
+                classVisitor.visitField(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, staticFieldName, "Ljava/lang/Class;", null, null);
             }
 
-            mv = cv.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$get$" + staticFieldName,"()Ljava/lang/Class;",null, null);
+            mv = classVisitor.visitMethod(ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC, "$get$" + staticFieldName,"()Ljava/lang/Class;",null, null);
             mv.visitCode();
             mv.visitFieldInsn(GETSTATIC,controller.getInternalClassName(),staticFieldName,"Ljava/lang/Class;");
             mv.visitInsn(DUP);
@@ -1514,12 +1465,7 @@ public class AsmClassGenerator extends ClassGenerator {
             mv.visitEnd();
         }
 
-        mv =    cv.visitMethod(
-                        ACC_STATIC + ACC_SYNTHETIC,
-                        "class$",
-                        "(Ljava/lang/String;)Ljava/lang/Class;",
-                        null,
-                        null);
+        mv = classVisitor.visitMethod(ACC_STATIC + ACC_SYNTHETIC, "class$", "(Ljava/lang/String;)Ljava/lang/Class;", null, null);
         Label l0 = new Label();
         mv.visitLabel(l0);
         mv.visitVarInsn(ALOAD, 0);
@@ -1540,9 +1486,7 @@ public class AsmClassGenerator extends ClassGenerator {
         mv.visitMaxs(3, 2);
     }
 
-    /**
-     * load class object on stack
-     */
+    @Override
     public void visitClassExpression(ClassExpression expression) {
         ClassNode type = expression.getType();
         MethodVisitor mv = controller.getMethodVisitor();
@@ -1573,6 +1517,7 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getOperandStack().push(ClassHelper.CLASS_Type);
     }
 
+    @Override
     public void visitRangeExpression(RangeExpression expression) {
         OperandStack operandStack = controller.getOperandStack();
         expression.getFrom().visit(this);
@@ -1585,14 +1530,16 @@ public class AsmClassGenerator extends ClassGenerator {
         operandStack.replace(ClassHelper.RANGE_TYPE, 3);
     }
 
+    @Override
     public void visitMapEntryExpression(MapEntryExpression expression) {
         throw new GroovyBugError("MapEntryExpression should not be visited here");
     }
 
+    @Override
     public void visitMapExpression(MapExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
 
-        List entries = expression.getMapEntryExpressions();
+        List<MapEntryExpression> entries = expression.getMapEntryExpressions();
         int size = entries.size();
         BytecodeHelper.pushConstant(mv, size * 2);
 
@@ -1620,6 +1567,7 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getOperandStack().push(ClassHelper.MAP_TYPE);
     }
 
+    @Override
     public void visitArgumentlistExpression(ArgumentListExpression ale) {
         if (containsSpreadExpression(ale)) {
             despreadList(ale.getExpressions(), true);
@@ -1628,30 +1576,32 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    public void despreadList(List expressions, boolean wrap) {
-        ArrayList spreadIndexes = new ArrayList();
-        ArrayList spreadExpressions = new ArrayList();
-        ArrayList normalArguments = new ArrayList();
-        for (int i = 0; i < expressions.size(); i++) {
-            Object expr = expressions.get(i);
+    public void despreadList(List<Expression> expressions, boolean wrap) {
+        List<Expression> spreadIndexes = new ArrayList<>();
+        List<Expression> spreadExpressions = new ArrayList<>();
+        List<Expression> normalArguments = new ArrayList<>();
+        for (int i = 0, n = expressions.size(); i < n; i += 1) {
+            Expression expr = expressions.get(i);
             if (!(expr instanceof SpreadExpression)) {
                 normalArguments.add(expr);
             } else {
-                spreadIndexes.add(new ConstantExpression(i - spreadExpressions.size(),true));
+                spreadIndexes.add(new ConstantExpression(i - spreadExpressions.size(), true));
                 spreadExpressions.add(((SpreadExpression) expr).getExpression());
             }
         }
 
-        //load normal arguments as array
+        // load normal arguments as array
         visitTupleExpression(new ArgumentListExpression(normalArguments), wrap);
-        //load spread expressions as array
-        (new TupleExpression(spreadExpressions)).visit(this);
-        //load insertion index
-        (new ArrayExpression(ClassHelper.int_TYPE, spreadIndexes, null)).visit(this);
+        // load spread expressions as array
+        new TupleExpression(spreadExpressions).visit(this);
+        // load insertion index
+        new ArrayExpression(ClassHelper.int_TYPE, spreadIndexes, null).visit(this);
+
         controller.getOperandStack().remove(1);
         despreadList.call(controller.getMethodVisitor());
     }
 
+    @Override
     public void visitTupleExpression(TupleExpression expression) {
         visitTupleExpression(expression, false);
     }
@@ -1663,7 +1613,7 @@ public class AsmClassGenerator extends ClassGenerator {
         BytecodeHelper.pushConstant(mv, size);
         mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
 
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             mv.visitInsn(DUP);
             BytecodeHelper.pushConstant(mv, i);
             Expression argument = expression.getExpression(i);
@@ -1688,19 +1638,19 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getOperandStack().remove(1);
     }
 
+    @Override
     public void visitArrayExpression(ArrayExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         ClassNode elementType = expression.getElementType();
         String arrayTypeName = BytecodeHelper.getClassInternalName(elementType);
-        List sizeExpression = expression.getSizeExpression();
+        List<Expression> sizeExpression = expression.getSizeExpression();
 
         int size = 0;
         int dimensions = 0;
         if (sizeExpression != null) {
-            for (Object o : sizeExpression) {
-                Expression element = (Expression) o;
+            for (Expression element : sizeExpression) {
                 if (element == ConstantExpression.EMPTY_EXPRESSION) break;
-                dimensions++;
+                dimensions += 1;
                 // let's convert to an int
                 element.visit(this);
                 controller.getOperandStack().doGroovyCast(ClassHelper.int_TYPE);
@@ -1747,7 +1697,7 @@ public class AsmClassGenerator extends ClassGenerator {
             mv.visitTypeInsn(ANEWARRAY, arrayTypeName);
         }
 
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             mv.visitInsn(DUP);
             BytecodeHelper.pushConstant(mv, i);
             Expression elementExpression = expression.getExpression(i);
@@ -1764,6 +1714,7 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getOperandStack().push(expression.getType());
     }
 
+    @Override
     public void visitClosureListExpression(ClosureListExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
         controller.getCompileStack().pushVariableScope(expression.getVariableScope());
@@ -1771,11 +1722,9 @@ public class AsmClassGenerator extends ClassGenerator {
         List<Expression> expressions = expression.getExpressions();
         final int size = expressions.size();
         // init declarations
-//        LinkedList<DeclarationExpression> declarations = new LinkedList<DeclarationExpression>();
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             Expression expr = expressions.get(i);
             if (expr instanceof DeclarationExpression) {
-//                declarations.add((DeclarationExpression) expr);
                 DeclarationExpression de = (DeclarationExpression) expr;
                 BinaryExpression be = new BinaryExpression(
                         de.getLeftExpression(),
@@ -1787,7 +1736,7 @@ public class AsmClassGenerator extends ClassGenerator {
             }
         }
 
-        LinkedList instructions = new LinkedList();
+        List<Object> instructions = new LinkedList<>();
         BytecodeSequence seq = new BytecodeSequence(instructions);
         BlockStatement bs = new BlockStatement();
         bs.addStatement(seq);
@@ -1810,17 +1759,15 @@ public class AsmClassGenerator extends ClassGenerator {
         });
 
         // visit cases
-        for (int i = 0; i < size; i++) {
-            final Label label = new Label();
-            Object expr = expressions.get(i);
-            final boolean isStatement = expr instanceof Statement;
+        for (int i = 0; i < size; i += 1) {
+            Label label = new Label();
+            Expression expr = expressions.get(i);
             labels[i] = label;
             instructions.add(new BytecodeInstruction() {
                 public void visit(MethodVisitor mv) {
                     mv.visitLabel(label);
-                    // expressions will leave a value on stack, statements not
-                    // so expressions need to pop the alibi null
-                    if (!isStatement) mv.visitInsn(POP);
+                    // expressions will leave a value on stack, so need to pop the alibi null
+                    mv.visitInsn(POP);
                 }
             });
             instructions.add(expr);
@@ -1832,17 +1779,15 @@ public class AsmClassGenerator extends ClassGenerator {
         }
 
         // default case
-        {
-            instructions.add(new BytecodeInstruction() {
-                public void visit(MethodVisitor mv) {
-                    mv.visitLabel(dflt);
-                }
-            });
-            ConstantExpression text = new ConstantExpression("invalid index for closure");
-            ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
-            ThrowStatement ts = new ThrowStatement(cce);
-            instructions.add(ts);
-        }
+        instructions.add(new BytecodeInstruction() {
+            public void visit(MethodVisitor mv) {
+                mv.visitLabel(dflt);
+            }
+        });
+        ConstantExpression text = new ConstantExpression("invalid index for closure");
+        ConstructorCallExpression cce = new ConstructorCallExpression(ClassHelper.make(IllegalArgumentException.class), text);
+        ThrowStatement ts = new ThrowStatement(cce);
+        instructions.add(ts);
 
         // return
         instructions.add(new BytecodeInstruction() {
@@ -1863,7 +1808,7 @@ public class AsmClassGenerator extends ClassGenerator {
         int listArrayVar = controller.getCompileStack().defineTemporaryVariable("_listOfClosures", true);
 
         // add curried versions
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             // stack: closure
 
             // we need to create a curried closure version
@@ -1909,6 +1854,13 @@ public class AsmClassGenerator extends ClassGenerator {
         controller.getOperandStack().pop();
     }
 
+    @Override
+    public void visitBytecodeExpression(BytecodeExpression expression) {
+        expression.visit(controller.getMethodVisitor());
+        controller.getOperandStack().push(expression.getType());
+    }
+
+    @Override
     public void visitBytecodeSequence(BytecodeSequence bytecodeSequence) {
         MethodVisitor mv = controller.getMethodVisitor();
         List instructions = bytecodeSequence.getInstructions();
@@ -1927,11 +1879,12 @@ public class AsmClassGenerator extends ClassGenerator {
                 runner.visit(mv);
             }
         }
-        controller.getOperandStack().remove(mark-controller.getOperandStack().getStackLength());
+        controller.getOperandStack().remove(mark - controller.getOperandStack().getStackLength());
     }
 
+    @Override
     public void visitListExpression(ListExpression expression) {
-        onLineNumber(expression,"ListExpression" );
+        onLineNumber(expression, "ListExpression");
 
         int size = expression.getExpressions().size();
         boolean containsSpreadExpression = containsSpreadExpression(expression);
@@ -1943,7 +1896,7 @@ public class AsmClassGenerator extends ClassGenerator {
             mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
             int maxInit = 1000;
             if (size<maxInit || !containsOnlyConstants) {
-                for (int i = 0; i < size; i++) {
+                for (int i = 0; i < size; i += 1) {
                     mv.visitInsn(DUP);
                     BytecodeHelper.pushConstant(mv, i);
                     expression.getExpression(i).visit(this);
@@ -1953,14 +1906,14 @@ public class AsmClassGenerator extends ClassGenerator {
                 controller.getOperandStack().remove(size);
             } else {
                 List<Expression> expressions = expression.getExpressions();
-                List<String> methods = new ArrayList();
+                List<String> methods = new ArrayList<>();
                 MethodVisitor oldMv = mv;
                 int index = 0;
                 while (index<size) {
                     String methodName = "$createListEntry_" + controller.getNextHelperMethodIndex();
                     methods.add(methodName);
                     mv = controller.getClassVisitor().visitMethod(
-                            ACC_PRIVATE+ACC_STATIC+ACC_SYNTHETIC,
+                            ACC_PRIVATE + ACC_STATIC + ACC_SYNTHETIC,
                             methodName,
                             "([Ljava/lang/Object;)V",
                             null, null);
@@ -1968,7 +1921,7 @@ public class AsmClassGenerator extends ClassGenerator {
                     mv.visitCode();
                     int methodBlockSize = Math.min(size-index, maxInit);
                     int methodBlockEnd = index + methodBlockSize;
-                    for (; index < methodBlockEnd; index++) {
+                    for (; index < methodBlockEnd; index += 1) {
                         mv.visitVarInsn(ALOAD, 0);
                         mv.visitLdcInsn(index);
                         expressions.get(index).visit(this);
@@ -1994,14 +1947,7 @@ public class AsmClassGenerator extends ClassGenerator {
         operandStack.push(ClassHelper.LIST_TYPE);
     }
 
-    private static boolean containsOnlyConstants(ListExpression list) {
-        for (Expression exp : list.getExpressions()) {
-            if (exp instanceof ConstantExpression) continue;
-            return false;
-        }
-        return true;
-    }
-
+    @Override
     public void visitGStringExpression(GStringExpression expression) {
         MethodVisitor mv = controller.getMethodVisitor();
 
@@ -2012,7 +1958,7 @@ public class AsmClassGenerator extends ClassGenerator {
         BytecodeHelper.pushConstant(mv, size);
         mv.visitTypeInsn(ANEWARRAY, "java/lang/Object");
 
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             mv.visitInsn(DUP);
             BytecodeHelper.pushConstant(mv, i);
             expression.getValue(i).visit(this);
@@ -2021,15 +1967,15 @@ public class AsmClassGenerator extends ClassGenerator {
         }
         controller.getOperandStack().remove(size);
 
-        List strings = expression.getStrings();
+        List<ConstantExpression> strings = expression.getStrings();
         size = strings.size();
         BytecodeHelper.pushConstant(mv, size);
         mv.visitTypeInsn(ANEWARRAY, "java/lang/String");
 
-        for (int i = 0; i < size; i++) {
+        for (int i = 0; i < size; i += 1) {
             mv.visitInsn(DUP);
             BytecodeHelper.pushConstant(mv, i);
-            controller.getOperandStack().pushConstant((ConstantExpression) strings.get(i));
+            controller.getOperandStack().pushConstant(strings.get(i));
             controller.getOperandStack().box();
             mv.visitInsn(AASTORE);
         }
@@ -2042,6 +1988,7 @@ public class AsmClassGenerator extends ClassGenerator {
     /**
      * Note: ignore it. Annotation generation needs the current visitor.
      */
+    @Override
     public void visitAnnotations(AnnotatedNode node) {
     }
 
@@ -2098,38 +2045,37 @@ public class AsmClassGenerator extends ClassGenerator {
         Map<String, Object> atAttrs = new HashMap<>();
         Map<String, ListExpression> arrayAttrs = new HashMap<>();
 
-        for (String name : an.getMembers().keySet()) {
-            Expression expr = an.getMember(name);
+        for (Map.Entry<String, Expression> member : an.getMembers().entrySet()) {
+            String name = member.getKey();
+            Expression expr = member.getValue();
             if (expr instanceof AnnotationConstantExpression) {
                 atAttrs.put(name, ((AnnotationConstantExpression) expr).getValue());
             } else if (expr instanceof ConstantExpression) {
                 constantAttrs.put(name, ((ConstantExpression) expr).getValue());
             } else if (expr instanceof ClassExpression) {
-                constantAttrs.put(name,
-                        Type.getType(BytecodeHelper.getTypeDescription((expr.getType()))));
+                constantAttrs.put(name, Type.getType(BytecodeHelper.getTypeDescription((expr.getType()))));
             } else if (expr instanceof PropertyExpression) {
                 enumAttrs.put(name, (PropertyExpression) expr);
             } else if (expr instanceof ListExpression) {
                 arrayAttrs.put(name, (ListExpression) expr);
             } else if (expr instanceof ClosureExpression) {
                 ClassNode closureClass = controller.getClosureWriter().getOrAddClosureClass((ClosureExpression) expr, ACC_PUBLIC);
-                constantAttrs.put(name,
-                        Type.getType(BytecodeHelper.getTypeDescription(closureClass)));
+                constantAttrs.put(name, Type.getType(BytecodeHelper.getTypeDescription(closureClass)));
             }
         }
 
-        for (Map.Entry entry : constantAttrs.entrySet()) {
-            av.visit((String) entry.getKey(), entry.getValue());
+        for (Map.Entry<String, Object> entry : constantAttrs.entrySet()) {
+            av.visit(entry.getKey(), entry.getValue());
         }
-        for (Map.Entry entry : enumAttrs.entrySet()) {
-            PropertyExpression propExp = (PropertyExpression) entry.getValue();
-            av.visitEnum((String) entry.getKey(),
+        for (Map.Entry<String, PropertyExpression> entry : enumAttrs.entrySet()) {
+            PropertyExpression propExp = entry.getValue();
+            av.visitEnum(entry.getKey(),
                     BytecodeHelper.getTypeDescription(propExp.getObjectExpression().getType()),
                     String.valueOf(((ConstantExpression) propExp.getProperty()).getValue()));
         }
-        for (Map.Entry entry : atAttrs.entrySet()) {
+        for (Map.Entry<String, Object> entry : atAttrs.entrySet()) {
             AnnotationNode atNode = (AnnotationNode) entry.getValue();
-            AnnotationVisitor av2 = av.visitAnnotation((String) entry.getKey(),
+            AnnotationVisitor av2 = av.visitAnnotation(entry.getKey(),
                     BytecodeHelper.getTypeDescription(atNode.getClassNode()));
             visitAnnotationAttributes(atNode, av2);
             av2.visitEnd();
@@ -2139,9 +2085,9 @@ public class AsmClassGenerator extends ClassGenerator {
 
     private void visitArrayAttributes(AnnotationNode an, Map<String, ListExpression> arrayAttr, AnnotationVisitor av) {
         if (arrayAttr.isEmpty()) return;
-        for (Map.Entry entry : arrayAttr.entrySet()) {
-            AnnotationVisitor av2 = av.visitArray((String) entry.getKey());
-            List<Expression> values = ((ListExpression) entry.getValue()).getExpressions();
+        for (Map.Entry<String, ListExpression> entry : arrayAttr.entrySet()) {
+            AnnotationVisitor av2 = av.visitArray(entry.getKey());
+            List<Expression> values = entry.getValue().getExpressions();
             if (!values.isEmpty()) {
                 int arrayElementType = determineCommonArrayType(values);
                 for (Expression exprChild : values) {
@@ -2152,8 +2098,8 @@ public class AsmClassGenerator extends ClassGenerator {
         }
     }
 
-    private static int determineCommonArrayType(List values) {
-        Expression expr = (Expression) values.get(0);
+    private static int determineCommonArrayType(List<Expression> values) {
+        Expression expr = values.get(0);
         int arrayElementType = -1;
         if (expr instanceof AnnotationConstantExpression) {
             arrayElementType = 1;
@@ -2193,52 +2139,74 @@ public class AsmClassGenerator extends ClassGenerator {
     // Implementation methods
     //-------------------------------------------------------------------------
 
-    public void visitBytecodeExpression(BytecodeExpression cle) {
-        cle.visit(controller.getMethodVisitor());
-        controller.getOperandStack().push(cle.getType());
+    public static int argumentSize(Expression arguments) {
+        if (arguments instanceof TupleExpression) {
+            TupleExpression tupleExpression = (TupleExpression) arguments;
+            int size = tupleExpression.getExpressions().size();
+            return size;
+        }
+        return 1;
+    }
+
+    private static String[] buildExceptions(ClassNode[] exceptions) {
+        if (exceptions == null) return null;
+        return Arrays.stream(exceptions).map(BytecodeHelper::getClassInternalName).toArray(String[]::new);
     }
 
-    public static boolean isThisExpression(Expression expression) {
-        if (expression instanceof VariableExpression) {
-            VariableExpression varExp = (VariableExpression) expression;
-            return varExp.getName().equals("this");
+    private static boolean containsOnlyConstants(ListExpression list) {
+        for (Expression exp : list.getExpressions()) {
+            if (exp instanceof ConstantExpression) continue;
+            return false;
         }
-        return false;
+        return true;
     }
 
-    private static boolean isSuperExpression(Expression expression) {
-        if (expression instanceof VariableExpression) {
-            VariableExpression varExp = (VariableExpression) expression;
-            return varExp.getName().equals("super");
+    public static boolean containsSpreadExpression(Expression arguments) {
+        List<Expression> args = null;
+        if (arguments instanceof TupleExpression) {
+            TupleExpression tupleExpression = (TupleExpression) arguments;
+            args = tupleExpression.getExpressions();
+        } else if (arguments instanceof ListExpression) {
+            ListExpression le = (ListExpression) arguments;
+            args = le.getExpressions();
+        } else {
+            return arguments instanceof SpreadExpression;
+        }
+        for (Expression arg : args) {
+            if (arg instanceof SpreadExpression) return true;
         }
         return false;
     }
 
-    private static boolean isThisOrSuper(Expression expression) {
-        return isThisExpression(expression) || isSuperExpression(expression);
+    private boolean isInnerClass() {
+        return controller.getClassNode().getOuterClass() != null;
     }
 
-    public void onLineNumber(ASTNode statement, String message) {
-        if (statement == null || statement instanceof BlockStatement) return;
+    public static boolean isNullConstant(Expression expression) {
+        return expression instanceof ConstantExpression && ((ConstantExpression) expression).isNullExpression();
+    }
 
-        currentASTNode = statement;
-        int line = statement.getLineNumber();
-        if (line < 0 || (!ASM_DEBUG && line == controller.getLineNumber())) return;
+    public static boolean isThisExpression(Expression expression) {
+        return expression instanceof VariableExpression && ((VariableExpression) expression).isThisExpression();
+    }
 
-        controller.setLineNumber(line);
-        MethodVisitor mv = controller.getMethodVisitor();
-        if (mv != null) {
-            Label l = new Label();
-            mv.visitLabel(l);
-            mv.visitLineNumber(line, l);
-        }
+    private static boolean isSuperExpression(Expression expression) {
+        return expression instanceof VariableExpression && ((VariableExpression) expression).isSuperExpression();
     }
 
-    private boolean isInnerClass() {
-        return controller.getClassNode() instanceof InnerClassNode;
+    private static boolean isThisOrSuper(Expression expression) {
+        return isThisExpression(expression) || isSuperExpression(expression);
+    }
+
+    private static boolean isVargs(Parameter[] params) {
+        return (params.length > 0 && params[params.length - 1].getType().isArray());
     }
 
-    protected CompileUnit getCompileUnit() {
+    private static boolean samePackages(String pkg1, String pkg2) {
+        return Objects.equals(pkg1, pkg2);
+    }
+
+    private CompileUnit getCompileUnit() {
         CompileUnit answer = controller.getClassNode().getCompileUnit();
         if (answer == null) {
             answer = context.getCompileUnit();
@@ -2252,4 +2220,24 @@ public class AsmClassGenerator extends ClassGenerator {
         mn.getUnit().addGeneratedInnerClass((InnerClassNode)innerClass);
         return innerClasses.add(innerClass);
     }
+
+    public void onLineNumber(ASTNode statement, String message) {
+        if (statement == null || statement instanceof BlockStatement) return;
+
+        currentASTNode = statement;
+        int line = statement.getLineNumber();
+        if (line < 0 || (!ASM_DEBUG && line == controller.getLineNumber())) return;
+
+        controller.setLineNumber(line);
+        MethodVisitor mv = controller.getMethodVisitor();
+        if (mv != null) {
+            Label l = new Label();
+            mv.visitLabel(l);
+            mv.visitLineNumber(line, l);
+        }
+    }
+
+    public void throwException(String s) {
+        throw new RuntimeParserException(s, currentASTNode);
+    }
 }


[groovy] 08/18: Trivial refactoring: Remove redundant type arguments

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 c7894e0c61469d90ef7efe3b15d02e9543ce6f34
Author: Daniel.Sun <re...@hotmail.com>
AuthorDate: Fri Nov 15 15:48:43 2019 +0800

    Trivial refactoring: Remove redundant type arguments
    
    (cherry picked from commit abf7dda3a5b3626e3ce3de1e4703f8aa9ccebcf6)
---
 .../groovy/transform/stc/StaticTypeCheckingVisitor.java  | 16 ++++++++--------
 1 file changed, 8 insertions(+), 8 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
index 5b803f0..a64a53e 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3705,27 +3705,27 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
         final ClassNode receiver = getType(objectExpression);
         List<Receiver<String>> owners = new LinkedList<>();
-        owners.add(Receiver.<String>make(receiver));
+        owners.add(Receiver.make(receiver));
         if (isClassClassNodeWrappingConcreteType(receiver)) {
             GenericsType clazzGT = receiver.getGenericsTypes()[0];
-            owners.add(0, Receiver.<String>make(clazzGT.getType()));
+            owners.add(0, Receiver.make(clazzGT.getType()));
         }
         if (receiver.isInterface()) {
-            owners.add(Receiver.<String>make(OBJECT_TYPE));
+            owners.add(Receiver.make(OBJECT_TYPE));
         }
         addSelfTypes(receiver, owners);
         if (!typeCheckingContext.temporaryIfBranchTypeInformation.empty()) {
             List<ClassNode> potentialReceiverType = getTemporaryTypesForExpression(objectExpression);
             if (potentialReceiverType != null) {
                 for (ClassNode node : potentialReceiverType) {
-                    owners.add(Receiver.<String>make(node));
+                    owners.add(Receiver.make(node));
                 }
             }
         }
         if (typeCheckingContext.lastImplicitItType != null
                 && objectExpression instanceof VariableExpression
                 && ((VariableExpression) objectExpression).getName().equals("it")) {
-            owners.add(Receiver.<String>make(typeCheckingContext.lastImplicitItType));
+            owners.add(Receiver.make(typeCheckingContext.lastImplicitItType));
         }
         if (typeCheckingContext.delegationMetadata != null
                 && objectExpression instanceof VariableExpression
@@ -3733,7 +3733,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 && /*isNested:*/typeCheckingContext.delegationMetadata.getParent() != null) {
             owners.clear();
             List<Receiver<String>> enclosingClass = Collections.singletonList(
-                    Receiver.<String>make(typeCheckingContext.getEnclosingClassNode()));
+                    Receiver.make(typeCheckingContext.getEnclosingClassNode()));
             addReceivers(owners, enclosingClass, typeCheckingContext.delegationMetadata.getParent(), "owner.");
         }
         return owners;
@@ -3742,7 +3742,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private static void addSelfTypes(final ClassNode receiver, final List<Receiver<String>> owners) {
         LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<>();
         for (ClassNode selfType : Traits.collectSelfTypes(receiver, selfTypes)) {
-            owners.add(Receiver.<String>make(selfType));
+            owners.add(Receiver.make(selfType));
         }
     }
 
@@ -5751,6 +5751,6 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
         }
 
-        return variable.getOriginType();
+        return originType;
     }
 }


[groovy] 14/18: GROOVY-8955: prevent Matcher.find()'s side-effect on Matcher.asBoolean()

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 557f889d2eac60258be971b2b5738e23b7f14c49
Author: Szymon Stępniak <wo...@github.com>
AuthorDate: Fri Nov 15 11:05:48 2019 -0600

    GROOVY-8955: prevent Matcher.find()'s side-effect on Matcher.asBoolean()
    
    This closes #815
    
    (cherry picked from commit f0d1c9abef1780c8f7088d002309f7384cdec6f2)
---
 .../groovy/runtime/StringGroovyMethods.java        | 34 +++++++-------
 src/spec/doc/core-operators.adoc                   |  8 ++--
 src/test/groovy/RegularExpressionsTest.groovy      | 53 +++++++++++++++++-----
 .../groovy/runtime/StringGroovyMethodsTest.java    | 39 ++++++++++++++--
 4 files changed, 98 insertions(+), 36 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
index 72b39f6..8500643 100644
--- a/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/StringGroovyMethods.java
@@ -78,16 +78,15 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
      * A string is coerced to false if it is of length 0,
      * and to true otherwise.
      *
-     * @param string the character sequence
+     * @param chars the character sequence
      * @return the boolean value
      * @since 1.7.0
      */
-    public static boolean asBoolean(CharSequence string) {
-        if (null == string) {
-            return false;
+    public static boolean asBoolean(CharSequence chars) {
+        if (chars != null) {
+            return chars.length() > 0;
         }
-
-        return string.length() > 0;
+        return false;
     }
 
     /**
@@ -98,12 +97,11 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
      * @since 1.7.0
      */
     public static boolean asBoolean(Matcher matcher) {
-        if (null == matcher) {
-            return false;
+        if (matcher != null) {
+            RegexSupport.setLastMatcher(matcher);
+            return matcher.find(0); //GROOVY-8855
         }
-
-        RegexSupport.setLastMatcher(matcher);
-        return matcher.find();
+        return false;
     }
 
     /**
@@ -917,8 +915,8 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
         if (matcher.find()) {
             if (hasGroup(matcher)) {
                 int count = matcher.groupCount();
-                List groups = new ArrayList(count);
-                for (int i = 0; i <= count; i++) {
+                List<String> groups = new ArrayList<>(count);
+                for (int i = 0; i <= count; i += 1) {
                     groups.add(matcher.group(i));
                 }
                 return InvokerHelper.toString(closure.call(groups));
@@ -1354,7 +1352,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
         int counter = 0;
         matcher.reset();
         while (matcher.find()) {
-            counter++;
+            counter += 1;
         }
         return counter;
     }
@@ -1596,7 +1594,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
      * @see java.util.regex.Matcher#group()
      * @since 1.0
      */
-    public static Iterator iterator(final Matcher matcher) {
+    public static Iterator iterator(Matcher matcher) {
         matcher.reset();
         return new Iterator() {
             private boolean found /* = false */;
@@ -1627,7 +1625,7 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
                     // are we using groups?
                     // yes, so return the specified group as list
                     List<String> list = new ArrayList<String>(matcher.groupCount());
-                    for (int i = 0; i <= matcher.groupCount(); i++) {
+                    for (int i = 0; i <= matcher.groupCount(); i += 1) {
                         list.add(matcher.group(i));
                     }
                     return list;
@@ -2464,13 +2462,13 @@ public class StringGroovyMethods extends DefaultGroovyMethodsSupport {
             matcher.reset();
         } else if (idx > 0) {
             matcher.reset();
-            for (int i = 0; i < idx; i++) {
+            for (int i = 0; i < idx; i += 1) {
                 matcher.find();
             }
         } else if (idx < 0) {
             matcher.reset();
             idx += getCount(matcher);
-            for (int i = 0; i < idx; i++) {
+            for (int i = 0; i < idx; i += 1) {
                 matcher.find();
             }
         }
diff --git a/src/spec/doc/core-operators.adoc b/src/spec/doc/core-operators.adoc
index e1a64f5..3ed328c 100644
--- a/src/spec/doc/core-operators.adoc
+++ b/src/spec/doc/core-operators.adoc
@@ -439,8 +439,7 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_op_variant
 
 === Find operator
 
-Alternatively to building a pattern, you can directly use the find operator `=~` to build a `java.util.regex.Matcher`
-instance:
+Alternatively to building a pattern, you can use the find operator `=~` to directly create a `java.util.regex.Matcher` instance:
 
 [source,groovy]
 ----
@@ -448,10 +447,11 @@ include::{projectdir}/src/spec/test/OperatorsTest.groovy[tags=pattern_matcher_op
 ----
 <1> `=~` creates a matcher against the `text` variable, using the pattern on the right hand side
 <2> the return type of `=~` is a `Matcher`
-<3> equivalent to calling `if (!m.find())`
+<3> equivalent to calling `if (!m.find(0))`
 
 Since a `Matcher` coerces to a `boolean` by calling its `find` method, the `=~` operator is consistent with the simple
-use of Perl's `=~` operator, when it appears as a predicate (in `if`, `while`, etc.).
+use of Perl's `=~` operator, when it appears as a predicate (in `if`, `?:`, etc.). When the intent is to iterate over
+matches of the specified pattern (in `while`, etc.) call `find()` directly on the matcher or use the `iterator` DGM.
 
 === Match operator
 
diff --git a/src/test/groovy/RegularExpressionsTest.groovy b/src/test/groovy/RegularExpressionsTest.groovy
index 45f93b1..d256f1c 100644
--- a/src/test/groovy/RegularExpressionsTest.groovy
+++ b/src/test/groovy/RegularExpressionsTest.groovy
@@ -18,22 +18,25 @@
  */
 package groovy
 
-import groovy.test.GroovyTestCase
+import org.junit.Test
 
 import java.util.regex.Matcher
 import java.util.regex.Pattern
 
+import static groovy.test.GroovyAssert.shouldFail
+
 /**
  * Tests Groovy's regular expression syntax and DGM methods.
  */
-class RegularExpressionsTest extends GroovyTestCase {
+final class RegularExpressionsTest {
 
+    @Test
     void testMatchOperator() {
         assert "cheese" ==~ "cheese"
         assert !("cheesecheese" ==~ "cheese")
     }
 
-    // The find operator is: =~
+    @Test // The find operator is: =~
     void testFindOperator() {
         assert "cheese" =~ "cheese"
 
@@ -46,14 +49,14 @@ class RegularExpressionsTest extends GroovyTestCase {
 
         assert m instanceof Matcher
 
-        while (m) {
+        while (m.find()) {
             i = i + 1
         }
         assert i == 2
 
         i = 0
         m = "cheesecheese" =~ "e+"
-        while (m) {
+        while (m.find()) {
             i = i + 1
         }
         assert i == 4
@@ -65,7 +68,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert m.group() == "ee"
     }
 
-    // From the javadoc of the getAt() method     
+    @Test // From the javadoc of the getAt() method
     void testMatcherWithIntIndex() {
         def p = /ab[d|f]/
         def m = "abcabdabeabf" =~ p
@@ -98,6 +101,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testMatcherWithIndexAndRanges() {
         def string = "cheesecheese"
         def matcher = string =~ "e+"
@@ -117,6 +121,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         shouldFail { matcher[0, [1, 2]] }
     }
 
+    @Test
     void testMatcherIterator() {
         def matcher = "cheesecheese" =~ "e+"
         def iter = matcher.iterator()
@@ -154,6 +159,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert [["chee", "ch"], ["se", "s"], [" ple", " pl"], ["ase", "as"]] == matcher.collect { it }
     }
 
+    @Test
     void testMatcherEach() {
         def count = 0
         def result = []
@@ -183,7 +189,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert [["chee", "ch"], ["se", "s"], [" ple", " pl"], ["ase", "as"]] == result
     }
 
-    // Check consistency between each and collect
+    @Test // Check consistency between each and collect
     void testMatcherEachVsCollect() {
         def matcher = "cheese cheese" =~ "e+"
         def result = []
@@ -210,6 +216,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert result == matcher.collect { a, g -> g }
     }
 
+    @Test
     void testSimplePattern() {
         def pattern = ~"foo"
         assert pattern instanceof Pattern
@@ -217,6 +224,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert !pattern.matcher("bar").matches()
     }
 
+    @Test
     void testMultiLinePattern() {
         def pattern = ~"""foo"""
         assert pattern instanceof Pattern
@@ -224,11 +232,12 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert !pattern.matcher("bar").matches()
     }
 
+    @Test
     void testPatternInAssertion() {
         assert "foofoofoo" =~ ~"foo"
     }
 
-
+    @Test
     void testMatcherWithReplace() {
         def matcher = "cheese-cheese" =~ "cheese"
         def answer = matcher.replaceAll("edam")
@@ -238,6 +247,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert cheese == "nice cheese!"
     }
 
+    @Test
     void testGetLastMatcher() {
         assert "cheese" ==~ "cheese"
         assert Matcher.getLastMatcher().matches()
@@ -258,6 +268,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testRyhmeMatchGina() {
         def myFairStringy = 'The rain in Spain stays mainly in the plain!'
         // words, that end with 'ain': \b\w*ain\b
@@ -276,6 +287,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert found == 'rain Spain plain '
     }
 
+    @Test
     void testEachMatchWithPattern() {
         def compiledPattern = ~/.at/
         def result = []
@@ -283,6 +295,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert "cat sat hat" == result.join(" ")
     }
 
+    @Test
     void testPatternVersionsOfStringRegexMethods() {
         def compiledPattern = ~/.at/
         def s = "The cat sat on the hat"
@@ -291,6 +304,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert s.replaceAll(compiledPattern, 'x') == "The x x on the x"
     }
 
+    @Test
     void testFindOperatorCollect() {
         def m = 'coffee' =~ /ee/
         def result = ''
@@ -311,6 +325,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert m.collect { it }.join(',') == 'ee,ee'
     }
 
+    @Test
     void testIteration() {
         def string = 'a:1 b:2 c:3'
         def result = []
@@ -339,12 +354,14 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert numbers == '123'
     }
 
+    @Test
     void testFirst() {
         assert "cheesecheese" =~ "cheese"
         assert "cheesecheese" =~ /cheese/
         assert "cheese" == /cheese/   /*they are both string syntaxes*/
     }
 
+    @Test
     void testSecond() {
         // Let's create a regex Pattern
         def pattern = ~/foo/
@@ -352,6 +369,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert pattern.matcher("foo").matches()
     }
 
+    @Test
     void testThird() {
         // Let's create a Matcher
         def matcher = "cheesecheese" =~ /cheese/
@@ -360,12 +378,14 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert answer == "edamedam"
     }
 
+    @Test
     void testFourth() {
         // Let's do some replacement
         def cheese = ("cheesecheese" =~ /cheese/).replaceFirst("nice")
         assert cheese == "nicecheese"
     }
 
+    @Test
     void testFifth() {
         def matcher = "\$abc." =~ "\\\$(.*)\\."
         matcher.matches();                   // must be invoked
@@ -374,6 +394,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert matcher[0][1] == "abc"
     }
 
+    @Test
     void testSixth() {
         def matcher = "\$abc." =~ /\$(.*)\./    // no need to double-escape!
         assert "\\\$(.*)\\." == /\$(.*)\./
@@ -383,6 +404,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert matcher[0][1] == "abc"
     }
 
+    @Test
     void testReplaceWithClosure() {
         assert '1-FISH, two fish' == "one fish, two fish".replaceFirst(~/([a-z]{3})\s([a-z]{4})/) {
             [one: 1, two: 2][it[1]] + '-' + it[2].toUpperCase()
@@ -392,6 +414,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         }
     }
 
+    @Test
     void testNoGroupMatcherAndGet() {
         def p = /ab[d|f]/
         def m = "abcabdabeabf" =~ p
@@ -404,6 +427,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert result == ['0:abd', '1:abf']
     }
 
+    @Test
     void testFindWithOneGroupAndGet() {
         def p = /(?:ab([c|d|e|f]))/
         def m = "abcabdabeabf" =~ p
@@ -416,6 +440,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert result == ['0:[abc, c]', '1:[abd, d]', '2:[abe, e]', '3:[abf, f]']
     }
 
+    @Test
     void testAnotherOneGroupMatcherAndGet() {
         def m = "abcabdabeabfabxyzabx" =~ /(?:ab([d|x-z]+))/
         def result = []
@@ -445,24 +470,28 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert '$\\23\\$\\45\\' == '$\\23\\$\\45\\'.replaceAll(p, c)
     }
 
+    @Test
     void testReplaceAllClosure() {
         def p = /([^z]*)(z)/
         def c = { all, m, d -> m }
         replaceAllHelper(p, c)
     }
 
+    @Test
     void testReplaceAllClosureWithIt() {
         def p = /([^z]*)(z)/
         def c = { it[1] }
         replaceAllHelper(p, c)
     }
 
+    @Test
     void testReplaceAllClosureWithObjectArray() {
         def p = /([^z]*)(z)/
         def c = { Object[] a -> a[1] }
         replaceAllHelper(p, c)
     }
 
+    @Test
     void testFind() {
         def p = /.ar/
         assert null == 'foo foo baz'.find(p)
@@ -478,6 +507,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert 'bar' == 'foo bar baz'.find(compiledPattern)
     }
 
+    @Test
     void testFindClosureNoGroups() {
         def p = /.ar/
         def c = { match -> return "-$match-" }
@@ -491,6 +521,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert '-car-' == 'car'.find(compiledPattern, c)
     }
 
+    @Test
     void testFindClosureWithGroups() {
         def AREA_CODE = /\d{3}/
         def EXCHANGE = /\d{3}/
@@ -515,6 +546,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert "(888) 555-1212" == "bar 888-555-1212 foo".find(compiledPhonePattern, closureSingleVar)
     }
 
+    @Test
     void testFindAll() {
         def p = /.at/
         def compiledPattern = ~p
@@ -528,6 +560,7 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert ["+cat", "+sat", "+hat"] == orig.findAll(compiledPattern) { "+$it" }
     }
 
+    @Test
     void testFindAllWithGroups() {
         def p = /(.)a(.)/
         def compiledPattern = ~p
@@ -545,10 +578,9 @@ class RegularExpressionsTest extends GroovyTestCase {
         assert ["c+cat+t", "s+sat+t", "h+hat+t"] == orig.findAll(compiledPattern, closureSingleVar)
     }
 
+    @Test
     void testMatchesPartially() {
-
         def pattern = /\w+@\w+\.\w{2,}/
-
         def useCases = [
                 "glaforge@gmail.com": true,
                 "glaforge"          : true,
@@ -556,7 +588,6 @@ class RegularExpressionsTest extends GroovyTestCase {
                 "glaforge@"         : true,
                 "glaforge@@"        : false
         ]
-
         useCases.each { String email, boolean bool ->
             def matcher = email =~ pattern
 
diff --git a/src/test/org/codehaus/groovy/runtime/StringGroovyMethodsTest.java b/src/test/org/codehaus/groovy/runtime/StringGroovyMethodsTest.java
index 5e7fccd..e892ce4 100644
--- a/src/test/org/codehaus/groovy/runtime/StringGroovyMethodsTest.java
+++ b/src/test/org/codehaus/groovy/runtime/StringGroovyMethodsTest.java
@@ -19,16 +19,22 @@
 package org.codehaus.groovy.runtime;
 
 import groovy.lang.Closure;
-import groovy.test.GroovyTestCase;
+import org.junit.Test;
 
 import java.math.BigDecimal;
 import java.math.BigInteger;
 import java.util.Collections;
 import java.util.List;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
-public class StringGroovyMethodsTest extends GroovyTestCase {
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
 
+public final class StringGroovyMethodsTest {
+
+    @Test
     public void testIncrementString() throws Exception {
         String original = "z";
         String answer = StringGroovyMethods.next(original);
@@ -37,6 +43,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertTrue(answer.compareTo(original) > 0);
     }
 
+    @Test
     public void testDecrementString() throws Exception {
         String original = "a";
         String answer = StringGroovyMethods.previous(original);
@@ -45,6 +52,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertTrue(ScriptBytecodeAdapter.compareLessThan(answer, original));
     }
 
+    @Test
     public void testToMethods() throws Exception {
         assertEquals(StringGroovyMethods.toInteger("1"), new Integer(1));
         assertEquals(StringGroovyMethods.toLong("1"), new Long(1));
@@ -61,6 +69,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(StringGroovyMethods.toBoolean("0"), Boolean.FALSE);
     }
 
+    @Test
     public void testIsMethods() throws Exception {
         String intStr = "123";
         String floatStr = "1.23E-1";
@@ -91,16 +100,33 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertFalse(StringGroovyMethods.isNumber(nonNumberStr));
     }
 
+    @Test
+    public void testAsMethods() {
+        Pattern pattern = Pattern.compile("[a-z]+");
+        String correctInput = "abcde";
+        String incorrectInput = "123";
+        Matcher correctMatcher = pattern.matcher(correctInput);
+        Matcher incorrectMatcher = pattern.matcher(incorrectInput);
+
+        assertTrue(StringGroovyMethods.asBoolean(correctMatcher));
+        assertTrue(StringGroovyMethods.asBoolean(correctMatcher));
+        assertFalse(StringGroovyMethods.asBoolean(incorrectMatcher));
+        assertFalse(StringGroovyMethods.asBoolean(incorrectMatcher));
+    }
+
+    @Test
     public void testStartsWithAny() {
         assertTrue(StringGroovyMethods.startsWithAny("abcd", "ab", "ef"));
         assertFalse(StringGroovyMethods.startsWithAny("abcd", "ef", "gh"));
     }
 
+    @Test
     public void testEndsWithAny() {
         assertTrue(StringGroovyMethods.endsWithAny("abcd", "cd", "ef"));
         assertFalse(StringGroovyMethods.endsWithAny("abcd", "ef", "gh"));
     }
 
+    @Test
     public void testIsBlank() {
         assertTrue(StringGroovyMethods.isBlank(""));
         assertTrue(StringGroovyMethods.isBlank(" "));
@@ -125,6 +151,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertFalse(StringGroovyMethods.isBlank("\tabc\t"));
     }
 
+    @Test
     public void testFindAllFromCharSequenceWithClosure() {
         CharSequence charSequence = new StringBuilder().append("ABCD");
         String regex = "(A)(B)(C)(D)";
@@ -134,6 +161,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindAllFromCharSequenceWithPatternAndClosure() {
         CharSequence charSequence = new StringBuilder().append("ABCD");
         Pattern pattern = Pattern.compile("(A)(B)(C)(D)");
@@ -143,6 +171,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindAllFromStringWithClosure() {
         String string = "ABCD";
         String regex = "(A)(B)(C)(D)";
@@ -152,6 +181,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindAllFromStringWithPatternAndClosure() {
         String string = "ABCD";
         Pattern pattern = Pattern.compile("(A)(B)(C)(D)");
@@ -161,6 +191,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindFromCharSequenceWithClosure() {
         CharSequence charSequence = new StringBuilder().append("ABCD");
         String regex = "(A)(B)(C)(D)";
@@ -170,6 +201,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindFromCharSequenceWithPatternAndClosure() {
         CharSequence charSequence = new StringBuilder().append("ABCD");
         Pattern pattern = Pattern.compile("(A)(B)(C)(D)");
@@ -179,6 +211,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindFromStringWithClosure() {
         String string = "ABCD";
         String regex = "(A)(B)(C)(D)";
@@ -188,6 +221,7 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
         assertEquals(expectedResult, result);
     }
 
+    @Test
     public void testFindFromStringWithPatternAndClosure() {
         String string = "ABCD";
         Pattern pattern = Pattern.compile("(A)(B)(C)(D)");
@@ -211,5 +245,4 @@ public class StringGroovyMethodsTest extends GroovyTestCase {
             }
         };
     }
-
 }


[groovy] 06/18: GROOVY-8423: Do not adjust access modifiers for inner class table

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 7b749c28b2817d72e4a2f31239e8e0dbdb5d3b6c
Author: Shil Sinha <sh...@apache.org>
AuthorDate: Thu Nov 14 17:24:00 2019 -0600

    GROOVY-8423: Do not adjust access modifiers for inner class table
    
    This closes #648
    
    (cherry picked from commit 10cebe871a574808f1edb87c73f0c17f73a24e10)
---
 .../groovy/classgen/AsmClassGenerator.java         | 14 +-----
 src/test/gls/innerClass/InnerClassTest.groovy      | 54 +++++++++++++++++++---
 2 files changed, 50 insertions(+), 18 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
index a528d3b..bcc140f 100644
--- a/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
+++ b/src/main/java/org/codehaus/groovy/classgen/AsmClassGenerator.java
@@ -309,20 +309,11 @@ public class AsmClassGenerator extends ClassGenerator {
             outerClassName = null;
             if (innerClass.isAnonymous()) innerClassName = null;
         }
-        int mods = adjustedClassModifiersForInnerClassTable(cn);
-        if ((mods & ACC_PRIVATE) != 0) {
-            mods ^= ACC_PRIVATE;
-            innerClass.setModifiers(mods);
-        }
-        classVisitor.visitInnerClass(
-                innerClassInternalName,
-                outerClassName,
-                innerClassName,
-                mods);
+        int modifiers = adjustedClassModifiersForInnerClassTable(cn);
+        classVisitor.visitInnerClass(innerClassInternalName, outerClassName, innerClassName, modifiers);
     }
 
     /*
-     * Classes but not interfaces should have ACC_SUPER set
      * See http://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.6-300-D.2-5
      * for what flags are allowed depending on the fact we are writing the inner class table
      * or the class itself
@@ -331,7 +322,6 @@ public class AsmClassGenerator extends ClassGenerator {
         int modifiers = classNode.getModifiers();
         modifiers = modifiers & ~ACC_SUPER;
         modifiers = fixInterfaceModifiers(classNode, modifiers);
-        modifiers = fixInnerClassModifiers(classNode, modifiers);
         return modifiers;
     }
 
diff --git a/src/test/gls/innerClass/InnerClassTest.groovy b/src/test/gls/innerClass/InnerClassTest.groovy
index 7bfd0ab..9f20b7e 100644
--- a/src/test/gls/innerClass/InnerClassTest.groovy
+++ b/src/test/gls/innerClass/InnerClassTest.groovy
@@ -122,19 +122,61 @@ final class InnerClassTest {
         '''
     }
 
+    @Test // GROOVY-8423
+    void testPrivateInnerClassHasPrivateModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                private class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert isPrivate(modifiers)
+        '''
+    }
+
+    @Test // GROOVY-8423
+    void testProtectedInnerClassHasProtectedModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                protected class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert isProtected(modifiers)
+        '''
+    }
+
+    @Test // GROOVY-8423
+    void testPackagePrivateInnerClassHasProtectedModifier() {
+        assertScript '''
+            import static java.lang.reflect.Modifier.*
+
+            class A {
+                @groovy.transform.PackageScope class B {}
+            }
+
+            int modifiers = A.B.modifiers
+            assert !isPrivate(modifiers) && !isProtected(modifiers) && !isPublic(modifiers)
+        '''
+    }
+
     @Test
     void testStaticInnerClass() {
         assertScript '''
-            import java.lang.reflect.Modifier
+            import static java.lang.reflect.Modifier.*
 
             class A {
-                static class B{}
+                static class B {}
             }
-            def x = new A.B()
-            assert x != null
+            def b = new A.B()
+            assert b != null
 
-            def mods = A.B.modifiers
-            assert Modifier.isPublic(mods)
+            int modifiers = A.B.modifiers
+            assert isPublic(modifiers)
         '''
     }
 


[groovy] 18/18: GROOVY-8579, GROOVY-8930: check static interface method for direct calls

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 5c93020a456e5f73f4e9f4f1771f9a933004daf4
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Fri Nov 15 13:09:44 2019 -0600

    GROOVY-8579, GROOVY-8930: check static interface method for direct calls
    
    - calling a static interface method requires Java 1.8+ bytecode
    
    (cherry picked from commit fedc791efd562ed1fe74e3887340c38cabfcbb19)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 13 ++++++---
 .../{Groovy8579Bug.groovy => Groovy8579.groovy}    | 32 ++++++++++++++++------
 2 files changed, 33 insertions(+), 12 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 0725829..44140c0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3492,10 +3492,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
                             storeType(call, returnType);
                             storeTargetMethod(call, directMethodCallCandidate);
-                            ClassNode declaringClass = directMethodCallCandidate.getDeclaringClass();
-                            if (declaringClass.isInterface() && directMethodCallCandidate.isStatic() && !(directMethodCallCandidate instanceof ExtensionMethodNode)) {
-                                typeCheckingContext.getEnclosingClassNode().putNodeMetaData(MINIMUM_BYTECODE_VERSION, Opcodes.V1_8);
-                            }
+
                             String data = chosenReceiver.getData();
                             if (data != null) {
                                 // the method which has been chosen is supposed to be a call on delegate or owner
@@ -3768,6 +3765,14 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     protected void storeTargetMethod(final Expression call, final MethodNode directMethodCallCandidate) {
         call.putNodeMetaData(DIRECT_METHOD_CALL_TARGET, directMethodCallCandidate);
+
+        if (directMethodCallCandidate != null
+                && directMethodCallCandidate.isStatic()
+                && directMethodCallCandidate.getDeclaringClass().isInterface()
+                && !(directMethodCallCandidate instanceof ExtensionMethodNode)) {
+            typeCheckingContext.getEnclosingClassNode().putNodeMetaData(MINIMUM_BYTECODE_VERSION, Opcodes.V1_8);
+        }
+
         checkOrMarkPrivateAccess(call, directMethodCallCandidate);
         checkSuperCallFromClosure(call, directMethodCallCandidate);
         extension.onMethodSelection(call, directMethodCallCandidate);
diff --git a/subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579Bug.groovy b/subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579.groovy
similarity index 60%
rename from subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579Bug.groovy
rename to subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579.groovy
index 153f33f..8105cea 100644
--- a/subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579Bug.groovy
+++ b/subprojects/tests-vm8/src/test/groovy/groovy/bugs/vm8/Groovy8579.groovy
@@ -18,19 +18,35 @@
  */
 package groovy.bugs.vm8
 
-import groovy.test.GroovyTestCase
+import org.junit.Test
 
-class Groovy8579Bug extends GroovyTestCase {
-    void testCallToStaticInterfaceMethod() {
-        assertScript '''
-            import groovy.transform.CompileStatic
+import static groovy.test.GroovyAssert.assertScript
+
+final class Groovy8579 {
 
-            @CompileStatic
-            Comparator myMethod() {
+    @Test
+    void testCallToStaticInterfaceMethod1() {
+        assertScript '''
+            @groovy.transform.CompileStatic
+            Comparator test() {
                 Map.Entry.comparingByKey()
             }
 
-            assert myMethod() instanceof Comparator
+            assert test() instanceof Comparator
+        '''
+    }
+
+    @Test
+    void testCallToStaticInterfaceMethod2() {
+        assertScript '''
+            import static java.util.Map.Entry.comparingByKey
+
+            @groovy.transform.CompileStatic
+            Comparator test() {
+                comparingByKey()
+            }
+
+            assert test() instanceof Comparator
         '''
     }
 }


[groovy] 13/18: GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths

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 58d6ef487bc87e519472eeee7a4911467dcc1a20
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 11 15:02:53 2019 -0600

    GROOVY-8775, GROOVY-9197: Ant: separate JVM and compilation classpaths
    
    (cherry picked from commit c6e50bab27dc705116b93daccd62d53160c99938)
---
 src/test/groovy/bugs/Groovy9197.groovy             |  61 +++++++
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 190 ++++++++++++---------
 .../org/codehaus/groovy/ant/GroovycTest.xml        |  20 +++
 .../groovy/ant/MakesExternalReference.java         |  39 +++++
 .../org/codehaus/groovy/ant/commons-lang3-3.4.jar  | Bin 0 -> 434678 bytes
 .../org/codehaus/groovy/ant/GroovycTest.java       |   7 +
 6 files changed, 236 insertions(+), 81 deletions(-)

diff --git a/src/test/groovy/bugs/Groovy9197.groovy b/src/test/groovy/bugs/Groovy9197.groovy
new file mode 100644
index 0000000..f752f35
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy9197.groovy
@@ -0,0 +1,61 @@
+/*
+ *  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
+
+import static groovy.grape.Grape.resolve
+
+final class Groovy9197 {
+
+    @Test
+    void testJointCompilationClasspathPropagation() {
+        def uris = resolve(autoDownload:true, classLoader:new GroovyClassLoader(null),
+            [groupId:'org.apache.commons', artifactId:'commons-lang3', version:'3.9'])
+
+        def config = new CompilerConfiguration(
+            classpath: new File(uris[0]).path,
+            targetDirectory: File.createTempDir(),
+            jointCompilationOptions: [memStub: true]
+        )
+
+        def parentDir = File.createTempDir()
+        try {
+            def pojo = new File(parentDir, 'Pojo.java')
+            pojo.write '''
+                import static org.apache.commons.lang3.StringUtils.isEmpty;
+                public class Pojo {
+                    public static void main(String[] args) {
+                        assert !isEmpty(" ");
+                        assert isEmpty("");
+                    }
+                }
+            '''
+
+            def unit = new JavaAwareCompilationUnit(config)
+            unit.addSources(pojo)
+            unit.compile()
+        } finally {
+            parentDir.deleteDir()
+            config.targetDirectory.deleteDir()
+        }
+    }
+}
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index a72af08..ccc6efe 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -19,6 +19,7 @@
 package org.codehaus.groovy.ant;
 
 import groovy.lang.GroovyClassLoader;
+import org.antlr.v4.runtime.tree.ParseTreeVisitor;
 import org.apache.groovy.io.StringBuilderWriter;
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -31,6 +32,7 @@ import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
 import org.apache.tools.ant.util.GlobPatternMapper;
 import org.apache.tools.ant.util.SourceFileScanner;
+import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.SourceExtensionHandler;
@@ -38,8 +40,8 @@ import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 import org.codehaus.groovy.runtime.DefaultGroovyStaticMethods;
 import org.codehaus.groovy.tools.ErrorReporter;
 import org.codehaus.groovy.tools.FileSystemCompiler;
-import org.codehaus.groovy.tools.RootLoader;
 import org.codehaus.groovy.tools.javac.JavaAwareCompilationUnit;
+import org.objectweb.asm.ClassVisitor;
 import picocli.CommandLine;
 
 import java.io.File;
@@ -47,11 +49,13 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.Writer;
-import java.net.URL;
+import java.net.URI;
+import java.net.URISyntaxException;
 import java.nio.charset.Charset;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
@@ -67,17 +71,22 @@ import java.util.StringTokenizer;
  * <pre>
  * &lt;?xml version="1.0"?&gt;
  * &lt;project name="MyGroovyBuild" default="compile"&gt;
- *   &lt;property name="groovy.home" value="/Path/To/Groovy"/&gt;
+ *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
  *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
- *   &lt;path id="groovy.classpath"&gt;
- *     &lt;fileset dir="${groovy.home}/lib"&gt;
- *       &lt;include name="groovy-*${groovy.version}.jar" /&gt;
- *     &lt;/fileset&gt;
- *   &lt;/path&gt;
- *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/&gt;
+ *
+ *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
+ *     &lt;classpath&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
+ *     &lt;/classpath&gt;
+ *   &lt;/taskdef&gt;
  *
  *   &lt;target name="compile" description="compile groovy sources"&gt;
- *     &lt;groovyc srcdir="src" listfiles="true" classpathref="groovy.classpath"/&gt;
+ *     &lt;groovyc srcdir="src" destdir="bin" fork="true" listfiles="true" includeantruntime="false"/&gt;
+ *       &lt;classpath&gt;
+ *         &lt;fileset dir="${groovy.home}/lib" includes="groovy-*${groovy.version}.jar" excludes="groovy-ant-${groovy.version}.jar"/&gt;
+ *       &lt;/classpath&gt;
+ *     &lt;/groovyc&gt;
  *   &lt;/target&gt;
  * &lt;/project&gt;
  * </pre>
@@ -85,13 +94,13 @@ import java.util.StringTokenizer;
  * This task can take the following arguments:
  * <ul>
  * <li>srcdir</li>
- * <li>scriptExtension</li>
- * <li>targetBytecode</li>
  * <li>destdir</li>
  * <li>sourcepath</li>
  * <li>sourcepathRef</li>
  * <li>classpath</li>
  * <li>classpathRef</li>
+ * <li>scriptExtension</li>
+ * <li>targetBytecode</li>
  * <li>listfiles</li>
  * <li>failonerror</li>
  * <li>proceed</li>
@@ -123,39 +132,42 @@ import java.util.StringTokenizer;
  * </ul>
  * Of these arguments, the <b>srcdir</b> and <b>destdir</b> are required.
  * <p>
- * <p>When this task executes, it will recursively scan srcdir and destdir looking for Groovy source files
- * to compile. This task makes its compile decision based on timestamp.
+ * When this task executes, it will recursively scan srcdir and destdir looking
+ * for Groovy source files to compile. This task makes its compile decision based
+ * on timestamp.
  * <p>
  * A more elaborate build file showing joint compilation:
  * <pre>
  * &lt;?xml version="1.0"?&gt;
  * &lt;project name="MyJointBuild" default="compile"&gt;
- *   &lt;property name="groovy.home" value="/Path/To/Groovy"/&gt;
+ *   &lt;property name="groovy.home" location="/Path/To/Groovy"/&gt;
  *   &lt;property name="groovy.version" value="X.Y.Z"/&gt;
  *
- *   &lt;path id="groovy.classpath"&gt;
+ *   &lt;path id="classpath.main"&gt;
  *     &lt;fileset dir="${groovy.home}/lib"&gt;
- *       &lt;include name="groovy-*${groovy.version}.jar" /&gt;
+ *       &lt;include name="groovy-*${groovy.version}.jar"/&gt;
+ *       &lt;exclude name="groovy-ant-${groovy.version}.jar"/&gt;
  *     &lt;/fileset&gt;
  *   &lt;/path&gt;
  *
- *   &lt;target name="clean" description="remove all built files"&gt;
- *     &lt;delete dir="classes" /&gt;
- *   &lt;/target&gt;
+ *   &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc"&gt;
+ *     &lt;classpath&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-${groovy.version}.jar"/&gt;
+ *       &lt;fileset file="${groovy.home}/lib/groovy-ant-${groovy.version}.jar"/&gt;
+ *     &lt;/classpath&gt;
+ *   &lt;/taskdef&gt;
  *
- *   &lt;target name="compile" depends="init" description="compile java and groovy sources"&gt;
- *     &lt;mkdir dir="classes" /&gt;
- *     &lt;groovyc destdir="classes" srcdir="src" listfiles="true" keepStubs="true" stubdir="stubs"&gt;
- *       &lt;javac debug="on" deprecation="true"/&gt;
- *       &lt;classpath&gt;
- *         &lt;fileset dir="classes"/&gt;
- *         &lt;path refid="groovy.classpath"/&gt;
- *       &lt;/classpath&gt;
- *     &lt;/groovyc&gt;
+ *   &lt;target name="clean"&gt;
+ *     &lt;delete dir="bin" failonerror="false"/&gt;
  *   &lt;/target&gt;
  *
- *   &lt;target name="init"&gt;
- *     &lt;taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc" classpathref="groovy.classpath"/&gt;
+ *   &lt;target name="compile" depends="clean" description="compile java and groovy sources"&gt;
+ *     &lt;mkdir dir="bin"/&gt;
+ *
+ *     &lt;groovyc srcdir="src" destdir="bin" stubdir="stubs" keepStubs="true"
+ *      fork="true" includeantruntime="false" classpathref="classpath.main"&gt;
+ *       &lt;javac debug="true" source="1.8" target="1.8"/&gt;
+ *     &lt;/groovyc&gt;
  *   &lt;/target&gt;
  * &lt;/project&gt;
  * </pre>
@@ -165,7 +177,7 @@ import java.util.StringTokenizer;
  * Can also be used from {@link groovy.ant.AntBuilder} to allow the build file to be scripted in Groovy.
  */
 public class Groovyc extends MatchingTask {
-    private static final URL[] EMPTY_URL_ARRAY = new URL[0];
+
     private static final File[] EMPTY_FILE_ARRAY = new File[0];
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
 
@@ -176,20 +188,20 @@ public class Groovyc extends MatchingTask {
     private Path compileClasspath;
     private Path compileSourcepath;
     private String encoding;
-    private boolean stacktrace = false;
-    private boolean verbose = false;
+    private boolean stacktrace;
+    private boolean verbose;
     private boolean includeAntRuntime = true;
-    private boolean includeJavaRuntime = false;
-    private boolean fork = false;
+    private boolean includeJavaRuntime;
+    private boolean fork;
     private File forkJavaHome;
-    private String forkedExecutable = null;
+    private String forkedExecutable;
     private String memoryInitialSize;
     private String memoryMaximumSize;
     private String scriptExtension = "*.groovy";
-    private String targetBytecode = null;
+    private String targetBytecode;
 
     protected boolean failOnError = true;
-    protected boolean listFiles = false;
+    protected boolean listFiles;
     protected File[] compileList = EMPTY_FILE_ARRAY;
 
     private String updatedProperty;
@@ -214,12 +226,12 @@ public class Groovyc extends MatchingTask {
     /**
      * If true, generates metadata for reflection on method parameter names (jdk8+ only).  Defaults to false.
      */
-    private boolean parameters = false;
+    private boolean parameters;
 
     /**
      * If true, enable preview Java features (JEP 12) (jdk12+ only). Defaults to false.
      */
-    private boolean previewFeatures = false;
+    private boolean previewFeatures;
 
     /**
      * Adds a path for source compilation.
@@ -1071,13 +1083,6 @@ public class Groovyc extends MatchingTask {
     }
 
     private void doForkCommandLineList(List<String> commandLineList, Path classpath, String separator) {
-        if (includeAntRuntime) {
-            classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
-        }
-        if (includeJavaRuntime) {
-            classpath.addJavaRuntime();
-        }
-
         if (forkedExecutable != null && !forkedExecutable.isEmpty()) {
             commandLineList.add(forkedExecutable);
         } else {
@@ -1089,38 +1094,61 @@ public class Groovyc extends MatchingTask {
             }
             commandLineList.add(javaHome + separator + "bin" + separator + "java");
         }
-        commandLineList.add("-classpath");
-        commandLineList.add(getClasspathRelative(classpath));
 
-        String fileEncoding = System.getProperty("file.encoding");
-        if (fileEncoding != null && !fileEncoding.isEmpty()) {
-            commandLineList.add("-Dfile.encoding=" + fileEncoding);
+        String[] bootstrapClasspath;
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof AntClassLoader) {
+            bootstrapClasspath = ((AntClassLoader) loader).getClasspath().split(File.pathSeparator);
+        } else {
+            Class<?>[] bootstrapClasses = {
+                FileSystemCompilerFacade.class,
+                FileSystemCompiler.class,
+                ParseTreeVisitor.class,
+                ClassVisitor.class,
+                CommandLine.class,
+            };
+            bootstrapClasspath = Arrays.stream(bootstrapClasses).map(Groovyc::getLocation)
+                .map(uri -> new File(uri).getAbsolutePath()).distinct().toArray(String[]::new);
         }
-        if (targetBytecode != null) {
-            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+        if (bootstrapClasspath.length > 0) {
+            commandLineList.add("-classpath");
+            commandLineList.add(getClasspathRelative(bootstrapClasspath));
         }
+
         if (memoryInitialSize != null && !memoryInitialSize.isEmpty()) {
             commandLineList.add("-Xms" + memoryInitialSize);
         }
         if (memoryMaximumSize != null && !memoryMaximumSize.isEmpty()) {
             commandLineList.add("-Xmx" + memoryMaximumSize);
         }
+        if (targetBytecode != null) {
+            commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
+        }
         if (!"*.groovy".equals(getScriptExtension())) {
             String tmpExtension = getScriptExtension();
             if (tmpExtension.startsWith("*."))
                 tmpExtension = tmpExtension.substring(1);
             commandLineList.add("-Dgroovy.default.scriptExtension=" + tmpExtension);
         }
+
         commandLineList.add(FileSystemCompilerFacade.class.getName());
+        commandLineList.add("--classpath");
+        if (includeAntRuntime) {
+            classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
+        }
+        if (includeJavaRuntime) {
+            classpath.addJavaRuntime();
+        }
+        commandLineList.add(getClasspathRelative(classpath.list()));
         if (forceLookupUnnamedFiles) {
             commandLineList.add("--forceLookupUnnamedFiles");
         }
     }
 
-    private String getClasspathRelative(Path classpath) {
+    private String getClasspathRelative(String[] classpath) {
         String baseDir = getProject().getBaseDir().getAbsolutePath();
         StringBuilder sb = new StringBuilder();
-        for (String next : classpath.list()) {
+        for (String next : classpath) {
             if (sb.length() > 0) {
                 sb.append(File.pathSeparatorChar);
             }
@@ -1133,6 +1161,14 @@ public class Groovyc extends MatchingTask {
         return sb.toString();
     }
 
+    private static URI getLocation(Class<?> clazz) {
+        try {
+            return clazz.getProtectionDomain().getCodeSource().getLocation().toURI();
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     /**
      * Add "groovyc" parameters to the commandLineList, based on the ant configuration.
      *
@@ -1214,7 +1250,7 @@ public class Groovyc extends MatchingTask {
     }
 
     private String[] makeCommandLine(List<String> commandLineList) {
-        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
+        log.info("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
         return commandLineList.toArray(EMPTY_STRING_ARRAY);
     }
 
@@ -1302,10 +1338,9 @@ public class Groovyc extends MatchingTask {
 
             Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
             List<String> jointOptions = extractJointOptions(classpath);
-            String separator = System.getProperty("file.separator");
             List<String> commandLineList = new ArrayList<>();
 
-            if (fork) doForkCommandLineList(commandLineList, classpath, separator);
+            if (fork) doForkCommandLineList(commandLineList, classpath, File.separator);
             doNormalCommandLineList(commandLineList, jointOptions, classpath);
             addSourceFiles(commandLineList);
 
@@ -1359,23 +1394,17 @@ public class Groovyc extends MatchingTask {
     }
 
     protected GroovyClassLoader buildClassLoaderFor() {
+        if (fork) {
+            throw new GroovyBugError("Cannot use Groovyc#buildClassLoaderFor() for forked compilation");
+        }
         // GROOVY-5044
-        if (!fork && !getIncludeantruntime()) {
+        if (!getIncludeantruntime()) {
             throw new IllegalArgumentException("The includeAntRuntime=false option is not compatible with fork=false");
         }
 
-        ClassLoader parent =
-                AccessController.doPrivileged(
-                        new PrivilegedAction<ClassLoader>() {
-                            @Override
-                            public ClassLoader run() {
-                                return getIncludeantruntime()
-                                        ? getClass().getClassLoader()
-                                        : new AntClassLoader(new RootLoader(EMPTY_URL_ARRAY, null), getProject(), getClasspath());
-                            }
-                        });
-        if (parent instanceof AntClassLoader) {
-            AntClassLoader antLoader = (AntClassLoader) parent;
+        ClassLoader loader = getClass().getClassLoader();
+        if (loader instanceof AntClassLoader) {
+            AntClassLoader antLoader = (AntClassLoader) loader;
             String[] pathElm = antLoader.getClasspath().split(File.pathSeparator);
             List<String> classpath = configuration.getClasspath();
             /*
@@ -1406,13 +1435,13 @@ public class Groovyc extends MatchingTask {
             }
         }
 
-        GroovyClassLoader loader = AccessController.doPrivileged(
-                (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(parent, configuration));
+        GroovyClassLoader groovyLoader = AccessController.doPrivileged(
+                (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(loader, configuration));
         if (!forceLookupUnnamedFiles) {
             // in normal case we don't need to do script lookups
-            loader.setResourceLoader(filename -> null);
+            groovyLoader.setResourceLoader(filename -> null);
         }
-        return loader;
+        return groovyLoader;
     }
 
     private Set<String> getScriptExtensions() {
@@ -1423,11 +1452,10 @@ public class Groovyc extends MatchingTask {
         if (scriptExtensions.isEmpty()) {
             scriptExtensions.add(getScriptExtension().substring(2)); // first extension will be the one set explicitly on <groovyc>
 
-            Path classpath = getClasspath() != null ? getClasspath() : new Path(getProject());
-            final String[] pe = classpath.list();
+            Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
             try (GroovyClassLoader loader = new GroovyClassLoader(getClass().getClassLoader())) {
-                for (String file : pe) {
-                    loader.addClasspath(file);
+                for (String element : classpath.list()) {
+                    loader.addClasspath(element);
                 }
                 scriptExtensions.addAll(SourceExtensionHandler.getRegisteredExtensions(loader));
             } catch (IOException e) {
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
index d4fb8d2..73bb824 100644
--- a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
@@ -187,6 +187,26 @@
         <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy" fork="false" includeAntRuntime="false"/>
     </target>
 
+    <!-- GROOVY-9197 -->
+    <target name="jointForkedCompilation_ExternalJarOnClasspath">
+        <presetdef name="compile">
+            <groovyc fork="true" includeantruntime="false">
+                <javac debug="true" source="${javaVersion}" target="${javaVersion}"/>
+            </groovyc>
+        </presetdef>
+
+        <path id="the.classpath">
+            <path refid="groovyMaterials"/>
+            <fileset file="commons-lang3-3.4.jar"/>
+        </path>
+
+        <compile srcdir="${srcPath}" destdir="${destPath}" includes="MakesExternalReference.java">
+            <classpath refid="the.classpath"/>
+        </compile>
+
+        <java classname="org.codehaus.groovy.ant.MakesExternalReference" classpathref="the.classpath"/>
+    </target>
+
     <target name="clean">
         <delete quiet="true">
             <fileset dir="${destPath}/org/codehaus/groovy/ant">
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java
new file mode 100644
index 0000000..e5d2c73
--- /dev/null
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/MakesExternalReference.java
@@ -0,0 +1,39 @@
+/*
+ *  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 org.codehaus.groovy.ant;
+
+import java.io.*;
+
+import static org.apache.commons.lang3.StringUtils.isEmpty;
+
+public class MakesExternalReference {
+    public static void main(String[] args) throws IOException {
+        FileOutputStream fout = new FileOutputStream(
+            new File("target/classes/groovy/test/org/codehaus/groovy/ant/MakesExternalReference_Result.txt"));
+        try {
+            assert !isEmpty(" ");
+            fout.write("OK.".getBytes());
+        } finally {
+            try {
+                fout.close();
+            } catch (IOException ignore) {
+            }
+        }
+    }
+}
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar
new file mode 100644
index 0000000..8ec91d4
Binary files /dev/null and b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/commons-lang3-3.4.jar differ
diff --git a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
index cb60c5d..cec5dd6 100644
--- a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
+++ b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
@@ -252,6 +252,13 @@ public class GroovycTest extends GroovyTestCase {
         ensureFails("noForkNoAntRuntime");
     }
 
+    // GROOVY-9197
+    public void testJointCompilationPropagatesClasspath() {
+        ensureNotPresent("MakesExternalReference");
+        project.executeTarget("jointForkedCompilation_ExternalJarOnClasspath");
+        ensureResultOK("MakesExternalReference");
+    }
+
     private void ensureExecutes(String target) {
         ensureNotPresent("GroovycTest1");
         project.executeTarget(target);


[groovy] 10/18: Trivial refactoring: Remove redundant `if` 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 2deb4260875acca7815cd64296f6fbe3b658d73f
Author: Daniel.Sun <re...@hotmail.com>
AuthorDate: Fri Nov 15 16:13:43 2019 +0800

    Trivial refactoring: Remove redundant `if` statement
    
    (cherry picked from commit 1cd9c49e2a62b89a08f150c46cc3ceeb22153f25)
---
 .../org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java   | 3 +--
 1 file changed, 1 insertion(+), 2 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 e29b5c4..0725829 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -427,8 +427,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected boolean shouldSkipClassNode(final ClassNode node) {
-        if (isSkipMode(node)) return true;
-        return false;
+        return isSkipMode(node);
     }
 
     /**


[groovy] 17/18: Improve the robustness of closing resources

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 9f9ea84aa24e5b7381fd482a0d6855d1339c04e4
Author: Daniel Sun <su...@apache.org>
AuthorDate: Sun Nov 17 15:24:03 2019 +0800

    Improve the robustness of closing resources
    
    (cherry picked from commit 148d14fb9c5642fe9a30d16630766470033d702c)
---
 src/main/java/groovy/lang/GroovyClassLoader.java | 7 +++++--
 1 file changed, 5 insertions(+), 2 deletions(-)

diff --git a/src/main/java/groovy/lang/GroovyClassLoader.java b/src/main/java/groovy/lang/GroovyClassLoader.java
index afc52ff..cd44d74 100644
--- a/src/main/java/groovy/lang/GroovyClassLoader.java
+++ b/src/main/java/groovy/lang/GroovyClassLoader.java
@@ -630,8 +630,11 @@ public class GroovyClassLoader extends URLClassLoader {
 
         @Override
         public void close() throws IOException {
-            super.close();
-            delegate.close();
+            try {
+                super.close();
+            } finally {
+                delegate.close();
+            }
         }
 
         public long getTimeStamp() {


[groovy] 01/18: GROOVY-9307: Bump javaparser to 3.15.5 (#1079)

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 32f6b78f25a9dbf1519fc5870eb38354804f2257
Author: Daniel.Sun <su...@apache.org>
AuthorDate: Mon Nov 11 20:04:46 2019 +0800

    GROOVY-9307: Bump javaparser to 3.15.5 (#1079)
    
    (cherry picked from commit fd5794f9c8e8faa1c00a96f8f035d60b4b99e14b)
---
 build.gradle | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/build.gradle b/build.gradle
index 7299e39..67bd25a 100644
--- a/build.gradle
+++ b/build.gradle
@@ -141,7 +141,7 @@ ext {
     ivyVersion = '2.5.0'
     jansiVersion = '1.18'
     jarjarVersion = '1.7.2'
-    javaParserVersion = '3.15.4'
+    javaParserVersion = '3.15.5'
     jlineVersion = '2.14.6'
     jmockVersion = '1.2.0'
     logbackVersion = '1.1.7'


[groovy] 11/18: Ant: add support for more joint compilation options

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 816195b2f90a7860a5ba7877a5c45262449caba7
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Wed Nov 13 13:58:02 2019 -0600

    Ant: add support for more joint compilation options
    
    <groovyc>
      <javac _attribute_ />
    </groovyc>
    - bootclasspath
    - bootclasspathref
    - deprecation
    - modulepath
    - modulepathref
    - modulesourcepath
    - modulesourcepathref
    - nativeheaderdir
    - nowarn
    - release
    - upgrademodulepath
    - upgrademodulepathref
    
    <groovyc>
      <javac>
        <compilerarg value="-proc:_option_" />
      </javac>
    </groovyc>
    
    <groovyc previewFeatures="true">
      <javac><!-- receives "--enable-preview" argument -->
    </groovyc>
    
    (cherry picked from commit 15dc98c9a499231931a8b98f5031569adb6a0b89)
---
 .../codehaus/groovy/tools/FileSystemCompiler.java  | 53 ++++++++++---------
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 59 ++++++++++++++++------
 2 files changed, 71 insertions(+), 41 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java b/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
index 39e103f..8b16882 100644
--- a/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
+++ b/src/main/java/org/codehaus/groovy/tools/FileSystemCompiler.java
@@ -84,7 +84,7 @@ public class FileSystemCompiler {
      *
      * @since 2.5
      */
-    public static void displayHelp(final PrintWriter writer) {
+    public static void displayHelp(PrintWriter writer) {
         configureParser(new CompilationOptions()).usage(writer);
     }
 
@@ -102,7 +102,7 @@ public class FileSystemCompiler {
      *
      * @since 2.5
      */
-    public static void displayVersion(final PrintWriter writer) {
+    public static void displayVersion(PrintWriter writer) {
         for (String line : new VersionProvider().getVersion()) {
             writer.println(line);
         }
@@ -115,10 +115,10 @@ public class FileSystemCompiler {
             File file = new File(filename);
             if (!file.exists()) {
                 System.err.println("error: file not found: " + file);
-                ++errors;
+                errors += 1;
             } else if (!file.canRead()) {
                 System.err.println("error: file not readable: " + file);
-                ++errors;
+                errors += 1;
             }
         }
 
@@ -419,15 +419,15 @@ public class FileSystemCompiler {
 
             // joint compilation parameters
             if (jointCompilation) {
-                Map<String, Object> compilerOptions = new HashMap<String, Object>();
-                compilerOptions.put("namedValues", javacOptionsList());
-                compilerOptions.put("flags", flagsWithParameterMetaData());
+                Map<String, Object> compilerOptions = new HashMap<>();
+                compilerOptions.put("flags", javacFlags());
+                compilerOptions.put("namedValues", javacNamedValues());
                 configuration.setJointCompilationOptions(compilerOptions);
             }
 
             if (indy) {
-                configuration.getOptimizationOptions().put("int", false);
-                configuration.getOptimizationOptions().put("indy", true);
+                configuration.getOptimizationOptions().put("int", Boolean.FALSE);
+                configuration.getOptimizationOptions().put("indy", Boolean.TRUE);
             }
 
             final List<String> transformations = new ArrayList<>();
@@ -443,12 +443,12 @@ public class FileSystemCompiler {
 
             String configScripts = System.getProperty("groovy.starter.configscripts", null);
             if (configScript != null || (configScripts != null && !configScripts.isEmpty())) {
-                List<String> scripts = new ArrayList<String>();
+                List<String> scripts = new ArrayList<>();
                 if (configScript != null) {
                     scripts.add(configScript);
                 }
                 if (configScripts != null) {
-                    scripts.addAll(StringGroovyMethods.tokenize((CharSequence) configScripts, ','));
+                    scripts.addAll(StringGroovyMethods.tokenize(configScripts, ','));
                 }
                 processConfigScripts(scripts, configuration);
             }
@@ -460,26 +460,29 @@ public class FileSystemCompiler {
             return generateFileNamesFromOptions(files);
         }
 
-        String[] javacOptionsList() {
-            if (javacOptionsMap == null) {
-                return null;
-            }
-            List<String> result = new ArrayList<String>();
-            for (Map.Entry<String, String> entry : javacOptionsMap.entrySet()) {
-                result.add(entry.getKey());
-                result.add(entry.getValue());
+        private String[] javacNamedValues() {
+            List<String> result = new ArrayList<>();
+            if (javacOptionsMap != null) {
+                for (Map.Entry<String, String> entry : javacOptionsMap.entrySet()) {
+                    result.add(entry.getKey());
+                    result.add(entry.getValue());
+                }
             }
-            return result.toArray(new String[0]);
+            return result.isEmpty() ? null : result.toArray(new String[0]);
         }
 
-        String[] flagsWithParameterMetaData() {
-            if (flags == null) {
-                return null;
+        private String[] javacFlags() {
+            List<String> result = new ArrayList<>();
+            if (flags != null) {
+                result.addAll(flags);
             }
             if (parameterMetadata) {
-                flags.add("parameters");
+                result.add("parameters");
+            }
+            if (previewFeatures) {
+                result.add("-enable-preview");
             }
-            return flags.toArray(new String[0]);
+            return result.isEmpty() ? null : result.toArray(new String[0]);
         }
     }
 }
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index a255703..a72af08 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -988,6 +988,16 @@ public class Groovyc extends MatchingTask {
             jointOptions.add("-Fg:none");
         }
 
+        // map "deprecation" to "-Fdeprecation"
+        if (javac.getDeprecation()) {
+            jointOptions.add("-Fdeprecation");
+        }
+
+        // map "nowarn" to "-Fnowarn"
+        if (javac.getNowarn()) {
+            jointOptions.add("-Fnowarn");
+        }
+
         // map "verbose" to "-Fverbose"
         if (javac.getVerbose()) {
             jointOptions.add("-Fverbose");
@@ -997,25 +1007,45 @@ public class Groovyc extends MatchingTask {
 
         for (Map.Entry<String, Object> e : rc.getAttributeMap().entrySet()) {
             String key = e.getKey();
-            if (key.contains("encoding")
-                    || key.contains("extdirs")
-                    || key.contains("depend")
-                    || key.contains("source")
-                    || key.contains("target")) {
-                // map "encoding", etc. to "-Jkey=val"
+            if (key.equals("depend")
+                    || key.equals("encoding")
+                    || key.equals("extdirs")
+                    || key.equals("nativeheaderdir")
+                    || key.equals("release")
+                    || key.equals("source")
+                    || key.equals("target")) {
+                switch (key) {
+                case "nativeheaderdir":
+                    key = "h"; break;
+                case "release":
+                    key = "-" + key; // to get "--" when passed to javac
+                }
+                // map "depend", "encoding", etc. to "-Jkey=val"
                 jointOptions.add("-J" + key + "=" + getProject().replaceProperties(e.getValue().toString()));
 
             } else if (key.contains("classpath")) {
                 if (key.startsWith("boot")) {
-                    // TODO: javac.getBootclasspath()
+                    // map "bootclasspath" or "bootclasspathref" to "-Jbootclasspath="
+                    jointOptions.add("-Jbootclasspath=" + javac.getBootclasspath());
                 } else {
+                    // map "classpath" or "classpathref" to "--classpath"
                     classpath.add(javac.getClasspath());
                 }
-            } else if (!key.contains("debug") && !key.contains("verbose")) {
+            } else if (key.contains("module") && key.contains("path")) {
+                if (key.startsWith("upgrade")) {
+                    // map "upgrademodulepath" or "upgrademodulepathref" to "-J-upgrade-module-path="
+                    jointOptions.add("-J-upgrade-module-path=" + javac.getUpgrademodulepath());
+                } else if (key.contains("source")) {
+                    // map "modulesourcepath" or "modulesourcepathref" to "-J-module-source-path="
+                    jointOptions.add("-J-module-source-path=" + javac.getModulesourcepath());
+                } else {
+                    // map "modulepath" or "modulepathref" to "-J-module-path="
+                    jointOptions.add("-J-module-path=" + javac.getModulepath());
+                }
+            } else if (!key.contains("debug") && !key.equals("deprecation") && !key.equals("nowarn") && !key.equals("verbose")) {
                 log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored.");
             }
-            // TODO: modulepath, modulepathref, modulesourcepath, modulesourcepathref, upgrademodulepath, upgrademodulepathref
-            // TODO: release, deprecation, failonerror, nowarn, tempdir, nativeheaderdir, includes(file)? excludes(file)?
+            // TODO: defaultexcludes, excludes(file)?, includes(file)?, includeDestClasses, tempdir
         }
 
         // Ant's <javac> supports nested <compilerarg value=""> elements (there
@@ -1028,12 +1058,9 @@ public class Groovyc extends MatchingTask {
                         String value = getProject().replaceProperties(e.getValue().toString());
                         StringTokenizer st = new StringTokenizer(value, " ");
                         while (st.hasMoreTokens()) {
-                            String optionStr = st.nextToken();
-                            String replaced = optionStr.replace("-X", "-FX");
-                            if (optionStr.equals(replaced)) {
-                                replaced = optionStr.replace("-W", "-FW"); // GROOVY-5063
-                            }
-                            jointOptions.add(replaced);
+                            String option = st.nextToken();
+                            // GROOVY-5063: map "-Werror", etc. to "-FWerror"
+                            jointOptions.add(option.replaceFirst("^-(W|X|proc:)", "-F$1"));
                         }
                     }
                 }


[groovy] 04/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 bc6ee3b67ece69c091c8e557c9b8898874868546
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 14 12:41:43 2019 -0600

    minor edits
    
    (cherry picked from commit f22d47964cceca8d30dbda178768c7cfcd37844c)
---
 .../transform/stc/StaticTypeCheckingSupport.java   | 179 ++++++++-----------
 .../transform/stc/StaticTypeCheckingVisitor.java   | 189 ++++++++++-----------
 .../groovy/classgen/asm/sc/bugs/Groovy7276.groovy  |  20 ++-
 3 files changed, 171 insertions(+), 217 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
index f27988a..10de207 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingSupport.java
@@ -16,9 +16,9 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-
 package org.codehaus.groovy.transform.stc;
 
+import org.apache.groovy.util.Maps;
 import org.codehaus.groovy.GroovyBugError;
 import org.codehaus.groovy.ast.ClassHelper;
 import org.codehaus.groovy.ast.ClassNode;
@@ -45,6 +45,7 @@ import org.codehaus.groovy.control.CompilationUnit;
 import org.codehaus.groovy.control.CompilerConfiguration;
 import org.codehaus.groovy.control.Phases;
 import org.codehaus.groovy.runtime.metaclass.MetaClassRegistryImpl;
+import org.codehaus.groovy.syntax.Types;
 import org.codehaus.groovy.tools.GroovyClass;
 import org.codehaus.groovy.transform.trait.Traits;
 import org.objectweb.asm.Opcodes;
@@ -61,7 +62,6 @@ import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
-import java.util.Map.Entry;
 import java.util.Optional;
 import java.util.Set;
 import java.util.TreeSet;
@@ -107,7 +107,6 @@ import static org.codehaus.groovy.ast.ClassHelper.short_TYPE;
 import static org.codehaus.groovy.ast.ClassHelper.void_WRAPPER_TYPE;
 import static org.codehaus.groovy.ast.tools.GenericsUtils.getSuperClass;
 import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
-import static org.codehaus.groovy.syntax.Types.ASSIGN;
 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;
@@ -135,9 +134,7 @@ 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.LEFT_SQUARE_BRACKET;
 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.MATCH_REGEX;
 import static org.codehaus.groovy.syntax.Types.MINUS;
 import static org.codehaus.groovy.syntax.Types.MINUS_EQUAL;
@@ -153,55 +150,46 @@ 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;
+
 /**
  * Static support methods for {@link StaticTypeCheckingVisitor}.
  */
 public abstract class StaticTypeCheckingSupport {
-    protected static final ClassNode
-            Collection_TYPE = makeWithoutCaching(Collection.class);
-    protected static final ClassNode Deprecated_TYPE = makeWithoutCaching(Deprecated.class);
     protected static final ClassNode Matcher_TYPE = makeWithoutCaching(Matcher.class);
     protected static final ClassNode ArrayList_TYPE = makeWithoutCaching(ArrayList.class);
-    protected static final AbstractExtensionMethodCache EXTENSION_METHOD_CACHE = ExtensionMethodCache.INSTANCE;
-    protected static final Map<ClassNode, Integer> NUMBER_TYPES = Collections.unmodifiableMap(
-            new HashMap<ClassNode, Integer>() {
-                private static final long serialVersionUID = 8841951852732042766L;
-
-                {
-                    put(byte_TYPE, 0);
-                    put(Byte_TYPE, 0);
-                    put(short_TYPE, 1);
-                    put(Short_TYPE, 1);
-                    put(int_TYPE, 2);
-                    put(Integer_TYPE, 2);
-                    put(Long_TYPE, 3);
-                    put(long_TYPE, 3);
-                    put(float_TYPE, 4);
-                    put(Float_TYPE, 4);
-                    put(double_TYPE, 5);
-                    put(Double_TYPE, 5);
-                }
-            });
-
-    protected static final Map<String, Integer> NUMBER_OPS = Collections.unmodifiableMap(
-            new HashMap<String, Integer>() {
-                private static final long serialVersionUID = 6951856193525808411L;
-
-                {
-                    put("plus", PLUS);
-                    put("minus", MINUS);
-                    put("multiply", MULTIPLY);
-                    put("div", DIVIDE);
-                    put("or", BITWISE_OR);
-                    put("and", BITWISE_AND);
-                    put("xor", BITWISE_XOR);
-                    put("mod", MOD);
-                    put("intdiv", INTDIV);
-                    put("leftShift", LEFT_SHIFT);
-                    put("rightShift", RIGHT_SHIFT);
-                    put("rightShiftUnsigned", RIGHT_SHIFT_UNSIGNED);
-                }
-            });
+    protected static final ClassNode Collection_TYPE = makeWithoutCaching(Collection.class);
+    protected static final ClassNode Deprecated_TYPE = makeWithoutCaching(Deprecated.class);
+    protected static final ExtensionMethodCache EXTENSION_METHOD_CACHE = ExtensionMethodCache.INSTANCE;
+
+    protected static final Map<ClassNode, Integer> NUMBER_TYPES = Maps.of(
+            byte_TYPE, 0,
+            Byte_TYPE, 0,
+            short_TYPE, 1,
+            Short_TYPE, 1,
+            int_TYPE, 2,
+            Integer_TYPE, 2,
+            Long_TYPE, 3,
+            long_TYPE, 3,
+            float_TYPE, 4,
+            Float_TYPE, 4,
+            double_TYPE, 5,
+            Double_TYPE, 5
+    );
+
+    protected static final Map<String, Integer> NUMBER_OPS = Maps.of(
+            "plus", PLUS,
+            "minus", MINUS,
+            "multiply", MULTIPLY,
+            "div", DIVIDE,
+            "or", BITWISE_OR,
+            "and", BITWISE_AND,
+            "xor", BITWISE_XOR,
+            "mod", MOD,
+            "intdiv", INTDIV,
+            "leftShift", LEFT_SHIFT,
+            "rightShift", RIGHT_SHIFT,
+            "rightShiftUnsigned", RIGHT_SHIFT_UNSIGNED
+    );
 
     protected static final ClassNode GSTRING_STRING_CLASSNODE = WideningCategories.lowestUpperBound(
             STRING_TYPE,
@@ -298,12 +286,11 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     public static Set<MethodNode> findDGMMethodsForClassNode(final ClassLoader loader, ClassNode clazz, String name) {
-        TreeSet<MethodNode> accumulator = new TreeSet<MethodNode>(DGM_METHOD_NODE_COMPARATOR);
+        TreeSet<MethodNode> accumulator = new TreeSet<>(DGM_METHOD_NODE_COMPARATOR);
         findDGMMethodsForClassNode(loader, clazz, name, accumulator);
         return accumulator;
     }
 
-
     /**
      * @deprecated Use {@link #findDGMMethodsForClassNode(ClassLoader, ClassNode, String, TreeSet)} instead
      */
@@ -633,27 +620,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     public static boolean isAssignment(int op) {
-        switch (op) {
-            case ASSIGN:
-            case LOGICAL_OR_EQUAL:
-            case LOGICAL_AND_EQUAL:
-            case PLUS_EQUAL:
-            case MINUS_EQUAL:
-            case MULTIPLY_EQUAL:
-            case DIVIDE_EQUAL:
-            case INTDIV_EQUAL:
-            case MOD_EQUAL:
-            case POWER_EQUAL:
-            case LEFT_SHIFT_EQUAL:
-            case RIGHT_SHIFT_EQUAL:
-            case RIGHT_SHIFT_UNSIGNED_EQUAL:
-            case BITWISE_OR_EQUAL:
-            case BITWISE_AND_EQUAL:
-            case BITWISE_XOR_EQUAL:
-                return true;
-            default:
-                return false;
-        }
+        return Types.isAssignment(op);
     }
 
     /**
@@ -978,7 +945,7 @@ public abstract class StaticTypeCheckingSupport {
         if (c.equals(interfaceClass)) return 0;
         ClassNode[] interfaces = c.getInterfaces();
         int max = -1;
-        for (final ClassNode anInterface : interfaces) {
+        for (ClassNode anInterface : interfaces) {
             int sub = getMaximumInterfaceDistance(anInterface, interfaceClass);
             // we need to keep the -1 to track the mismatch, a +1
             // by any means could let it look like a direct match
@@ -1004,7 +971,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     public static List<MethodNode> findDGMMethodsByNameAndArguments(final ClassLoader loader, final ClassNode receiver, final String name, final ClassNode[] args) {
-        return findDGMMethodsByNameAndArguments(loader, receiver, name, args, new LinkedList<MethodNode>());
+        return findDGMMethodsByNameAndArguments(loader, receiver, name, args, new LinkedList<>());
     }
 
     /**
@@ -1068,7 +1035,7 @@ public abstract class StaticTypeCheckingSupport {
             ClassNode raw = makeRawType(receiver);
             return chooseBestMethod(raw, methods, args);
         }
-        List<MethodNode> bestChoices = new LinkedList<MethodNode>();
+        List<MethodNode> bestChoices = new LinkedList<>();
         int bestDist = Integer.MAX_VALUE;
         Collection<MethodNode> choicesLeft = removeCovariantsAndInterfaceEquivalents(methods);
         for (MethodNode candidateNode : choicesLeft) {
@@ -1112,7 +1079,7 @@ public abstract class StaticTypeCheckingSupport {
         }
         if (bestChoices.size() > 1) {
             // GROOVY-6849: prefer extension methods in case of ambiguity
-            List<MethodNode> onlyExtensionMethods = new LinkedList<MethodNode>();
+            List<MethodNode> onlyExtensionMethods = new LinkedList<>();
             for (MethodNode choice : bestChoices) {
                 if (choice instanceof ExtensionMethodNode) {
                     onlyExtensionMethods.add(choice);
@@ -1190,7 +1157,7 @@ public abstract class StaticTypeCheckingSupport {
         return Arrays.stream(params).map(param -> {
             String name = param.getType().getUnresolvedName();
             Optional<GenericsType> value = genericsPlaceholderAndTypeMap.entrySet().stream()
-                .filter(e -> e.getKey().getName().equals(name)).findFirst().map(Entry::getValue);
+                .filter(e -> e.getKey().getName().equals(name)).findFirst().map(Map.Entry::getValue);
             ClassNode type = value.map(GenericsType::getType).orElseGet(() -> makeRawType(param.getType()));
 
             return new Parameter(type, param.getName());
@@ -1209,8 +1176,8 @@ public abstract class StaticTypeCheckingSupport {
 
     private static Collection<MethodNode> removeCovariantsAndInterfaceEquivalents(Collection<MethodNode> collection) {
         if (collection.size() <= 1) return collection;
-        List<MethodNode> toBeRemoved = new LinkedList<MethodNode>();
-        List<MethodNode> list = new LinkedList<MethodNode>(new LinkedHashSet<MethodNode>(collection));
+        List<MethodNode> toBeRemoved = new LinkedList<>();
+        List<MethodNode> list = new LinkedList<>(new LinkedHashSet<>(collection));
         for (int i = 0; i < list.size() - 1; i++) {
             MethodNode one = list.get(i);
             if (toBeRemoved.contains(one)) continue;
@@ -1235,7 +1202,7 @@ public abstract class StaticTypeCheckingSupport {
             }
         }
         if (toBeRemoved.isEmpty()) return list;
-        List<MethodNode> result = new LinkedList<MethodNode>(list);
+        List<MethodNode> result = new LinkedList<>(list);
         result.removeAll(toBeRemoved);
         return result;
     }
@@ -1479,7 +1446,7 @@ public abstract class StaticTypeCheckingSupport {
         boolean failure = false;
 
         // correct receiver for inner class
-        // we assume the receiver is an instance of the declaring class of the 
+        // we assume the receiver is an instance of the declaring class of the
         // candidate method, but findMethod returns also outer class methods
         // for that receiver. For now we skip receiver based checks in that case
         // TODO: correct generics for when receiver is to be skipped
@@ -1488,7 +1455,7 @@ public abstract class StaticTypeCheckingSupport {
         Parameter[] parameters = candidateMethod.getParameters();
         Map<GenericsTypeName, GenericsType> classGTs;
         if (skipBecauseOfInnerClassNotReceiver) {
-            classGTs = Collections.EMPTY_MAP;
+            classGTs = Collections.emptyMap();
         } else {
             classGTs = GenericsUtils.extractPlaceholders(receiver);
         }
@@ -1500,7 +1467,7 @@ public abstract class StaticTypeCheckingSupport {
 
         // we have here different generics contexts we have to deal with.
         // There is firstly the context given through the class, and the method.
-        // The method context may hide generics given through the class, but use 
+        // The method context may hide generics given through the class, but use
         // the non-hidden ones.
         Map<GenericsTypeName, GenericsType> resolvedMethodGenerics = new HashMap<GenericsTypeName, GenericsType>();
         if (!skipBecauseOfInnerClassNotReceiver) {
@@ -1512,13 +1479,13 @@ public abstract class StaticTypeCheckingSupport {
         applyGenericsConnections(classGTs, resolvedMethodGenerics);
         // and then start our checks with the receiver
         if (!skipBecauseOfInnerClassNotReceiver) {
-            failure |= inferenceCheck(Collections.EMPTY_SET, resolvedMethodGenerics, candidateMethod.getDeclaringClass(), receiver, false);
+            failure |= inferenceCheck(Collections.emptySet(), resolvedMethodGenerics, candidateMethod.getDeclaringClass(), receiver, false);
         }
         // the outside context parts till now define placeholder we are not allowed to
         // generalize, thus we save that for later use...
-        // extension methods are special, since they set the receiver as 
+        // extension methods are special, since they set the receiver as
         // first parameter. While we normally allow generalization for the first
-        // parameter, in case of an extension method we must not. 
+        // parameter, in case of an extension method we must not.
         Set<GenericsTypeName> fixedGenericsPlaceHolders = extractResolvedPlaceHolders(resolvedMethodGenerics);
 
         for (int i = 0; i < arguments.length; i++) {
@@ -1541,9 +1508,9 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static Set<GenericsTypeName> extractResolvedPlaceHolders(Map<GenericsTypeName, GenericsType> resolvedMethodGenerics) {
-        if (resolvedMethodGenerics.isEmpty()) return Collections.EMPTY_SET;
-        Set<GenericsTypeName> result = new HashSet<GenericsTypeName>();
-        for (Entry<GenericsTypeName, GenericsType> entry : resolvedMethodGenerics.entrySet()) {
+        if (resolvedMethodGenerics.isEmpty()) return Collections.emptySet();
+        Set<GenericsTypeName> result = new HashSet<>();
+        for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedMethodGenerics.entrySet()) {
             GenericsType value = entry.getValue();
             if (value.isPlaceholder()) continue;
             result.add(entry.getKey());
@@ -1552,7 +1519,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static boolean inferenceCheck(Set<GenericsTypeName> fixedGenericsPlaceHolders, Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, ClassNode type, ClassNode wrappedArgument, boolean lastArg) {
-        Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>();
+        Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         if (isPrimitiveType(wrappedArgument)) wrappedArgument = getWrapper(wrappedArgument);
 
         if (lastArg &&
@@ -1573,7 +1540,7 @@ public abstract class StaticTypeCheckingSupport {
         // information. This way the method level information slowly turns
         // into information for the callsite
         applyGenericsConnections(connections, resolvedMethodGenerics);
-        // since it is possible that the callsite uses some generics as well, 
+        // since it is possible that the callsite uses some generics as well,
         // we may have to add additional elements here
         addMissingEntries(connections, resolvedMethodGenerics);
         // to finally see if the parameter and the argument fit together,
@@ -1597,7 +1564,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static boolean compatibleConnections(Map<GenericsTypeName, GenericsType> connections, Map<GenericsTypeName, GenericsType> resolvedMethodGenerics, Set<GenericsTypeName> fixedGenericsPlaceHolders) {
-        for (Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
+        for (Map.Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
             GenericsType resolved = resolvedMethodGenerics.get(entry.getKey());
             if (resolved == null) continue;
             GenericsType connection = entry.getValue();
@@ -1644,7 +1611,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static void addMissingEntries(Map<GenericsTypeName, GenericsType> connections, Map<GenericsTypeName, GenericsType> resolved) {
-        for (Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
+        for (Map.Entry<GenericsTypeName, GenericsType> entry : connections.entrySet()) {
             if (resolved.containsKey(entry.getKey())) continue;
             GenericsType gt = entry.getValue();
             ClassNode cn = gt.getType();
@@ -1655,10 +1622,10 @@ public abstract class StaticTypeCheckingSupport {
 
     public static ClassNode resolveClassNodeGenerics(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, final Map<GenericsTypeName, GenericsType> placeholdersFromContext, ClassNode currentType) {
         ClassNode target = currentType.redirect();
-        resolvedPlaceholders = new HashMap<GenericsTypeName, GenericsType>(resolvedPlaceholders);
+        resolvedPlaceholders = new HashMap<>(resolvedPlaceholders);
         applyContextGenerics(resolvedPlaceholders, placeholdersFromContext);
 
-        Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>();
+        Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         extractGenericsConnections(connections, currentType, target);
         applyGenericsConnections(connections, resolvedPlaceholders);
         currentType = applyGenericsContext(resolvedPlaceholders, currentType);
@@ -1672,9 +1639,9 @@ public abstract class StaticTypeCheckingSupport {
         if (connections == null) return;
         int count = 0;
         while (count < 10000) {
-            count++;
+            count += 1;
             boolean checkForMorePlaceHolders = false;
-            for (Entry<GenericsTypeName, GenericsType> entry : resolvedPlaceholders.entrySet()) {
+            for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedPlaceholders.entrySet()) {
                 GenericsTypeName name = entry.getKey();
                 GenericsType replacement = connections.get(name);
                 if (replacement == null) {
@@ -1800,7 +1767,7 @@ public abstract class StaticTypeCheckingSupport {
                 ClassNode corrected = getCorrectedClassNode(type, superClass, true);
                 extractGenericsConnections(connections, corrected, target);
             } else {
-                // if we reach here, we have an unhandled case 
+                // if we reach here, we have an unhandled case
                 throw new GroovyBugError("The type " + type + " seems not to normally extend " + target + ". Sorry, I cannot handle this.");
             }
         }
@@ -1817,7 +1784,7 @@ public abstract class StaticTypeCheckingSupport {
     }
 
     private static void extractGenericsConnections(Map<GenericsTypeName, GenericsType> connections, GenericsType[] usage, GenericsType[] declaration) {
-        // if declaration does not provide generics, there is no connection to make 
+        // if declaration does not provide generics, there is no connection to make
         if (usage == null || declaration == null || declaration.length == 0) return;
         if (usage.length != declaration.length) return;
 
@@ -1872,7 +1839,7 @@ public abstract class StaticTypeCheckingSupport {
             Map<GenericsTypeName, GenericsType> spec, ClassNode parameterUsage
     ) {
         GenericsType[] gts = parameterUsage.getGenericsTypes();
-        if (gts == null) return Collections.EMPTY_MAP;
+        if (gts == null) return Collections.emptyMap();
 
         GenericsType[] newGTs = applyGenericsContext(spec, gts);
         ClassNode newTarget = parameterUsage.redirect().getPlainNodeReference();
@@ -1981,7 +1948,7 @@ public abstract class StaticTypeCheckingSupport {
 
     private static void applyContextGenerics(Map<GenericsTypeName, GenericsType> resolvedPlaceholders, Map<GenericsTypeName, GenericsType> placeholdersFromContext) {
         if (placeholdersFromContext == null) return;
-        for (Entry<GenericsTypeName, GenericsType> entry : resolvedPlaceholders.entrySet()) {
+        for (Map.Entry<GenericsTypeName, GenericsType> entry : resolvedPlaceholders.entrySet()) {
             GenericsType gt = entry.getValue();
             if (gt.isPlaceholder()) {
                 GenericsTypeName name = new GenericsTypeName(gt.getName());
@@ -2067,7 +2034,7 @@ public abstract class StaticTypeCheckingSupport {
 
     private static Map<GenericsTypeName, GenericsType> mergeGenerics(Map<GenericsTypeName, GenericsType> current, GenericsType[] newGenerics) {
         if (newGenerics == null || newGenerics.length == 0) return current;
-        if (current == null) current = new HashMap<GenericsTypeName, GenericsType>();
+        if (current == null) current = new HashMap<>();
         for (GenericsType gt : newGenerics) {
             if (!gt.isPlaceholder()) continue;
             GenericsTypeName name = new GenericsTypeName(gt.getName());
@@ -2274,7 +2241,6 @@ public abstract class StaticTypeCheckingSupport {
         }
     }
 
-
     /**
      * @return true if the class node is either a GString or the LUB of String and GString.
      */
@@ -2349,9 +2315,8 @@ public abstract class StaticTypeCheckingSupport {
         CompilationUnit cu = new CompilationUnit(copyConf);
         cu.addClassNode(node);
         cu.compile(Phases.CLASS_GENERATION);
-        @SuppressWarnings("unchecked")
-        List<GroovyClass> classes = (List<GroovyClass>) cu.getClasses();
-        Class aClass = cu.getClassLoader().defineClass(className, classes.get(0).getBytes());
+        List<GroovyClass> classes = cu.getClasses();
+        Class<?> aClass = cu.getClassLoader().defineClass(className, classes.get(0).getBytes());
         try {
             return aClass.getMethod("eval").invoke(null);
         } catch (IllegalAccessException | NoSuchMethodException | InvocationTargetException e) {
@@ -2367,7 +2332,7 @@ public abstract class StaticTypeCheckingSupport {
      * @return a set of interfaces implemented by this class node
      */
     public static Set<ClassNode> collectAllInterfaces(ClassNode node) {
-        Set<ClassNode> result = new HashSet<ClassNode>();
+        Set<ClassNode> result = new HashSet<>();
         collectAllInterfaces(node, result);
         return result;
     }
@@ -2411,7 +2376,7 @@ public abstract class StaticTypeCheckingSupport {
                     && (!voidOnly || VOID_TYPE == method.getReturnType())
                     && method.getParameters().length == 1) {
                 if (result == null) {
-                    result = new LinkedList<MethodNode>();
+                    result = new LinkedList<>();
                 }
                 result.add(method);
             }
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 b032191..0447f9f 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -129,6 +129,7 @@ import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
 import java.util.Objects;
+import java.util.Optional;
 import java.util.Queue;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicLong;
@@ -405,7 +406,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
         typeCheckingContext.pushEnclosingClassNode(node);
         Set<MethodNode> oldVisitedMethod = typeCheckingContext.alreadyVisitedMethods;
-        typeCheckingContext.alreadyVisitedMethods = new LinkedHashSet<MethodNode>();
+        typeCheckingContext.alreadyVisitedMethods = new LinkedHashSet<>();
         super.visitClass(node);
         Iterator<InnerClassNode> innerClasses = node.getInnerClasses();
         while (innerClasses.hasNext()) {
@@ -489,14 +490,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         }
     }
 
-    private static void addPrivateFieldOrMethodAccess(Expression source, ClassNode cn, StaticTypesMarker type, ASTNode accessedMember) {
-        Set<ASTNode> set = cn.<Set<ASTNode>>getNodeMetaData(type);
-        if (set == null) {
-            set = new LinkedHashSet<ASTNode>();
-            cn.putNodeMetaData(type, set);
-        }
-        set.add(accessedMember);
-        source.putNodeMetaData(type, accessedMember);
+    private static void addPrivateFieldOrMethodAccess(Expression source, ClassNode cn, StaticTypesMarker key, ASTNode accessedMember) {
+        cn.getNodeMetaData(key, x -> new LinkedHashSet<>()).add(accessedMember);
+        source.putNodeMetaData(key, accessedMember);
     }
 
     /**
@@ -569,12 +565,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             Expression objectExpression = ((MethodCallExpression) call).getObjectExpression();
             if (isSuperExpression(objectExpression)) {
                 ClassNode current = typeCheckingContext.getEnclosingClassNode();
-                LinkedList<MethodNode> list = current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED);
-                if (list == null) {
-                    list = new LinkedList<MethodNode>();
-                    current.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, list);
-                }
-                list.add(directCallTarget);
+                current.getNodeMetaData(SUPER_MOP_METHOD_REQUIRED, x -> new LinkedList<>()).add(directCallTarget);
                 call.putNodeMetaData(SUPER_MOP_METHOD_REQUIRED, current);
             }
         }
@@ -761,8 +752,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private boolean isLHSOfEnclosingAssignment(final Expression expression) {
-        BinaryExpression ec = typeCheckingContext.getEnclosingBinaryExpression();
-        return ec != null && ec.getLeftExpression() == expression && isAssignment(ec.getOperation().getType());
+        return Optional.ofNullable(typeCheckingContext.getEnclosingBinaryExpression())
+            .filter(be -> be.getLeftExpression() == expression && isAssignment(be.getOperation().getType())).isPresent();
     }
 
     @Override
@@ -868,7 +859,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 if (leftVar.isClosureSharedVariable()) {
                     // if left expression is a closure shared variable, we should check it twice
                     // see GROOVY-5874
-                    typeCheckingContext.secondPassExpressions.add(new SecondPassExpression<Void>(expression));
+                    typeCheckingContext.secondPassExpressions.add(new SecondPassExpression<>(expression));
                 }
             }
 
@@ -938,7 +929,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         VariableExpression var = (VariableExpression) accessedVariable;
                         List<ClassNode> types = typeCheckingContext.ifElseForWhileAssignmentTracker.get(var);
                         if (types == null) {
-                            types = new LinkedList<ClassNode>();
+                            types = new LinkedList<>();
                             ClassNode type = var.getNodeMetaData(INFERRED_TYPE);
                             types.add(type);
                             typeCheckingContext.ifElseForWhileAssignmentTracker.put(var, types);
@@ -1142,9 +1133,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      * @param typeExpression     the expression which represents the target type
      */
     protected void pushInstanceOfTypeInfo(final Expression objectOfInstanceOf, final Expression typeExpression) {
-        final Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.peek();
+        Map<Object, List<ClassNode>> tempo = typeCheckingContext.temporaryIfBranchTypeInformation.peek();
         Object key = extractTemporaryTypeInfoKey(objectOfInstanceOf);
-        List<ClassNode> potentialTypes = tempo.computeIfAbsent(key, k -> new LinkedList<ClassNode>());
+        List<ClassNode> potentialTypes = tempo.computeIfAbsent(key, k -> new LinkedList<>());
         potentialTypes.add(typeExpression.getType());
     }
 
@@ -1389,7 +1380,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             if (!(keyExpr instanceof ConstantExpression)) {
                 addStaticTypeError("Dynamic keys in map-style constructors are unsupported in static type checking", keyExpr);
             } else {
-                AtomicReference<ClassNode> lookup = new AtomicReference<ClassNode>();
+                AtomicReference<ClassNode> lookup = new AtomicReference<>();
                 PropertyExpression pexp = new PropertyExpression(varX("_", receiverType), keyExpr.getText());
                 boolean hasProperty = existsProperty(pexp, false, new PropertyLookupVisitor(lookup));
                 if (!hasProperty) {
@@ -1766,7 +1757,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         ClassNode contentType = OBJECT_TYPE;
         if (types != null && types.length == 1) contentType = types[0].getType();
         PropertyExpression subExp = new PropertyExpression(varX("{}", contentType), pexp.getPropertyAsString());
-        AtomicReference<ClassNode> result = new AtomicReference<ClassNode>();
+        AtomicReference<ClassNode> result = new AtomicReference<>();
         if (existsProperty(subExp, true, new PropertyLookupVisitor(result))) {
             ClassNode intf = LIST_TYPE.getPlainNodeReference();
             intf.setGenericsTypes(new GenericsType[]{new GenericsType(getWrapper(result.get()))});
@@ -1782,7 +1773,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (types == null || types.length != 1) return OBJECT_TYPE;
 
         PropertyExpression subExp = new PropertyExpression(varX("{}", types[0].getType()), pexp.getPropertyAsString());
-        AtomicReference<ClassNode> result = new AtomicReference<ClassNode>();
+        AtomicReference<ClassNode> result = new AtomicReference<>();
         if (existsProperty(subExp, true, new PropertyLookupVisitor(result))) {
             intf = LIST_TYPE.getPlainNodeReference();
             ClassNode itemType = result.get();
@@ -1939,7 +1930,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<VariableExpression, ClassNode>();
+        final Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
         forLoop.getLoopBlock().visit(new VariableExpressionTypeMemoizer(varOrigType));
 
         // visit body
@@ -2078,72 +2069,72 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     @Override
     public void visitPostfixExpression(final PostfixExpression expression) {
         super.visitPostfixExpression(expression);
-        Expression inner = expression.getExpression();
-        int op = expression.getOperation().getType();
-        visitPrefixOrPostifExpression(expression, inner, op);
+        Expression operand = expression.getExpression();
+        int operator = expression.getOperation().getType();
+        visitPrefixOrPostifExpression(expression, operand, operator);
     }
 
     @Override
     public void visitPrefixExpression(final PrefixExpression expression) {
         super.visitPrefixExpression(expression);
-        Expression inner = expression.getExpression();
-        int type = expression.getOperation().getType();
-        visitPrefixOrPostifExpression(expression, inner, type);
+        Expression operand = expression.getExpression();
+        int operator = expression.getOperation().getType();
+        visitPrefixOrPostifExpression(expression, operand, operator);
     }
 
-    private static ClassNode getMathWideningClassNode(ClassNode type) {
-        if (byte_TYPE.equals(type) || short_TYPE.equals(type) || int_TYPE.equals(type)) {
-            return int_TYPE;
-        }
-        if (Byte_TYPE.equals(type) || Short_TYPE.equals(type) || Integer_TYPE.equals(type)) {
-            return Integer_TYPE;
-        }
-        if (float_TYPE.equals(type)) return double_TYPE;
-        if (Float_TYPE.equals(type)) return Double_TYPE;
-        return type;
-    }
-
-    private void visitPrefixOrPostifExpression(final Expression origin, final Expression innerExpression, final int operationType) {
+    private void visitPrefixOrPostifExpression(final Expression origin, final Expression operand, final int operator) {
         boolean isPostfix = origin instanceof PostfixExpression;
-        ClassNode exprType = getType(innerExpression);
-        String name = operationType == PLUS_PLUS ? "next" : operationType == MINUS_MINUS ? "previous" : null;
-        if (isPrimitiveType(exprType) || isPrimitiveType(getUnwrapper(exprType))) {
-            if (operationType == PLUS_PLUS || operationType == MINUS_MINUS) {
-                if (!isPrimitiveType(exprType)) {
-                    MethodNode node = findMethodOrFail(varX("_dummy_", exprType), exprType, name);
-                    if (node != null) {
-                        storeTargetMethod(origin, node);
-                        storeType(origin,
-                                isPostfix ? exprType : getMathWideningClassNode(exprType));
-                        return;
-                    }
+        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);
+                if (node != null) {
+                    storeTargetMethod(origin, node);
+                    storeType(origin, isPostfix ? exprType : getMathWideningClassNode(exprType));
+                    return;
                 }
-                storeType(origin, exprType);
-                return;
             }
-            addUnsupportedPreOrPostfixExpressionError(origin);
+            storeType(origin, exprType);
             return;
-        } else if (implementsInterfaceOrIsSubclassOf(exprType, Number_TYPE) && (operationType == PLUS_PLUS || operationType == MINUS_MINUS)) {
+        }
+        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(innerExpression, exprType, name);
+            MethodNode node = findMethodOrFail(operand, exprType, name);
             if (node != null) {
                 storeTargetMethod(origin, node);
                 storeType(origin, getMathWideningClassNode(exprType));
                 return;
             }
         }
-        // not a primitive type. We must find a method which is called next
         if (name == null) {
             addUnsupportedPreOrPostfixExpressionError(origin);
             return;
         }
-        MethodNode node = findMethodOrFail(innerExpression, exprType, name);
+        MethodNode node = findMethodOrFail(operand, exprType, name);
         if (node != null) {
             storeTargetMethod(origin, node);
             storeType(origin, isPostfix ? exprType : inferReturnTypeGenerics(exprType, node, ArgumentListExpression.EMPTY_ARGUMENTS));
         }
     }
 
+    private static ClassNode getMathWideningClassNode(ClassNode type) {
+        if (byte_TYPE.equals(type) || short_TYPE.equals(type) || int_TYPE.equals(type)) {
+            return int_TYPE;
+        }
+        if (Byte_TYPE.equals(type) || Short_TYPE.equals(type) || Integer_TYPE.equals(type)) {
+            return Integer_TYPE;
+        }
+        if (float_TYPE.equals(type)) {
+            return double_TYPE;
+        }
+        if (Float_TYPE.equals(type)) {
+            return Double_TYPE;
+        }
+        return type;
+    }
+
     private void negativeOrPositiveUnary(Expression expression, String name) {
         ClassNode type = getType(expression);
         ClassNode typeRe = type.redirect();
@@ -2338,7 +2329,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (exp instanceof VariableExpression && info != null) {
             List<ClassNode> classNodes = getTemporaryTypesForExpression(exp);
             if (classNodes != null && !classNodes.isEmpty()) {
-                ArrayList<ClassNode> arr = new ArrayList<ClassNode>(classNodes.size() + 1);
+                ArrayList<ClassNode> arr = new ArrayList<>(classNodes.size() + 1);
                 if (result != null && !classNodes.contains(result)) arr.add(result);
                 arr.addAll(classNodes);
                 // GROOVY-7333: filter out Object
@@ -2361,7 +2352,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<VariableExpression, ClassNode>();
+        final Map<VariableExpression, ClassNode> varOrigType = new HashMap<>();
         Statement code = expression.getCode();
         code.visit(new VariableExpressionTypeMemoizer(varOrigType));
         Map<VariableExpression, List<ClassNode>> oldTracker = pushAssignmentTracking();
@@ -2452,7 +2443,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // GROOVY-6921: We must force a call to getType in order to update closure shared variable whose
             // types are inferred thanks to closure parameter type inference
             getType(ve);
-            Map<StaticTypesMarker, Object> metadata = new ListHashMap<StaticTypesMarker, Object>();
+            Map<StaticTypesMarker, Object> metadata = new ListHashMap<>();
             for (StaticTypesMarker marker : StaticTypesMarker.values()) {
                 Object value = ve.getNodeMetaData(marker);
                 if (value != null) {
@@ -2468,8 +2459,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     protected boolean shouldSkipMethodNode(final MethodNode node) {
-        Object type = node.getNodeMetaData(StaticTypeCheckingVisitor.class);
-        return Boolean.TRUE.equals(type);
+        return Boolean.TRUE.equals(node.getNodeMetaData(StaticTypeCheckingVisitor.class));
     }
 
     @Override
@@ -2598,7 +2588,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             //   - the actual receiver as found in the method call expression
             //   - any of the potential receivers found in the instanceof temporary table
             // in that order
-            List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
+            List<Receiver<String>> receivers = new LinkedList<>();
             addReceivers(receivers, makeOwnerList(new ClassExpression(receiver)), false);
             List<MethodNode> mn = null;
             Receiver<String> chosenReceiver = null;
@@ -2680,7 +2670,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     protected void visitMethodCallArguments(final ClassNode receiver, ArgumentListExpression arguments, boolean visitClosures, final MethodNode selectedMethod) {
         Parameter[] params = selectedMethod != null ? selectedMethod.getParameters() : Parameter.EMPTY_ARRAY;
-        List<Expression> expressions = new LinkedList<Expression>(arguments.getExpressions());
+        List<Expression> expressions = new LinkedList<>(arguments.getExpressions());
         if (selectedMethod instanceof ExtensionMethodNode) {
             params = ((ExtensionMethodNode) selectedMethod).getExtensionMethodNode().getParameters();
             expressions.add(0, varX("$self", receiver));
@@ -2716,7 +2706,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     private void checkNamedParamsAnnotation(Parameter param, MapExpression args) {
         if (!isOrImplements(param.getType(), MAP_TYPE)) return;
         List<MapEntryExpression> entryExpressions = args.getMapEntryExpressions();
-        Map<Object, Expression> entries = new LinkedHashMap<Object, Expression>();
+        Map<Object, Expression> entries = new LinkedHashMap<>();
         for (MapEntryExpression entry : entryExpressions) {
             Object key = entry.getKeyExpression();
             if (key instanceof ConstantExpression) {
@@ -2732,7 +2722,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     an = next;
                 }
             }
-            List<String> collectedNames = new ArrayList<String>();
+            List<String> collectedNames = new ArrayList<>();
             if (an != null) {
                 Expression value = an.getMember("value");
                 if (value instanceof AnnotationConstantExpression) {
@@ -2834,7 +2824,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
         // First we try to get as much information about the declaration
         // class through the receiver
-        Map<GenericsTypeName, GenericsType> targetMethodDeclarationClassConnections = new HashMap<GenericsTypeName, GenericsType>();
+        Map<GenericsTypeName, GenericsType> targetMethodDeclarationClassConnections = new HashMap<>();
         extractGenericsConnections(targetMethodDeclarationClassConnections, receiver, receiver.redirect());
         // then we use the method with the SAM parameter to get more information about the declaration
         Parameter[] parametersOfMethodContainingSAM = methodWithSAMParameter.getParameters();
@@ -2855,7 +2845,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // to replace the generics in the SAM type parameter of the target
         // method and than that to make the connections to the SAM type generics
         ClassNode paramTypeWithReceiverInformation = applyGenericsContext(targetMethodDeclarationClassConnections, param.getOriginType());
-        Map<GenericsTypeName, GenericsType> SAMTypeConnections = new HashMap<GenericsTypeName, GenericsType>();
+        Map<GenericsTypeName, GenericsType> SAMTypeConnections = new HashMap<>();
         ClassNode classForSAM = paramTypeWithReceiverInformation.redirect();
         extractGenericsConnections(SAMTypeConnections, paramTypeWithReceiverInformation, classForSAM);
 
@@ -3275,9 +3265,9 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private static void addDelegateReceiver(final List<Receiver<String>> receivers, final ClassNode delegate, final String path) {
-        receivers.add(new Receiver<String>(delegate, path));
+        receivers.add(new Receiver<>(delegate, path));
         if (Traits.isTrait(delegate.getOuterClass())) {
-            receivers.add(new Receiver<String>(delegate.getOuterClass(), path));
+            receivers.add(new Receiver<>(delegate.getOuterClass(), path));
         }
     }
 
@@ -3407,7 +3397,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 //   - the actual receiver as found in the method call expression
                 //   - any of the potential receivers found in the instanceof temporary table
                 // in that order
-                List<Receiver<String>> receivers = new LinkedList<Receiver<String>>();
+                List<Receiver<String>> receivers = new LinkedList<>();
                 List<Receiver<String>> owners = makeOwnerList(objectExpression);
                 addReceivers(receivers, owners, call.isImplicitThis());
                 List<MethodNode> mn = null;
@@ -3427,8 +3417,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         // a nice error message to the user
                         // a method is accessible if it is static, or if we are not in a static context and it is
                         // declared by the current receiver or a superclass
-                        List<MethodNode> accessibleMethods = new LinkedList<MethodNode>();
-                        List<MethodNode> inaccessibleMethods = new LinkedList<MethodNode>();
+                        List<MethodNode> accessibleMethods = new LinkedList<>();
+                        List<MethodNode> inaccessibleMethods = new LinkedList<>();
                         for (final MethodNode node : mn) {
                             if (node.isStatic()
                                     || (!typeCheckingContext.isInStaticContext && implementsInterfaceOrIsSubclassOf(receiverType, node.getDeclaringClass()))) {
@@ -3517,10 +3507,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                             if (objectExpression instanceof VariableExpression) {
                                 VariableExpression var = (VariableExpression) objectExpression;
                                 if (var.isClosureSharedVariable()) {
-                                    SecondPassExpression<ClassNode[]> wrapper = new SecondPassExpression<ClassNode[]>(
-                                            call,
-                                            args
-                                    );
+                                    SecondPassExpression<ClassNode[]> wrapper = new SecondPassExpression<>(call, args);
                                     typeCheckingContext.secondPassExpressions.add(wrapper);
                                 }
                             }
@@ -3651,7 +3638,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (directMethodCallCandidate instanceof ExtensionMethodNode) {
             ExtensionMethodNode emn = (ExtensionMethodNode) directMethodCallCandidate;
             if ("withTraits".equals(emn.getName()) && "DefaultGroovyMethods".equals(emn.getExtensionMethodNode().getDeclaringClass().getNameWithoutPackage())) {
-                List<ClassNode> nodes = new LinkedList<ClassNode>();
+                List<ClassNode> nodes = new LinkedList<>();
                 Collections.addAll(nodes, receiver.getInterfaces());
                 for (ClassNode arg : args) {
                     if (isClassClassNodeWrappingConcreteType(arg)) {
@@ -3718,7 +3705,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      */
     protected List<Receiver<String>> makeOwnerList(final Expression objectExpression) {
         final ClassNode receiver = getType(objectExpression);
-        List<Receiver<String>> owners = new LinkedList<Receiver<String>>();
+        List<Receiver<String>> owners = new LinkedList<>();
         owners.add(Receiver.<String>make(receiver));
         if (isClassClassNodeWrappingConcreteType(receiver)) {
             GenericsType clazzGT = receiver.getGenericsTypes()[0];
@@ -3754,7 +3741,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     }
 
     private static void addSelfTypes(final ClassNode receiver, final List<Receiver<String>> owners) {
-        LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<ClassNode>();
+        LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<>();
         for (ClassNode selfType : Traits.collectSelfTypes(receiver, selfTypes)) {
             owners.add(Receiver.<String>make(selfType));
         }
@@ -4011,7 +3998,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 VariableExpression key = entry.getKey();
                 List<ClassNode> allValues = entry.getValue();
                 // GROOVY-6099: First element of the list may be null, if no assignment was made before the branch
-                List<ClassNode> nonNullValues = new ArrayList<ClassNode>(allValues.size());
+                List<ClassNode> nonNullValues = new ArrayList<>(allValues.size());
                 for (ClassNode value : allValues) {
                     if (value != null) nonNullValues.add(value);
                 }
@@ -4027,7 +4014,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     protected Map<VariableExpression, List<ClassNode>> pushAssignmentTracking() {
         // memorize current assignment context
         Map<VariableExpression, List<ClassNode>> oldTracker = typeCheckingContext.ifElseForWhileAssignmentTracker;
-        typeCheckingContext.ifElseForWhileAssignmentTracker = new HashMap<VariableExpression, List<ClassNode>>();
+        typeCheckingContext.ifElseForWhileAssignmentTracker = new HashMap<>();
         return oldTracker;
     }
 
@@ -4401,7 +4388,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (samGt == null || closureGt == null) return samUsage;
 
         // extract the generics from the return type
-        Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>();
+        Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
         extractGenericsConnections(connections, getInferredReturnType(closureExpression), sam.getReturnType());
 
         // next we get the block parameter types and set the generics
@@ -4573,7 +4560,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private static List<MethodNode> addGeneratedMethods(final ClassNode receiver, final List<MethodNode> methods) {
         // using a comparator of parameters
-        List<MethodNode> result = new LinkedList<MethodNode>();
+        List<MethodNode> result = new LinkedList<>();
         for (MethodNode method : methods) {
             result.add(method);
             Parameter[] parameters = method.getParameters();
@@ -4632,7 +4619,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (isPrimitiveType(receiver)) receiver = getWrapper(receiver);
         List<MethodNode> methods;
         if (!receiver.isInterface() && "<init>".equals(name)) {
-            methods = addGeneratedMethods(receiver, new ArrayList<MethodNode>(receiver.getDeclaredConstructors()));
+            methods = addGeneratedMethods(receiver, new ArrayList<>(receiver.getDeclaredConstructors()));
             if (methods.isEmpty()) {
                 MethodNode node = new ConstructorNode(Opcodes.ACC_PUBLIC, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, GENERATED_EMPTY_STATEMENT);
                 node.setDeclaringClass(receiver);
@@ -4956,7 +4943,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
      */
     private ClassNode getGenericsResolvedTypeOfFieldOrProperty(AnnotatedNode an, ClassNode type) {
         if (!type.isUsingGenerics()) return type;
-        Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>();
+        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);
@@ -4987,7 +4974,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private static ClassNode makeSelf(ClassNode trait) {
         ClassNode ret = trait;
-        LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<ClassNode>();
+        LinkedHashSet<ClassNode> selfTypes = new LinkedHashSet<>();
         Traits.collectSelfTypes(ret, selfTypes);
         if (!selfTypes.isEmpty()) {
             selfTypes.add(ret);
@@ -5036,7 +5023,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 || (genericsTypes.length == 1 && OBJECT_TYPE.equals(genericsTypes[0].getType())))
                 && (!expressions.isEmpty())) {
             // maybe we can infer the component type
-            List<ClassNode> nodes = new LinkedList<ClassNode>();
+            List<ClassNode> nodes = new LinkedList<>();
             for (Expression expression : expressions) {
                 if (isNullConstant(expression)) {
                     // a null element is found in the list, skip it because we'll use the other elements from the list
@@ -5076,8 +5063,8 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         if (genericsTypes == null
                 || genericsTypes.length < 2
                 || (genericsTypes.length == 2 && OBJECT_TYPE.equals(genericsTypes[0].getType()) && OBJECT_TYPE.equals(genericsTypes[1].getType()))) {
-            List<ClassNode> keyTypes = new LinkedList<ClassNode>();
-            List<ClassNode> valueTypes = new LinkedList<ClassNode>();
+            List<ClassNode> keyTypes = new LinkedList<>();
+            List<ClassNode> valueTypes = new LinkedList<>();
             for (MapEntryExpression entryExpression : entryExpressions) {
                 keyTypes.add(getType(entryExpression.getKeyExpression()));
                 valueTypes.add(getType(entryExpression.getValueExpression()));
@@ -5190,7 +5177,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     }
                     actualType = wrapTypeIfNecessary(actualType);
 
-                    Map<GenericsTypeName, GenericsType> connections = new HashMap<GenericsTypeName, GenericsType>();
+                    Map<GenericsTypeName, GenericsType> connections = new HashMap<>();
                     extractGenericsConnections(connections, actualType, type);
                     extractGenericsConnectionsForSuperClassAndInterfaces(resolvedPlaceholders, connections);
                     applyGenericsConnections(connections, resolvedPlaceholders);
@@ -5218,7 +5205,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         for (GenericsType value : new HashSet<GenericsType>(connections.values())) {
             if (!value.isPlaceholder() && !value.isWildcard()) {
                 ClassNode valueType = value.getType();
-                List<ClassNode> deepNodes = new LinkedList<ClassNode>();
+                List<ClassNode> deepNodes = new LinkedList<>();
                 ClassNode unresolvedSuperClass = valueType.getUnresolvedSuperClass();
                 if (unresolvedSuperClass != null && unresolvedSuperClass.isUsingGenerics()) {
                     deepNodes.add(unresolvedSuperClass);
@@ -5283,7 +5270,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
             // now repeat the same for each parameter given in the ClosureExpression
             if (expression instanceof ClosureExpression && sam.getParameters().length > 0) {
-                List<ClassNode[]> genericsToConnect = new LinkedList<ClassNode[]>();
+                List<ClassNode[]> genericsToConnect = new LinkedList<>();
                 Parameter[] closureParams = ((ClosureExpression) expression).getParameters();
                 ClassNode[] closureParamTypes = extractTypesFromParameters(closureParams);
                 if (expression.getNodeMetaData(CLOSURE_ARGUMENTS) != null) {
@@ -5369,7 +5356,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private static Map<GenericsTypeName, GenericsType> extractPlaceHolders(MethodNode method, ClassNode receiver, ClassNode declaringClass) {
         if (declaringClass.equals(OBJECT_TYPE)) {
-            Map<GenericsTypeName, GenericsType> resolvedPlaceholders = new HashMap<GenericsTypeName, GenericsType>();
+            Map<GenericsTypeName, GenericsType> resolvedPlaceholders = new HashMap<>();
             if (method != null) addMethodLevelDeclaredGenerics(method, resolvedPlaceholders);
             return resolvedPlaceholders;
         }
@@ -5389,7 +5376,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             while (current != null) {
                 boolean continueLoop = true;
                 //extract the place holders
-                Map<GenericsTypeName, GenericsType> currentPlaceHolders = new HashMap<GenericsTypeName, GenericsType>();
+                Map<GenericsTypeName, GenericsType> currentPlaceHolders = new HashMap<>();
                 if (isGenericsPlaceHolderOrArrayOf(declaringClass) || declaringClass.equals(current)) {
                     extractGenericsConnections(currentPlaceHolders, current, declaringClass);
                     if (method != null) addMethodLevelDeclaredGenerics(method, currentPlaceHolders);
diff --git a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
index 97d8529..1bd307d 100644
--- a/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
+++ b/src/test/org/codehaus/groovy/classgen/asm/sc/bugs/Groovy7276.groovy
@@ -71,14 +71,16 @@ final class Groovy7276 extends StaticTypeCheckingTestCase implements StaticCompi
 
     @NotYetImplemented // GROOVY-7304
     void testShouldGoThroughPrivateBridgeAccessorWithWriteAccess() {
-        assertScript '''
-            class Foo {
-                private int i = 1
-                def m() { new String().with { ++i } }
-            }
-            assert new Foo().m() == 2
-            class Bar extends Foo {}
-            assert new Bar().m() == 2
-        '''
+        ['++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
+            """
+        }
     }
 }


[groovy] 12/18: updated docs for groovyc ant task

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 45d974a66acd3b74fcb14a02e470c3610f674164
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Thu Nov 14 10:26:14 2019 -0600

    updated docs for groovyc ant task
    
    (cherry picked from commit b2842cbce83546fdc73d351351cd114c5db23393)
---
 src/spec/doc/tools-groovyc.adoc | 70 +++++++++++++++++++++--------------------
 1 file changed, 36 insertions(+), 34 deletions(-)

diff --git a/src/spec/doc/tools-groovyc.adoc b/src/spec/doc/tools-groovyc.adoc
index 7871561..6d81049 100644
--- a/src/spec/doc/tools-groovyc.adoc
+++ b/src/spec/doc/tools-groovyc.adoc
@@ -75,16 +75,18 @@ Compiles Groovy source files and, if joint compilation option is used, Java sour
 Required taskdef
 ^^^^^^^^^^^^^^^^
 
-Assuming all the groovy jars you need are in _my.classpath_ (this will be `groovy-VERSION.jar`,
-`groovy-ant-VERSION.jar` plus any modules and transitive dependencies you might be using)
-you will need to declare this task at some point in the `build.xml` prior to the `groovyc` task being invoked.
+Assuming the groovy jars are in _groovy.libs_, you will need to declare this task
+at some point in the `build.xml` prior to the `groovyc` task being invoked.
 
 [source,xml]
-----------------------------------------------------
-<taskdef name="groovyc"
-         classname="org.codehaus.groovy.ant.Groovyc"
-         classpathref="my.classpath"/>
-----------------------------------------------------
+-----------------------------------------------------------------------
+<taskdef name="groovyc" classname="org.codehaus.groovy.ant.Groovyc">
+  <classpath>
+    <fileset file="${groovy.libs}/groovy-ant-VERSION.jar"/>
+    <fileset file="${groovy.libs}/groovy-VERSION.jar"/>
+  </classpath>
+</taskdef>
+-----------------------------------------------------------------------
 
 [[ThegroovycAntTask-groovycAttributes]]
 <groovyc> Attributes
@@ -166,6 +168,9 @@ you need to set this flag to true. Defaults to false. |No
 |parameters |Generates metadata for reflection on method parameter names on JDK 8 and above.
 Defaults to false. |No
 
+|previewFeatures |Enables the JEP preview features on JDK 12 and above.
+Defaults to false. |No
+
 |targetBytecode |Sets the bytecode compatibility level. |No
 
 |javahome |Sets the `java.home` value to use, default is the current JDK's home. |No
@@ -187,10 +192,14 @@ the compilation fails. |No
 *Example:*
 
 [source,xml]
-----
-<groovyc srcdir="src" destdir="target/classes">
-</groovyc>
-----
+-----------------------------------------------------------------------
+<path id="classpath.main">
+  <fileset dir="${groovy.libs}" includes="*.jar" excludes="groovy-ant-*.jar"/>
+  ...
+</path>
+<groovyc srcdir="${dir.sources}" destdir="${dir.classes}" classpathref="classpath.main"
+         fork="true" includeantruntime="false" configscript="config.groovy" targetBytecode="1.8"/>
+-----------------------------------------------------------------------
 
 
 [[ThegroovycAntTask-groovycNestedElements]]
@@ -201,48 +210,41 @@ the compilation fails. |No
 |==========================================================
 |element |kind |Required |Replaces Attribute
 |src |a path structure |Yes (unless srcdir is used) |srcdir
-|classpath |a path structure |No |classpath
-|javac |javac task |No |jointCompilationOptions
+|classpath |a path structure |No |classpath or classpathref
+|javac |javac task |No |N/A
 |==========================================================
 
 *Notes:*
 
 * For path structures see for example
 http://ant.apache.org/manual/using.html#path
-* For usages of the javac task see
+* For usages of the `javac` task see
 https://ant.apache.org/manual/Tasks/javac.html
-* The nested javac task behaves more or less as documented for the
-top-level `javac` task. `srcdir`, `destdir`, `classpath`, `encoding` for the
-nested `javac` task are taken from the enclosing `groovyc` task. If these
-attributes are specified then they are added, they do not replace. In
-fact, you should not attempt to overwrite the destination. Other
-attributes and nested elements are unaffected, for example `fork`,
-`memoryMaximumSize`, etc. may be used freely.
+* The nested `javac` task behaves more or less as documented for the top-level
+`javac` task. `srcdir`, `destdir`, `classpath`, `encoding` and `parameters`
+for the nested `javac` task are taken from the enclosing `groovyc` task. If
+these attributes are specified then they are added, they do not replace. In fact,
+you should not attempt to overwrite the destination. Other attributes and nested
+elements are unaffected, for example `fork`, `memoryMaximumSize`, etc. may be
+used freely.
 
 [[ThegroovycAntTask-JointCompilation]]
 Joint Compilation
 ^^^^^^^^^^^^^^^^^
 
-Joint compilation is enabled by using an embedded `javac` element, as shown in
-the following example:
+Joint compilation is enabled by using an embedded `javac` element, as shown in the following example:
 
 [source,xml]
-----
-<groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}">
+-----------------------------------------------------------------------
+<groovyc srcdir="${testSourceDirectory}" destdir="${testClassesDirectory}" targetBytecode="1.8">
   <classpath>
     <pathelement path="${mainClassesDirectory}"/>
     <pathelement path="${testClassesDirectory}"/>
     <path refid="testPath"/>
   </classpath>
-  <javac source="1.7" target="1.7" debug="on" />
+  <javac debug="true" source="1.8" target="1.8" />
 </groovyc>
-----
-
-It is rare to specify `srcdir` and `destdir`, the nested `javac` task is provided with the `srcdir`
-and `destdir` values from the enclosing `groovyc` task, and it is invariable
-the right thing to do just to leave this as is.
-To restate: the `javac` task gets the `srcdir`, `destdir` and `classpath` from
-the enclosing `groovyc` task.
+-----------------------------------------------------------------------
 
 More details about joint compilation can be found in the <<section-jointcompilation,joint compilation>> section.
 


[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 d1f9977722da5762fee40c3b1730267f476f45ad
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Mon Nov 11 12:46:38 2019 -0600

    minor edits
    
    (cherry picked from commit 81d8ac64923b9d514b3c49295a7f28241bbb46d4)
---
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 82 +++++++++-------------
 .../org/codehaus/groovy/ant/GroovycTest.xml        | 22 +++---
 .../org/codehaus/groovy/ant/GroovycTest2.java      |  6 +-
 .../org/codehaus/groovy/ant/GroovycTest.java       | 62 +++++++++-------
 4 files changed, 85 insertions(+), 87 deletions(-)

diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index f617d8e..a7d41af 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -19,7 +19,6 @@
 package org.codehaus.groovy.ant;
 
 import groovy.lang.GroovyClassLoader;
-import groovy.lang.GroovyResourceLoader;
 import org.apache.groovy.io.StringBuilderWriter;
 import org.apache.tools.ant.AntClassLoader;
 import org.apache.tools.ant.BuildException;
@@ -48,7 +47,6 @@ import java.io.FileWriter;
 import java.io.IOException;
 import java.io.PrintWriter;
 import java.io.Writer;
-import java.net.MalformedURLException;
 import java.net.URL;
 import java.nio.charset.Charset;
 import java.security.AccessController;
@@ -58,6 +56,7 @@ import java.util.Enumeration;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.Set;
 import java.util.StringTokenizer;
 
@@ -169,6 +168,7 @@ public class Groovyc extends MatchingTask {
     private static final URL[] EMPTY_URL_ARRAY = new URL[0];
     private static final File[] EMPTY_FILE_ARRAY = new File[0];
     private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private final LoggingHelper log = new LoggingHelper(this);
 
     private Path src;
@@ -297,7 +297,6 @@ public class Groovyc extends MatchingTask {
      * @param version the bytecode compatibility level
      */
     public void setTargetBytecode(String version) {
-
         for (String allowedJdk : CompilerConfiguration.ALLOWED_JDKS) {
             if (allowedJdk.equals(version)) {
                 this.targetBytecode = version;
@@ -966,10 +965,9 @@ public class Groovyc extends MatchingTask {
 
         // extract joint options, some get pushed up...
         RuntimeConfigurable rc = javac.getRuntimeConfigurableWrapper();
-        for (Object o1 : rc.getAttributeMap().entrySet()) {
-            final Map.Entry e = (Map.Entry) o1;
-            final String key = e.getKey().toString();
-            final String value = getProject().replaceProperties(e.getValue().toString());
+        for (Map.Entry<String, Object> e : rc.getAttributeMap().entrySet()) {
+            String key = e.getKey();
+            String value = getProject().replaceProperties(e.getValue().toString());
             if (key.contains("debug")) {
                 String level = "";
                 if (javac.getDebugLevel() != null) {
@@ -999,15 +997,14 @@ public class Groovyc extends MatchingTask {
 
         // ant's <javac> supports nested <compilerarg value=""> elements (there can be multiple of them)
         // for additional options to be passed to javac.
-        Enumeration children = rc.getChildren();
+        Enumeration<RuntimeConfigurable> children = rc.getChildren();
         while (children.hasMoreElements()) {
-            RuntimeConfigurable childrc = (RuntimeConfigurable) children.nextElement();
+            RuntimeConfigurable childrc = children.nextElement();
             if (childrc.getElementTag().equals("compilerarg")) {
-                for (Object o : childrc.getAttributeMap().entrySet()) {
-                    final Map.Entry e = (Map.Entry) o;
-                    final String key = e.getKey().toString();
+                for (Map.Entry<String, Object> e : childrc.getAttributeMap().entrySet()) {
+                    String key = e.getKey();
                     if (key.equals("value")) {
-                        final String value = getProject().replaceProperties(e.getValue().toString());
+                        String value = getProject().replaceProperties(e.getValue().toString());
                         StringTokenizer st = new StringTokenizer(value, " ");
                         while (st.hasMoreTokens()) {
                             String optionStr = st.nextToken();
@@ -1026,16 +1023,14 @@ public class Groovyc extends MatchingTask {
     }
 
     private void doForkCommandLineList(List<String> commandLineList, Path classpath, String separator) {
-        if (!fork) return;
-
         if (includeAntRuntime) {
-            classpath.addExisting((new Path(getProject())).concatSystemClasspath("last"));
+            classpath.addExisting(new Path(getProject()).concatSystemClasspath("last"));
         }
         if (includeJavaRuntime) {
             classpath.addJavaRuntime();
         }
 
-        if (forkedExecutable != null && !forkedExecutable.equals("")) {
+        if (forkedExecutable != null && !forkedExecutable.isEmpty()) {
             commandLineList.add(forkedExecutable);
         } else {
             String javaHome;
@@ -1049,18 +1044,17 @@ public class Groovyc extends MatchingTask {
         commandLineList.add("-classpath");
         commandLineList.add(getClasspathRelative(classpath));
 
-        final String fileEncodingProp = System.getProperty("file.encoding");
-        if ((fileEncodingProp != null) && !fileEncodingProp.equals("")) {
-            commandLineList.add("-Dfile.encoding=" + fileEncodingProp);
+        String fileEncoding = System.getProperty("file.encoding");
+        if (fileEncoding != null && !fileEncoding.isEmpty()) {
+            commandLineList.add("-Dfile.encoding=" + fileEncoding);
         }
         if (targetBytecode != null) {
             commandLineList.add("-Dgroovy.target.bytecode=" + targetBytecode);
         }
-
-        if ((memoryInitialSize != null) && !memoryInitialSize.equals("")) {
+        if (memoryInitialSize != null && !memoryInitialSize.isEmpty()) {
             commandLineList.add("-Xms" + memoryInitialSize);
         }
-        if ((memoryMaximumSize != null) && !memoryMaximumSize.equals("")) {
+        if (memoryMaximumSize != null && !memoryMaximumSize.isEmpty()) {
             commandLineList.add("-Xmx" + memoryMaximumSize);
         }
         if (!"*.groovy".equals(getScriptExtension())) {
@@ -1172,12 +1166,12 @@ public class Groovyc extends MatchingTask {
     }
 
     private String[] makeCommandLine(List<String> commandLineList) {
-        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable)commandLineList, "\n"));
+        log.verbose("Compilation arguments:\n" + DefaultGroovyMethods.join((Iterable<String>) commandLineList, "\n"));
         return commandLineList.toArray(EMPTY_STRING_ARRAY);
     }
 
     private void runForked(String[] commandLine) {
-        final Execute executor = new Execute();
+        Execute executor = new Execute();
         executor.setAntRun(getProject());
         executor.setWorkingDirectory(getProject().getBaseDir());
         executor.setCommandline(commandLine);
@@ -1186,7 +1180,7 @@ public class Groovyc extends MatchingTask {
         } catch (final IOException ioe) {
             throw new BuildException("Error running forked groovyc.", ioe);
         }
-        final int returnCode = executor.getExitValue();
+        int returnCode = executor.getExitValue();
         if (returnCode != 0) {
             taskSuccess = false;
             if (errorProperty != null) {
@@ -1212,28 +1206,23 @@ public class Groovyc extends MatchingTask {
             if (tmpExtension.startsWith("*."))
                 tmpExtension = tmpExtension.substring(1);
             configuration.setDefaultScriptExtension(tmpExtension);
-
-            // Load the file name list
-            String[] filenames = options.generateFileNames();
-            boolean fileNameErrors = filenames == null;
-
-            fileNameErrors = fileNameErrors || !FileSystemCompiler.validateFiles(filenames);
-
             if (targetBytecode != null) {
                 configuration.setTargetBytecode(targetBytecode);
             }
 
+            // Load the file name list
+            String[] fileNames = options.generateFileNames();
+            boolean fileNameErrors = (fileNames == null || !FileSystemCompiler.validateFiles(fileNames));
             if (!fileNameErrors) {
                 try (GroovyClassLoader loader = buildClassLoaderFor()) {
-                    FileSystemCompiler.doCompilation(configuration, makeCompileUnit(loader), filenames, forceLookupUnnamedFiles);
+                    FileSystemCompiler.doCompilation(configuration, makeCompileUnit(loader), fileNames, forceLookupUnnamedFiles);
                 }
             }
-
-        } catch (Exception re) {
-            Throwable t = re;
-            if ((re.getClass() == RuntimeException.class) && (re.getCause() != null)) {
+        } catch (Exception e) {
+            Throwable t = e;
+            if (e.getClass() == RuntimeException.class && e.getCause() != null) {
                 // unwrap to the real exception
-                t = re.getCause();
+                t = e.getCause();
             }
             Writer writer = new StringBuilderWriter();
             new ErrorReporter(t, false).write(new PrintWriter(writer));
@@ -1262,13 +1251,13 @@ public class Groovyc extends MatchingTask {
                     + (destDir != null ? " to " + destDir : ""));
 
             listFiles();
-            Path classpath = getClasspath() != null ? getClasspath() : new Path(getProject());
-            List<String> jointOptions = extractJointOptions(classpath);
 
+            Path classpath = Optional.ofNullable(getClasspath()).orElse(new Path(getProject()));
+            List<String> jointOptions = extractJointOptions(classpath);
             String separator = System.getProperty("file.separator");
             List<String> commandLineList = new ArrayList<>();
 
-            doForkCommandLineList(commandLineList, classpath, separator);
+            if (fork) doForkCommandLineList(commandLineList, classpath, separator);
             doNormalCommandLineList(commandLineList, jointOptions, classpath);
             addSourceFiles(commandLineList);
 
@@ -1326,7 +1315,8 @@ public class Groovyc extends MatchingTask {
         if (!fork && !getIncludeantruntime()) {
             throw new IllegalArgumentException("The includeAntRuntime=false option is not compatible with fork=false");
         }
-        final ClassLoader parent =
+
+        ClassLoader parent =
                 AccessController.doPrivileged(
                         new PrivilegedAction<ClassLoader>() {
                             @Override
@@ -1368,9 +1358,8 @@ public class Groovyc extends MatchingTask {
             }
         }
 
-        GroovyClassLoader loader =
-                AccessController.doPrivileged(
-                        (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(parent, configuration));
+        GroovyClassLoader loader = AccessController.doPrivileged(
+                (PrivilegedAction<GroovyClassLoader>) () -> new GroovyClassLoader(parent, configuration));
         if (!forceLookupUnnamedFiles) {
             // in normal case we don't need to do script lookups
             loader.setResourceLoader(filename -> null);
@@ -1384,7 +1373,6 @@ public class Groovyc extends MatchingTask {
 
     private void loadRegisteredScriptExtensions() {
         if (scriptExtensions.isEmpty()) {
-
             scriptExtensions.add(getScriptExtension().substring(2)); // first extension will be the one set explicitly on <groovyc>
 
             Path classpath = getClasspath() != null ? getClasspath() : new Path(getProject());
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
index 2a3f68b..d4fb8d2 100644
--- a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml
@@ -78,7 +78,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_NoFork_NoClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovyTest2.java">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1"/>
@@ -86,7 +86,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_NoFork_WithGroovyClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java"
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java"
                  classpathref="groovyMaterials">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
@@ -104,7 +104,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_NoFork_WithJavaClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1" classpathref="groovyMaterials"/>
@@ -112,7 +112,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_NoFork_WithBothClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java"
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java"
                  classpathref="groovyMaterials">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
@@ -121,7 +121,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_ForkGroovy_NoClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java" fork="true">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java" fork="true">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1"/>
@@ -129,8 +129,8 @@
     </target>
 
     <target name="GroovycTest1_Joint_ForkGroovy_WithGroovyClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java"
-                 classpathref="groovyMaterials" fork="true">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java" fork="true"
+                 classpathref="groovyMaterials">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1"/>
@@ -138,7 +138,7 @@
     </target>
 
     <target name="GroovycTest1_Joint_ForkGroovy_WithJavaClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java" fork="true">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java" fork="true">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1" classpathref="groovyMaterials"/>
@@ -146,8 +146,8 @@
     </target>
 
     <target name="GroovycTest1_Joint_ForkGroovy_WithBothClasspath">
-        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,Groovyc2.java"
-                 classpathref="groovyMaterials" fork="true">
+        <groovyc srcdir="${srcPath}" destdir="${destPath}" includes="GroovycTest1.groovy,GroovycTest2.java" fork="true"
+                 classpathref="groovyMaterials">
             <javac source="${javaVersion}" target="${javaVersion}" debug="true"/>
         </groovyc>
         <java classname="org.codehaus.groovy.ant.GroovycTest1" classpathref="groovyMaterials"/>
@@ -191,7 +191,9 @@
         <delete quiet="true">
             <fileset dir="${destPath}/org/codehaus/groovy/ant">
                 <include name="GroovycTest1*.class"/>
+                <include name="GroovycTest2*.class"/>
                 <include name="IncorrectGenericsUsage.class"/>
+                <include name="MakesExternalReference.class"/>
             </fileset>
         </delete>
     </target>
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest2.java b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest2.java
index d7ef1d5..ff990c2 100644
--- a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest2.java
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovycTest2.java
@@ -24,14 +24,14 @@ import java.io.IOException;
 
 class GroovycTest2 {
     static void main(String[] args) throws IOException {
-        File f = new File("target/classes/test/org/codehaus/groovy/ant/GroovycTest2_Result.txt");
-        FileOutputStream fout = new FileOutputStream(f);
+        FileOutputStream fout = new FileOutputStream(
+            new File("target/classes/groovy/test/org/codehaus/groovy/ant/GroovycTest2_Result.txt"));
         try {
             fout.write("OK.".getBytes());
         } finally {
             try {
                 fout.close();
-            } catch (IOException ioe) {
+            } catch (IOException ignore) {
             }
         }
     }
diff --git a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
index e0f25dc..cb60c5d 100644
--- a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
+++ b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovycTest.java
@@ -30,6 +30,8 @@ import java.io.FileOutputStream;
 import java.io.FileReader;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.net.URISyntaxException;
+import java.nio.file.Paths;
 import java.util.regex.Pattern;
 
 /**
@@ -40,17 +42,16 @@ import java.util.regex.Pattern;
  * matter as the tests remove all class files that should not pre-exist from this directory at each step.
  */
 public class GroovycTest extends GroovyTestCase {
-    private final String classDirectory = "target/classes/groovy/test/org/codehaus/groovy/ant/";
     private final File antFile = new File("src/test-resources/org/codehaus/groovy/ant/GroovycTest.xml");
     private Project project;
     private static boolean warned = false;
 
-    protected void setUp() throws Exception {
-        super.setUp(); //  Potentially throws Exception.
+    protected void setUp() {
         project = new Project();
         project.init();
         ProjectHelper.getProjectHelper().parse(project, antFile);
         project.executeTarget("clean");
+
         String altJavaHome = System.getProperty("java.home");
         if (altJavaHome.lastIndexOf("jre") >= 0) {
             altJavaHome = altJavaHome.substring(0, altJavaHome.lastIndexOf("jre"));
@@ -62,32 +63,40 @@ public class GroovycTest extends GroovyTestCase {
             if (altFile.exists()) {
                 project.setProperty("alt.java.home", altJavaHome);
             }
-        } catch (Exception e) {
-            // could be security, io, etc.  Ignore it.
+        } catch (Exception ignore) {
+            // could be security, io, etc.
             // End result is as if .exists() returned null
         }
     }
 
+    private String getTargetDirectory() {
+        try {
+            return Paths.get(getClass().getResource(".").toURI()).toString() + File.separator;
+        } catch (URISyntaxException e) {
+            throw new RuntimeException(e);
+        }
+    }
+
     private void ensureNotPresent(final String classname) {
-        if (!(new File(classDirectory + "GroovycTest.class")).exists()) {
+        if (!(new File(getTargetDirectory() + getClass().getSimpleName() + ".class")).exists()) {
             fail("Class file for GroovycTest does not exist and should.");
         }
-        if ((new File(classDirectory + classname + ".class")).exists()) {
+        if ((new File(getTargetDirectory() + classname + ".class")).exists()) {
             fail("Class file for " + classname + " already exists and shouldn't.");
         }
     }
 
     private void ensurePresent(final String classname) {
-        if (!(new File(classDirectory + classname + ".class")).exists()) {
+        if (!(new File(getTargetDirectory() + classname + ".class")).exists()) {
             fail("Class file for " + classname + " does not exist and should.");
         }
     }
 
     private void ensureResultOK(final String classname) {
-        if (!(new File(classDirectory + classname + ".class")).exists()) {
+        if (!(new File(getTargetDirectory() + classname + ".class")).exists()) {
             fail("Class file for " + classname + " does not exist and should.");
         }
-        final File result = new File(classDirectory + classname + "_Result.txt");
+        final File result = new File(getTargetDirectory() + classname + "_Result.txt");
         final char[] buffer = new char[10];
         FileReader fr = null;
         try {
@@ -153,23 +162,23 @@ public class GroovycTest extends GroovyTestCase {
     public void testGroovyc_Joint_NoFork_NestedCompilerArg_WithGroovyClasspath() {
         // capture ant's output so we can verify the effect of passing compilerarg to javac
         ByteArrayOutputStream allOutput = new ByteArrayOutputStream();
-        PrintStream out = new PrintStream(allOutput);
-        PrintStream origOut = System.out;
-        System.setOut(out);
-
-        ensureNotPresent("IncorrectGenericsUsage");
-        project.executeTarget("Groovyc_Joint_NoFork_NestedCompilerArg_WithGroovyClasspath");
-        ensurePresent("IncorrectGenericsUsage");
 
-        String antOutput = allOutput.toString();
-        antOutput = adjustOutputToHandleOpenJDKJavacOutputDifference(antOutput);
-        System.setOut(origOut);
-
-        // verify if passing -Xlint in compilerarg had its effect
-        Pattern p = Pattern.compile(".*?found[ ]*:[ ]*java.util.ArrayList.*", Pattern.DOTALL);
-        assertTrue("Expected line 1 not found in ant output", p.matcher(antOutput).matches());
-        p = Pattern.compile(".*?required[ ]*:[ ]*java.util.ArrayList<java.lang.String>.*", Pattern.DOTALL);
-        assertTrue("Expected line 2 not found in ant output", p.matcher(antOutput).matches());
+        PrintStream out = System.out;
+        System.setOut(new PrintStream(allOutput));
+        try {
+            ensureNotPresent("IncorrectGenericsUsage");
+            project.executeTarget("Groovyc_Joint_NoFork_NestedCompilerArg_WithGroovyClasspath");
+            ensurePresent("IncorrectGenericsUsage");
+
+            String antOutput = adjustOutputToHandleOpenJDKJavacOutputDifference(allOutput.toString());
+            // verify if passing -Xlint in compilerarg had its effect
+            Pattern p = Pattern.compile(".*?found[ ]*:[ ]*java.util.ArrayList.*", Pattern.DOTALL);
+            assertTrue("Expected line 1 not found in ant output", p.matcher(antOutput).matches());
+            p = Pattern.compile(".*?required[ ]*:[ ]*java.util.ArrayList<java.lang.String>.*", Pattern.DOTALL);
+            assertTrue("Expected line 2 not found in ant output", p.matcher(antOutput).matches());
+        } finally {
+            System.setOut(out);
+        }
     }
 
     /**
@@ -281,5 +290,4 @@ public class GroovycTest extends GroovyTestCase {
             badGroovy.delete();
         }
     }
-
 }


[groovy] 03/18: add notes on joint compiler arguments and refactor minor stuff

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 7b86d85c14e50021f8f0dd67bf278b3498625afe
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Tue Nov 12 17:20:59 2019 -0600

    add notes on joint compiler arguments and refactor minor stuff
    
    (cherry picked from commit 6aff769ed697218229fa12f6bbf3e4903f725218)
---
 .../groovy/tools/javac/JavacJavaCompiler.java      | 79 ++++++++------------
 .../main/java/org/codehaus/groovy/ant/Groovyc.java | 83 ++++++++++++++--------
 2 files changed, 83 insertions(+), 79 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java b/src/main/java/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java
index 4024f42..cb35ad2 100644
--- a/src/main/java/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java
+++ b/src/main/java/org/codehaus/groovy/tools/javac/JavacJavaCompiler.java
@@ -27,10 +27,6 @@ import org.codehaus.groovy.control.messages.ExceptionMessage;
 import org.codehaus.groovy.control.messages.SimpleMessage;
 import org.codehaus.groovy.runtime.DefaultGroovyMethods;
 
-import javax.tools.JavaCompiler.CompilationTask;
-import javax.tools.JavaFileObject;
-import javax.tools.StandardJavaFileManager;
-import javax.tools.ToolProvider;
 import java.io.File;
 import java.io.IOException;
 import java.net.URISyntaxException;
@@ -41,9 +37,7 @@ import java.security.AccessController;
 import java.security.CodeSource;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
-import java.util.LinkedList;
 import java.util.List;
 import java.util.Locale;
 import java.util.Map;
@@ -51,7 +45,7 @@ import java.util.Set;
 import java.util.stream.Collectors;
 
 public class JavacJavaCompiler implements JavaCompiler {
-    private static final String[] EMPTY_STRING_ARRAY = new String[0];
+
     private static final Locale DEFAULT_LOCALE = Locale.ENGLISH;
     private final CompilerConfiguration config;
     private final Charset charset;
@@ -62,7 +56,7 @@ public class JavacJavaCompiler implements JavaCompiler {
     }
 
     public void compile(List<String> files, CompilationUnit cu) {
-        String[] javacParameters = makeParameters(cu.getClassLoader());
+        List<String> javacParameters = makeParameters(cu.getClassLoader());
         StringBuilderWriter javacOutput = new StringBuilderWriter();
         int javacReturnValue = 0;
         try {
@@ -78,7 +72,6 @@ public class JavacJavaCompiler implements JavaCompiler {
                 javacReturnValue = 1;
                 cu.getErrorCollector().addFatalError(new ExceptionMessage(e, true, cu));
             }
-
         } catch (Exception e) {
             cu.getErrorCollector().addFatalError(new ExceptionMessage(e, true, cu));
         }
@@ -95,23 +88,21 @@ public class JavacJavaCompiler implements JavaCompiler {
         }
     }
 
-    private boolean doCompileWithSystemJavaCompiler(CompilationUnit cu, List<String> files, String[] javacParameters, StringBuilderWriter javacOutput) throws IOException {
-        javax.tools.JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
-        try (StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, DEFAULT_LOCALE, charset)) {
-            final Set<JavaFileObject> compilationUnitSet = cu.getJavaCompilationUnitSet(); // java stubs already added
+    private boolean doCompileWithSystemJavaCompiler(CompilationUnit cu, List<String> files, List<String> javacParameters, StringBuilderWriter javacOutput) throws IOException {
+        javax.tools.JavaCompiler compiler = javax.tools.ToolProvider.getSystemJavaCompiler();
+        try (javax.tools.StandardJavaFileManager fileManager = compiler.getStandardFileManager(null, DEFAULT_LOCALE, charset)) {
+            Set<javax.tools.JavaFileObject> compilationUnitSet = cu.getJavaCompilationUnitSet(); // java stubs already added
 
             // add java source files to compile
             fileManager.getJavaFileObjectsFromFiles(
-                    files.stream()
-                            .map(File::new)
-                            .collect(Collectors.toList())
+                    files.stream().map(File::new).collect(Collectors.toList())
             ).forEach(compilationUnitSet::add);
 
-            CompilationTask compilationTask = compiler.getTask(
+            javax.tools.JavaCompiler.CompilationTask compilationTask = compiler.getTask(
                     javacOutput,
                     fileManager,
                     null,
-                    Arrays.asList(javacParameters),
+                    javacParameters,
                     Collections.emptyList(),
                     compilationUnitSet
             );
@@ -133,72 +124,64 @@ public class JavacJavaCompiler implements JavaCompiler {
         cu.getErrorCollector().addFatalError(new SimpleMessage(header, cu));
     }
 
-    private String[] makeParameters(GroovyClassLoader parentClassLoader) {
-        Map options = config.getJointCompilationOptions();
-        LinkedList<String> paras = new LinkedList<String>();
+    private List<String> makeParameters(GroovyClassLoader parentClassLoader) {
+        Map<String, Object> options = config.getJointCompilationOptions();
+        List<String> params = new ArrayList<>();
 
         File target = config.getTargetDirectory();
         if (target == null) target = new File(".");
 
-        // defaults
-        paras.add("-d");
-        paras.add(target.getAbsolutePath());
+        params.add("-d");
+        params.add(target.getAbsolutePath());
 
-        // add flags
         String[] flags = (String[]) options.get("flags");
         if (flags != null) {
             for (String flag : flags) {
-                paras.add('-' + flag);
+                params.add("-" + flag);
             }
         }
 
         boolean hadClasspath = false;
-        // add namedValues
         String[] namedValues = (String[]) options.get("namedValues");
         if (namedValues != null) {
-            for (int i = 0; i < namedValues.length; i += 2) {
+            for (int i = 0, n = namedValues.length; i < n; i += 2) {
                 String name = namedValues[i];
                 if (name.equals("classpath")) hadClasspath = true;
-                paras.add('-' + name);
-                paras.add(namedValues[i + 1]);
+                params.add("-" + name);
+                params.add(namedValues[i + 1]);
             }
         }
 
         // append classpath if not already defined
         if (!hadClasspath) {
             // add all classpaths that compilation unit sees
-            List<String> paths = new ArrayList<String>(config.getClasspath());
-            ClassLoader cl = parentClassLoader;
-            while (cl != null) {
-                if (cl instanceof URLClassLoader) {
-                    for (URL u : ((URLClassLoader) cl).getURLs()) {
+            List<String> paths = new ArrayList<>(config.getClasspath());
+            ClassLoader loader = parentClassLoader;
+            while (loader != null) {
+                if (loader instanceof URLClassLoader) {
+                    for (URL u : ((URLClassLoader) loader).getURLs()) {
                         try {
                             paths.add(new File(u.toURI()).getPath());
-                        } catch (URISyntaxException e) {
-                            // ignore it
+                        } catch (URISyntaxException ignore) {
                         }
                     }
                 }
-                cl = cl.getParent();
+                loader = loader.getParent();
             }
 
             try {
-                CodeSource codeSource =
-                        AccessController.doPrivileged(
-                                (PrivilegedAction<CodeSource>) () -> GroovyObject.class.getProtectionDomain().getCodeSource()
-                        );
+                CodeSource codeSource = AccessController.doPrivileged(
+                        (PrivilegedAction<CodeSource>) () -> GroovyObject.class.getProtectionDomain().getCodeSource());
                 if (codeSource != null) {
                     paths.add(new File(codeSource.getLocation().toURI()).getPath());
                 }
-            } catch (URISyntaxException e) {
-                // ignore it
+            } catch (URISyntaxException ignore) {
             }
 
-            paras.add("-classpath");
-            paras.add(DefaultGroovyMethods.join((Iterable) paths, File.pathSeparator));
+            params.add("-classpath");
+            params.add(DefaultGroovyMethods.join((Iterable<String>) paths, File.pathSeparator));
         }
 
-        return paras.toArray(EMPTY_STRING_ARRAY);
+        return params;
     }
-
 }
diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
index a7d41af..a255703 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovyc.java
@@ -52,7 +52,7 @@ import java.nio.charset.Charset;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
 import java.util.ArrayList;
-import java.util.Enumeration;
+import java.util.Collections;
 import java.util.LinkedHashSet;
 import java.util.List;
 import java.util.Map;
@@ -959,47 +959,68 @@ public class Groovyc extends MatchingTask {
         }
     }
 
+    /**
+     * If {@code groovyc} task includes a nested {@code javac} task, check for
+     * shareable configuration.  {@code FileSystemCompiler} supports several
+     * command-line arguments for configuring joint compilation:
+     * <ul>
+     * <li><tt>-j</tt> enables joint compile
+     * <li><tt>-F</tt> is used to pass flags
+     * <li><tt>-J</tt> is used to pass name=value pairs
+     * </ul>
+     * Joint compilation options are transferred from {@link FileSystemCompiler}
+     * to {@link CompilerConfiguration}'s jointCompileOptions property.  Flags
+     * are saved to key "flags" (with the inclusion of "parameters" if enabled
+     * on groovyc), pairs are saved to key "namedValues" and the key "memStub"
+     * may also be set to {@link Boolean#TRUE} to influence joint compilation.
+     *
+     * @see org.codehaus.groovy.tools.javac.JavacJavaCompiler
+     * @see javax.tools.JavaCompiler
+     */
     private List<String> extractJointOptions(Path classpath) {
         List<String> jointOptions = new ArrayList<>();
         if (!jointCompilation) return jointOptions;
 
-        // extract joint options, some get pushed up...
+        // map "debug" and "debuglevel" to "-Fg"
+        if (javac.getDebug()) {
+            jointOptions.add("-Fg" + Optional.ofNullable(javac.getDebugLevel()).map(level -> ":" + level).orElse(""));
+        } else {
+            jointOptions.add("-Fg:none");
+        }
+
+        // map "verbose" to "-Fverbose"
+        if (javac.getVerbose()) {
+            jointOptions.add("-Fverbose");
+        }
+
         RuntimeConfigurable rc = javac.getRuntimeConfigurableWrapper();
+
         for (Map.Entry<String, Object> e : rc.getAttributeMap().entrySet()) {
             String key = e.getKey();
-            String value = getProject().replaceProperties(e.getValue().toString());
-            if (key.contains("debug")) {
-                String level = "";
-                if (javac.getDebugLevel() != null) {
-                    level = ":" + javac.getDebugLevel();
-                }
-                jointOptions.add("-Fg" + level);
-            } else if (key.contains("debugLevel")) {
-                // ignore, taken care of in debug
-            } else if (key.contains("verbose")) {
-                // false is default, so something to do only in true case
-                if ("on".equalsIgnoreCase(value) || "true".equalsIgnoreCase(value) || "yes".equalsIgnoreCase(value))
-                    jointOptions.add("-F" + key);
+            if (key.contains("encoding")
+                    || key.contains("extdirs")
+                    || key.contains("depend")
+                    || key.contains("source")
+                    || key.contains("target")) {
+                // map "encoding", etc. to "-Jkey=val"
+                jointOptions.add("-J" + key + "=" + getProject().replaceProperties(e.getValue().toString()));
+
             } else if (key.contains("classpath")) {
-                classpath.add(javac.getClasspath());
-            } else if ((key.contains("depend"))
-                    || (key.contains("extdirs"))
-                    || (key.contains("encoding"))
-                    || (key.contains("source"))
-                    || (key.contains("target"))
-                    || (key.contains("verbose"))) { // already handling verbose but pass on too
-                jointOptions.add("-J" + key + "=" + value);
-            } else {
-                log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored");
+                if (key.startsWith("boot")) {
+                    // TODO: javac.getBootclasspath()
+                } else {
+                    classpath.add(javac.getClasspath());
+                }
+            } else if (!key.contains("debug") && !key.contains("verbose")) {
+                log.warn("The option " + key + " cannot be set on the contained <javac> element. The option will be ignored.");
             }
-            // TODO includes? excludes?
+            // TODO: modulepath, modulepathref, modulesourcepath, modulesourcepathref, upgrademodulepath, upgrademodulepathref
+            // TODO: release, deprecation, failonerror, nowarn, tempdir, nativeheaderdir, includes(file)? excludes(file)?
         }
 
-        // ant's <javac> supports nested <compilerarg value=""> elements (there can be multiple of them)
-        // for additional options to be passed to javac.
-        Enumeration<RuntimeConfigurable> children = rc.getChildren();
-        while (children.hasMoreElements()) {
-            RuntimeConfigurable childrc = children.nextElement();
+        // Ant's <javac> supports nested <compilerarg value=""> elements (there
+        // can be multiple of them) for additional options to be passed to javac.
+        for (RuntimeConfigurable childrc : Collections.list(rc.getChildren())) {
             if (childrc.getElementTag().equals("compilerarg")) {
                 for (Map.Entry<String, Object> e : childrc.getAttributeMap().entrySet()) {
                     String key = e.getKey();


[groovy] 07/18: GROOVY-8310: STC: check closure return type when method type has generic

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 3401515ee63b59e4e0724a0b310b4ba276e82e70
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sun Nov 10 04:42:14 2019 -0600

    GROOVY-8310: STC: check closure return type when method type has generic
    
    (cherry picked from commit 4fb4dff8271fd4d0b6fa5c89f486cdd2bf4ca206)
---
 .../groovy/runtime/DefaultGroovyMethods.java       |  16 +--
 .../transform/stc/StaticTypeCheckingVisitor.java   |  21 ++--
 src/test/groovy/bugs/Groovy8310.groovy             | 118 +++++++++++++++++++++
 .../{Groovy8439Bug.groovy => Groovy8439.groovy}    |  51 +++++----
 4 files changed, 164 insertions(+), 42 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
index d5d0d44..1b2b18b 100644
--- a/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
+++ b/src/main/java/org/codehaus/groovy/runtime/DefaultGroovyMethods.java
@@ -3762,7 +3762,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @since 1.8.1
      */
     @Deprecated
-    public static <T,E> List<T> collectMany(Collection<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> List<T> collectMany(Collection<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends Collection<? extends T>> projection) {
         return collectMany((Iterable)self, projection);
     }
 
@@ -3772,7 +3772,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @since 1.8.5
      */
     @Deprecated
-    public static <T,E> Collection<T> collectMany(Collection<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> Collection<T> collectMany(Collection<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends Collection<? extends T>> projection) {
         return collectMany((Iterable)self, collector, projection);
     }
 
@@ -3800,7 +3800,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @see #sum(java.util.Collection, groovy.lang.Closure)
      * @since 2.2.0
      */
-    public static <T,E> List<T> collectMany(Iterable<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> List<T> collectMany(Iterable<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends Collection<? extends T>> projection) {
         return (List<T>) collectMany(self, new ArrayList<T>(), projection);
     }
 
@@ -3824,7 +3824,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @return the collector with the projected collections concatenated (flattened) into it
      * @since 2.2.0
      */
-    public static <T,E> Collection<T> collectMany(Iterable<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> Collection<T> collectMany(Iterable<E> self, Collection<T> collector, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends Collection<? extends T>> projection) {
         for (E next : self) {
             collector.addAll(projection.call(next));
         }
@@ -3847,7 +3847,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @return the collector with the projected collections concatenated (flattened) to it
      * @since 1.8.8
      */
-    public static <T,K,V> Collection<T> collectMany(Map<K, V> self, Collection<T> collector, @ClosureParams(MapEntryOrKeyValue.class) Closure<Collection<? extends T>> projection) {
+    public static <T,K,V> Collection<T> collectMany(Map<K, V> self, Collection<T> collector, @ClosureParams(MapEntryOrKeyValue.class) Closure<? extends Collection<? extends T>> projection) {
         for (Map.Entry<K, V> entry : self.entrySet()) {
             collector.addAll(callClosureForMapEntry(projection, entry));
         }
@@ -3869,7 +3869,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @return the collector with the projected collections concatenated (flattened) to it
      * @since 1.8.8
      */
-    public static <T,K,V> Collection<T> collectMany(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<Collection<? extends T>> projection) {
+    public static <T,K,V> Collection<T> collectMany(Map<K, V> self, @ClosureParams(MapEntryOrKeyValue.class) Closure<? extends Collection<? extends T>> projection) {
         return collectMany(self, new ArrayList<T>(), projection);
     }
 
@@ -3889,7 +3889,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @since 1.8.1
      */
     @SuppressWarnings("unchecked")
-    public static <T,E> List<T> collectMany(E[] self, @ClosureParams(FirstParam.Component.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> List<T> collectMany(E[] self, @ClosureParams(FirstParam.Component.class) Closure<? extends Collection<? extends T>> projection) {
         return collectMany((Iterable<E>)toList(self), projection);
     }
 
@@ -3909,7 +3909,7 @@ public class DefaultGroovyMethods extends DefaultGroovyMethodsSupport {
      * @since 1.8.1
      */
     @SuppressWarnings("unchecked")
-    public static <T,E> List<T> collectMany(Iterator<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<Collection<? extends T>> projection) {
+    public static <T,E> List<T> collectMany(Iterator<E> self, @ClosureParams(FirstParam.FirstGenericType.class) Closure<? extends Collection<? extends T>> projection) {
         return collectMany((Iterable)toList(self), projection);
     }
 
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 0447f9f..5b803f0 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -3531,17 +3531,16 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
             if (!callArgsVisited) {
                 visitMethodCallArguments(receiver, argumentList, true, target);
-                // GROOVY-6219
-                if (target != null) {
-                    List<Expression> argExpressions = argumentList.getExpressions();
-                    Parameter[] parameters = target.getParameters();
-                    for (int i = 0; i < argExpressions.size() && i < parameters.length; i += 1) {
-                        Expression arg = argExpressions.get(i);
-                        ClassNode aType = getType(arg), pType = parameters[i].getType();
-                        if (CLOSURE_TYPE.equals(aType) && CLOSURE_TYPE.equals(pType) && !isAssignableTo(aType, pType)) {
-                            addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call);
-                            call.removeNodeMetaData(DIRECT_METHOD_CALL_TARGET);
-                        }
+            }
+            if (target != null) {
+                List<Expression> argExpressions = argumentList.getExpressions();
+                Parameter[] parameters = target.getParameters();
+                for (int i = 0; i < argExpressions.size() && i < parameters.length; i += 1) {
+                    Expression arg = argExpressions.get(i);
+                    ClassNode aType = getType(arg), pType = parameters[i].getType();
+                    if (CLOSURE_TYPE.equals(aType) && CLOSURE_TYPE.equals(pType) && !isAssignableTo(aType, pType)) {
+                        addNoMatchingMethodError(receiver, name, getArgumentTypes(argumentList), call);
+                        call.removeNodeMetaData(DIRECT_METHOD_CALL_TARGET);
                     }
                 }
             }
diff --git a/src/test/groovy/bugs/Groovy8310.groovy b/src/test/groovy/bugs/Groovy8310.groovy
new file mode 100644
index 0000000..838566f
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8310.groovy
@@ -0,0 +1,118 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package groovy.bugs
+
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+import static groovy.test.GroovyAssert.shouldFail
+
+@CompileStatic
+final class Groovy8310 {
+
+    @Test
+    void testClosureReturnType1() {
+        def err = shouldFail '''
+            def bar(Closure<Collection<Integer>> block) {
+                block()
+            }
+
+            @groovy.transform.CompileStatic
+            def use() {
+                bar {
+                    [1]
+                }
+            }
+        '''
+
+        assert err =~ /Cannot find matching method \w+#bar\(groovy.lang.Closure <java.util.List>\)/
+    }
+
+    @Test
+    void testClosureReturnType2() {
+        def err = shouldFail '''
+            public <T> T bar(Closure<Collection<Integer>> block) {
+                block()
+            }
+
+            @groovy.transform.CompileStatic
+            def use() {
+                bar {
+                    [1]
+                }
+            }
+        '''
+
+        assert err =~ /Cannot find matching method \w+#bar\(groovy.lang.Closure <java.util.List>\)/
+    }
+
+    @Test
+    void testClosureReturnType3() {
+        assertScript '''
+            public <T> T bar(Closure<? extends Collection<Integer>> block) {
+                block()
+            }
+
+            @groovy.transform.CompileStatic
+            def use() {
+                bar {
+                    [1]
+                }
+            }
+
+            assert use() == [1]
+        '''
+    }
+
+    @Test
+    void testClosureReturnType4() {
+        assertScript '''
+            public <T> T bar(Closure<Collection<Integer>> block) {
+                block()
+            }
+
+            @groovy.transform.CompileStatic
+            def use() {
+                bar {
+                    (Collection<Integer>) [1]
+                }
+            }
+
+            assert use() == [1]
+        '''
+    }
+
+    @Test
+    void testClosureReturnType5() {
+        assertScript '''
+            public <T> T bar(Closure<Collection<Integer>> block) {
+                block()
+            }
+
+            def use() {
+                bar {
+                    [1] as Collection<Integer>
+                }
+            }
+
+            assert use() == [1]
+        '''
+    }
+}
diff --git a/src/test/groovy/bugs/Groovy8439Bug.groovy b/src/test/groovy/bugs/Groovy8439.groovy
similarity index 51%
rename from src/test/groovy/bugs/Groovy8439Bug.groovy
rename to src/test/groovy/bugs/Groovy8439.groovy
index e01c78e..a7d05a9 100644
--- a/src/test/groovy/bugs/Groovy8439Bug.groovy
+++ b/src/test/groovy/bugs/Groovy8439.groovy
@@ -18,34 +18,39 @@
  */
 package groovy.bugs
 
-import groovy.test.GroovyTestCase
+import groovy.transform.CompileStatic
+import org.junit.Test
 
-class Groovy8439Bug extends GroovyTestCase {
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy8439 {
+
+    @Test
     void testSTCGenerics() {
         assertScript '''
-        import groovy.transform.CompileStatic
-        @CompileStatic
-        class Test<T extends Task> {
-            static def something(Task task, Collection<BaseVariant> variants) {
-                variants.collectMany { it.sourceFolders }.collect { ConfigurableFileTree tree ->
-                    task.getBuildDir().toPath().relativize(tree.dir.toPath()).toString() + File.separator
+            @groovy.transform.CompileStatic
+            class Test<T extends Task> {
+                static def something(Task task, Collection<BaseVariant> variants) {
+                    variants.collectMany { it.sourceFolders }.collect { ConfigurableFileTree tree ->
+                        task.getBuildDir().toPath().relativize(tree.dir.toPath()).toString() + File.separator
+                    }
                 }
             }
-        }
-        
-        interface BaseVariant {
-            List<ConfigurableFileTree> getSourceFolders()
-        }
-        
-        interface ConfigurableFileTree {
-            File getDir()
-        }
-        
-        interface Task {
-            File getBuildDir()
-        }
-        
-        Test.something(null, [])
+
+            interface BaseVariant {
+                List<ConfigurableFileTree> getSourceFolders()
+            }
+
+            interface ConfigurableFileTree {
+                File getDir()
+            }
+
+            interface Task {
+                File getBuildDir()
+            }
+
+            Test.something(null, [])
         '''
     }
 }


[groovy] 09/18: Trivial refactoring: Remove redundant type cast

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 7c35699d29a533577ed37226a9043f9f9ece72e6
Author: Daniel.Sun <re...@hotmail.com>
AuthorDate: Fri Nov 15 15:49:58 2019 +0800

    Trivial refactoring: Remove redundant type cast
    
    (cherry picked from commit 102ceaa5171b4136ba5395962208ac1805acb6ed)
---
 .../transform/stc/StaticTypeCheckingVisitor.java   | 28 +++++++++++-----------
 1 file changed, 14 insertions(+), 14 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 a64a53e..e29b5c4 100644
--- a/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
+++ b/src/main/java/org/codehaus/groovy/transform/stc/StaticTypeCheckingVisitor.java
@@ -484,7 +484,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
     @Override
     public void visitClassExpression(final ClassExpression expression) {
         super.visitClassExpression(expression);
-        ClassNode cn = (ClassNode) expression.getNodeMetaData(INFERRED_TYPE);
+        ClassNode cn = expression.getNodeMetaData(INFERRED_TYPE);
         if (cn == null) {
             storeType(expression, getType(expression));
         }
@@ -636,7 +636,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     // IMPLICIT_RECEIVER is handled elsewhere
                     // however other access needs to be fixed for private access
                     if (vexp.getNodeMetaData(IMPLICIT_RECEIVER) == null) {
-                        ClassNode owner = (ClassNode) vexp.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
+                        ClassNode owner = vexp.getNodeMetaData(StaticCompilationMetadataKeys.PROPERTY_OWNER);
                         if (owner != null) {
                             FieldNode veFieldNode = owner.getField(vexp.getName());
                             if (veFieldNode != null) {
@@ -836,7 +836,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             if (op == KEYWORD_IN || op == COMPARE_NOT_IN) {
                 // in case of the "in" operator, the receiver and the arguments are reversed
                 // so we use the reversedExpression and get the target method from it
-                storeTargetMethod(expression, (MethodNode) reversedBinaryExpression.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
+                storeTargetMethod(expression, reversedBinaryExpression.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
             } else if (op == LEFT_SQUARE_BRACKET
                     && leftExpression instanceof VariableExpression
                     && leftExpression.getNodeMetaData(INFERRED_TYPE) == null) {
@@ -2179,7 +2179,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 varX("{source}", source)
         );
         virtualDecl.visit(this);
-        ClassNode newlyInferred = (ClassNode) virtualDecl.getNodeMetaData(INFERRED_TYPE);
+        ClassNode newlyInferred = virtualDecl.getNodeMetaData(INFERRED_TYPE);
 
         return !missesGenericsTypes(newlyInferred) ? newlyInferred : null;
     }
@@ -2469,7 +2469,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             return;
         }
         if (!extension.beforeVisitMethod(node)) {
-            ErrorCollector collector = (ErrorCollector) node.getNodeMetaData(ERROR_COLLECTOR);
+            ErrorCollector collector = node.getNodeMetaData(ERROR_COLLECTOR);
             if (collector != null) {
                 typeCheckingContext.getErrorCollector().addCollectorContents(collector);
             } else {
@@ -2625,7 +2625,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                     addAmbiguousErrorMessage(mn, name, args, call);
                 }
                 if (!callArgsVisited) {
-                    visitMethodCallArguments(receiver, argumentList, true, (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
+                    visitMethodCallArguments(receiver, argumentList, true, call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
                 }
             }
         } finally {
@@ -2853,7 +2853,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
         // to the corresponding parameters of the SAM type method
         MethodNode methodForSAM = findSAM(classForSAM);
         ClassNode[] parameterTypesForSAM = extractTypesFromParameters(methodForSAM.getParameters());
-        ClassNode[] blockParameterTypes = (ClassNode[]) openBlock.getNodeMetaData(CLOSURE_ARGUMENTS);
+        ClassNode[] blockParameterTypes = openBlock.getNodeMetaData(CLOSURE_ARGUMENTS);
         if (blockParameterTypes == null) {
             Parameter[] p = openBlock.getParameters();
             if (p == null) {
@@ -3310,7 +3310,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 listNode.setGenericsTypes(new GenericsType[]{new GenericsType(wrapTypeIfNecessary(subcallReturnType))});
                 storeType(call, listNode);
                 // store target method
-                storeTargetMethod(call, (MethodNode) subcall.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
+                storeTargetMethod(call, subcall.getNodeMetaData(DIRECT_METHOD_CALL_TARGET));
                 typeCheckingContext.popEnclosingMethodCall();
                 return;
             }
@@ -3528,7 +3528,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             }
 
             // now that a method has been chosen, we are allowed to visit the closures
-            MethodNode target = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+            MethodNode target = call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
             if (!callArgsVisited) {
                 visitMethodCallArguments(receiver, argumentList, true, target);
             }
@@ -4197,7 +4197,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             // o = new Object() // and eventually an object !
             // in that case, the INFERRED_TYPE corresponds to the current inferred type, while
             // DECLARATION_INFERRED_TYPE is the type which should be used for the initial type declaration
-            ClassNode oldDIT = (ClassNode) exp.getNodeMetaData(DECLARATION_INFERRED_TYPE);
+            ClassNode oldDIT = exp.getNodeMetaData(DECLARATION_INFERRED_TYPE);
             if (oldDIT != null) {
                 exp.putNodeMetaData(DECLARATION_INFERRED_TYPE, cn == null ? oldDIT : lowestUpperBound(oldDIT, cn));
             } else {
@@ -4902,7 +4902,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                 return result;
             }
         } else if (exp instanceof MethodCall) {
-            MethodNode target = (MethodNode) exp.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+            MethodNode target = exp.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
             if (target != null) {
                 return getType(target);
             }
@@ -4912,7 +4912,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
 
     private ClassNode getTypeFromClosureArguments(Parameter parameter, TypeCheckingContext.EnclosingClosure enclosingClosure) {
         ClosureExpression closureExpression = enclosingClosure.getClosureExpression();
-        ClassNode[] closureParamTypes = (ClassNode[]) closureExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
+        ClassNode[] closureParamTypes = closureExpression.getNodeMetaData(CLOSURE_ARGUMENTS);
         if (closureParamTypes == null) return null;
         final Parameter[] parameters = closureExpression.getParameters();
         String name = parameter.getName();
@@ -5570,7 +5570,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
                         List<ClassNode> classNodes = typeCheckingContext.closureSharedVariablesAssignmentTypes.get(var);
                         if (classNodes != null && classNodes.size() > 1) {
                             ClassNode lub = lowestUpperBound(classNodes);
-                            MethodNode methodNode = (MethodNode) call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
+                            MethodNode methodNode = call.getNodeMetaData(DIRECT_METHOD_CALL_TARGET);
                             // we must check that such a method exists on the LUB
                             Parameter[] parameters = methodNode.getParameters();
                             ClassNode[] params = extractTypesFromParameters(parameters);
@@ -5639,7 +5639,7 @@ public class StaticTypeCheckingVisitor extends ClassCodeVisitorSupport {
             Variable var = findTargetVariable(expression);
             if (var instanceof VariableExpression) {
                 VariableExpression ve = (VariableExpression) var;
-                varOrigType.put(ve, (ClassNode) ve.getNodeMetaData(INFERRED_TYPE));
+                varOrigType.put(ve, ve.getNodeMetaData(INFERRED_TYPE));
             }
         }
     }