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

[groovy] branch GROOVY-8446 created (now 0c44aa3)

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

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


      at 0c44aa3  GROOVY-8446: syntax error for void[] or void...

This branch includes the following new commits:

     new 0c44aa3  GROOVY-8446: syntax error for void[] or void...

The 1 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.



[groovy] 01/01: GROOVY-8446: syntax error for void[] or void...

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

emilles pushed a commit to branch GROOVY-8446
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 0c44aa3ba6c936d7ff048c7855b646b7a42cb1ef
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 16 14:04:20 2019 -0600

    GROOVY-8446: syntax error for void[] or void...
    
    GROOVY-9203: anonymous inners start at "$1" for each enclosing class
---
 .../codehaus/groovy/antlr/AntlrParserPlugin.java   | 425 +++++++++------------
 .../java/org/codehaus/groovy/ast/ModuleNode.java   |  27 +-
 .../{Groovy7973Bug.groovy => Groovy7973.groovy}    |  34 +-
 src/test/groovy/bugs/Groovy8446.groovy             |  59 +++
 4 files changed, 272 insertions(+), 273 deletions(-)

diff --git a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
index 4b44eae..8a18703 100644
--- a/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
+++ b/src/main/java/org/codehaus/groovy/antlr/AntlrParserPlugin.java
@@ -127,20 +127,21 @@ 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.
  */
 public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, GroovyTokenTypes {
 
     private static class AnonymousInnerClassCarrier extends Expression {
         ClassNode innerClass;
 
+        @Override
         public Expression transformExpression(ExpressionTransformer transformer) {
             return null;
         }
@@ -179,16 +180,15 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected AST ast;
     private ClassNode classNode;
     private MethodNode methodNode;
-    private String[] tokenNames;
-    private int innerClassCounter = 1;
-    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 +199,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,14 +236,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     public Reduction outputAST(final SourceUnit sourceUnit, final SourceBuffer sourceBuffer) {
-        AccessController.doPrivileged(new PrivilegedAction() {
-            public Object run() {
+        return AccessController.doPrivileged(new PrivilegedAction<Reduction>() {
+            @Override
+            public Reduction run() {
                 outputASTInVariousFormsIfNeeded(sourceUnit, sourceBuffer);
                 return null;
             }
         });
-
-        return null; //new Reduction(Tpken.EOF);
     }
 
     private void outputASTInVariousFormsIfNeeded(SourceUnit sourceUnit, SourceBuffer sourceBuffer) {
@@ -253,7 +250,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
@@ -297,7 +294,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         if ("html".equals(formatProp)) {
             try {
                 PrintStream out = new PrintStream(new FileOutputStream(sourceUnit.getName() + ".html"));
-                List<VisitorAdapter> v = new ArrayList<VisitorAdapter>();
+                List<VisitorAdapter> v = new ArrayList<>();
                 v.add(new NodeAsHTMLPrinter(out, tokenNames));
                 v.add(new SourcePrinter(out, tokenNames));
                 Visitor visitors = new CompositeVisitor(v);
@@ -309,10 +306,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();
@@ -323,7 +316,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();
@@ -336,15 +328,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) {
@@ -380,10 +372,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();
         }
@@ -393,15 +383,13 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     //-------------------------------------------------------------------------
 
     protected void packageDef(AST packageDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = packageDef.getFirstChild();
         if (isType(ANNOTATIONS, node)) {
             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);
     }
 
@@ -411,7 +399,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             output.putNodeMetaData(ImportNode.class, ImportNode.class);
 
             boolean isStatic = importNode.getType() == STATIC_IMPORT;
-            List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+            List<AnnotationNode> annotations = new ArrayList<>();
 
             AST node = importNode.getFirstChild();
             if (isType(ANNOTATIONS, node)) {
@@ -419,11 +407,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);
             }
 
@@ -433,6 +423,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;
             }
 
@@ -446,14 +438,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) {
@@ -462,18 +457,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);
@@ -490,7 +489,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected void annotationDef(AST classDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = classDef.getFirstChild();
         int modifiers = Opcodes.ACC_PUBLIC;
         if (isType(MODIFIERS, node)) {
@@ -532,14 +531,12 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected void interfaceDef(AST classDef) {
-        int oldInnerClassCounter = innerClassCounter;
         innerInterfaceDef(classDef);
         classNode = null;
-        innerClassCounter = oldInnerClassCounter;
     }
 
     protected void innerInterfaceDef(AST classDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = classDef.getFirstChild();
         int modifiers = Opcodes.ACC_PUBLIC;
         if (isType(MODIFIERS, node)) {
@@ -580,21 +577,16 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         classNode.setGenericsTypes(genericsType);
         configureAST(classNode, classDef);
 
-        int oldClassCount = innerClassCounter;
-
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
         output.addClass(classNode);
 
         classNode = outerClass;
-        innerClassCounter = oldClassCount;
     }
 
     protected void classDef(AST classDef) {
-        int oldInnerClassCounter = innerClassCounter;
         innerClassDef(classDef);
         classNode = null;
-        innerClassCounter = oldInnerClassCounter;
     }
 
     private ClassNode getClassOrScript(ClassNode node) {
@@ -602,31 +594,42 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return output.getScriptClassDummy();
     }
 
+    private static int anonymousClassCount(ClassNode node) {
+        int count = 0;
+        for (Iterator<InnerClassNode> it = node.getInnerClasses(); it.hasNext();) {
+            InnerClassNode innerClass = it.next();
+            if (innerClass.isAnonymous()) {
+                count += 1;
+            }
+        }
+        return count;
+    }
+
     protected Expression anonymousInnerClassDef(AST node) {
         ClassNode oldNode = classNode;
         ClassNode outerClass = getClassOrScript(oldNode);
-        String fullName = outerClass.getName() + '$' + innerClassCounter;
-        innerClassCounter++;
+        String innerClassName = outerClass.getName() + "$" + (anonymousClassCount(outerClass) + 1);
         if (enumConstantBeingDef) {
-            classNode = new EnumConstantClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
+            classNode = new EnumConstantClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
         } else {
-            classNode = new InnerClassNode(outerClass, fullName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
+            classNode = new InnerClassNode(outerClass, innerClassName, Opcodes.ACC_PUBLIC, ClassHelper.OBJECT_TYPE);
         }
         ((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;
     }
 
     protected void innerClassDef(AST classDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
 
         if (isType(TRAIT_DEF, classDef)) {
             annotations.add(new AnnotationNode(ClassHelper.make("groovy.transform.Trait")));
@@ -687,13 +690,10 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         // have here to ensure it won't be the inner class
         output.addClass(classNode);
 
-        int oldClassCount = innerClassCounter;
-
         assertNodeType(OBJBLOCK, node);
         objectBlock(node);
 
         classNode = outerClass;
-        innerClassCounter = oldClassCount;
     }
 
     protected void objectBlock(AST objectBlock) {
@@ -750,7 +750,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected void enumDef(AST enumNode) {
         assertNodeType(ENUM_DEF, enumNode);
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
 
         AST node = enumNode.getFirstChild();
         int modifiers = Opcodes.ACC_PUBLIC;
@@ -770,10 +770,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;
@@ -784,7 +785,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected void enumConstantDef(AST node) {
         enumConstantBeingDef = true;
         assertNodeType(ENUM_CONSTANT_DEF, node);
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST element = node.getFirstChild();
         if (isType(ANNOTATIONS, element)) {
             processAnnotations(annotations, element);
@@ -861,7 +862,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected void methodDef(AST methodDef) {
         MethodNode oldNode = methodNode;
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = methodDef.getFirstChild();
 
         GenericsType[] generics = null;
@@ -910,7 +911,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
             if (isType(LITERAL_throws, node)) {
                 AST throwsNode = node.getFirstChild();
-                List<ClassNode> exceptionList = new ArrayList<ClassNode>();
+                List<ClassNode> exceptionList = new ArrayList<>();
                 throwsList(throwsNode, exceptionList);
                 exceptions = exceptionList.toArray(exceptions);
                 node = node.getNextSibling();
@@ -925,9 +926,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);
@@ -972,7 +974,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected void constructorDef(AST constructorDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = constructorDef.getFirstChild();
         int modifiers = Opcodes.ACC_PUBLIC;
         if (isType(MODIFIERS, node)) {
@@ -992,7 +994,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         ClassNode[] exceptions = ClassNode.EMPTY_ARRAY;
         if (isType(LITERAL_throws, node)) {
             AST throwsNode = node.getFirstChild();
-            List<ClassNode> exceptionList = new ArrayList<ClassNode>();
+            List<ClassNode> exceptionList = new ArrayList<>();
             throwsList(throwsNode, exceptionList);
             exceptions = exceptionList.toArray(exceptions);
             node = node.getNextSibling();
@@ -1013,7 +1015,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected void fieldDef(AST fieldDef) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         AST node = fieldDef.getFirstChild();
 
         int modifiers = 0;
@@ -1048,7 +1050,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);
@@ -1098,6 +1099,8 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     public static Expression getDefaultValueForPrimitive(ClassNode type) {
+        if (type != null) type = type.redirect();
+
         if (type == ClassHelper.int_TYPE) {
             return new ConstantExpression(0);
         }
@@ -1126,7 +1129,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected ClassNode[] interfaces(AST node) {
-        List<ClassNode> interfaceList = new ArrayList<ClassNode>();
+        List<ClassNode> interfaceList = new ArrayList<>();
         for (AST implementNode = node.getFirstChild(); implementNode != null; implementNode = implementNode.getNextSibling()) {
             interfaceList.add(makeTypeWithArguments(implementNode));
         }
@@ -1146,7 +1149,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             if (isType(IMPLICIT_PARAMETERS, parametersNode)) return Parameter.EMPTY_ARRAY;
             return null;
         } else {
-            List<Parameter> parameters = new ArrayList<Parameter>();
+            List<Parameter> parameters = new ArrayList<>();
             AST firstParameterNode = null;
             do {
                 firstParam = (firstParameterNode == null);
@@ -1174,7 +1177,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected Parameter parameter(AST paramNode) {
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         boolean variableParameterDef = isType(VARIABLE_PARAMETER_DEF, paramNode);
         AST node = paramNode.getFirstChild();
 
@@ -1187,7 +1190,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();
         }
 
@@ -1314,8 +1318,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();
@@ -1335,7 +1338,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return annotatedNode;
     }
 
-
     // Statements
     //-------------------------------------------------------------------------
 
@@ -1421,10 +1423,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;
     }
@@ -1554,7 +1556,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     protected Expression declarationExpression(AST variableDef) {
         AST node = variableDef.getFirstChild();
         ClassNode type = null;
-        List<AnnotationNode> annotations = new ArrayList<AnnotationNode>();
+        List<AnnotationNode> annotations = new ArrayList<>();
         int modifiers = 0;
         if (isType(MODIFIERS, node)) {
             // force check of modifier conflicts
@@ -1631,20 +1633,18 @@ 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());
             }
-            if (tmpDefaultStatement != EmptyStatement.INSTANCE) {
-                if (defaultStatement == EmptyStatement.INSTANCE) {
+            if (!(tmpDefaultStatement instanceof EmptyStatement)) {
+                if (defaultStatement instanceof EmptyStatement) {
                     defaultStatement = tmpDefaultStatement;
                 } else {
                     throw new ASTRuntimeException(switchNode, "The default case is already defined.");
@@ -1654,13 +1654,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<Expression>();
+    protected Statement caseStatements(AST node, List<CaseStatement> cases) {
+        List<Expression> expressions = new ArrayList<>();
         Statement statement = EmptyStatement.INSTANCE;
         Statement defaultStatement = EmptyStatement.INSTANCE;
         AST nextSibling = node;
@@ -1677,10 +1677,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,7 +1720,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         AST node = tryNode.getNextSibling();
 
         // let's do the catch nodes
-        List<CatchStatement> catches = new ArrayList<CatchStatement>();
+        List<CatchStatement> catches = new ArrayList<>();
         for (; isType(LITERAL_catch, node); node = node.getNextSibling()) {
             final List<CatchStatement> catchStatements = catchStatement(node);
             catches.addAll(catchStatements);
@@ -1746,9 +1745,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     protected List<CatchStatement> catchStatement(AST catchNode) {
         AST node = catchNode.getFirstChild();
-        List<CatchStatement> catches = new LinkedList<CatchStatement>();
+        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)
@@ -1759,7 +1758,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) {
@@ -1797,7 +1797,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return whileStatement;
     }
 
-
     // Expressions
     //-------------------------------------------------------------------------
 
@@ -1825,7 +1824,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);
@@ -1886,10 +1886,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);
 
@@ -1905,14 +1901,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());
 
@@ -1946,23 +1943,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);
 
@@ -1993,18 +1986,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);
 
@@ -2029,42 +2010,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);
 
@@ -2099,7 +2074,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);
@@ -2114,7 +2088,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);
@@ -2150,7 +2126,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<Expression>();
+        List<Expression> list = new ArrayList<>();
         while (exprNode != null) {
             if (isType(EXPR, exprNode)) {
                 Expression expr = expression(exprNode);
@@ -2209,7 +2185,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;
@@ -2257,18 +2233,8 @@ 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<Expression>();
+        List<Expression> expressions = new ArrayList<>();
         AST elist = listNode.getFirstChild();
         assertNodeType(ELIST, elist);
 
@@ -2289,11 +2255,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);
@@ -2304,15 +2267,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;
     }
@@ -2336,7 +2299,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         }
     }
 
-
     protected Expression instanceofExpression(AST node) {
         AST leftNode = node.getFirstChild();
         Expression leftExpression = expression(leftNode);
@@ -2365,7 +2327,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) {
@@ -2381,7 +2345,6 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return castExpression;
     }
 
-
     protected Expression indexExpression(AST indexNode) {
         AST bracket = indexNode.getFirstChild();
         AST leftNode = bracket.getNextSibling();
@@ -2501,6 +2464,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);
@@ -2556,8 +2520,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);
@@ -2576,7 +2539,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"))) {
@@ -2631,7 +2594,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;
@@ -2668,8 +2631,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();
@@ -2685,14 +2648,14 @@ 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;
     }
 
     protected Expression enumArguments(AST elist) {
-        List<Expression> expressionList = new ArrayList<Expression>();
+        List<Expression> expressionList = new ArrayList<>();
         for (AST node = elist; node != null; node = node.getNextSibling()) {
             Expression expression = expression(node);
             expressionList.add(expression);
@@ -2703,7 +2666,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()) {
@@ -2720,7 +2683,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
                 // let's remove any non-MapEntryExpression instances
                 // such as if the last expression is a ClosureExpression
                 // so let's wrap the named method calls in a Map expression
-                List<Expression> argumentList = new ArrayList<Expression>();
+                List<Expression> argumentList = new ArrayList<>();
                 for (Object next : expressionList) {
                     Expression expression = (Expression) next;
                     if (!(expression instanceof MapEntryExpression)) {
@@ -2749,19 +2712,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<String>();
-        for (Object expression : expressionList) {
-            MapEntryExpression meExp = (MapEntryExpression) expression;
+        Set<String> namedArgumentNames = new HashSet<>();
+        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.");
                 }
             }
         }
@@ -2783,7 +2744,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
     }
 
     protected Expression expressionList(AST node) {
-        List<Expression> expressionList = new ArrayList<Expression>();
+        List<Expression> expressionList = new ArrayList<>();
         for (AST child = node.getFirstChild(); child != null; child = child.getNextSibling()) {
             expressionList.add(expression(child));
         }
@@ -2847,7 +2808,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
             case NUM_BIG_INT:
             case NUM_INT:
             case NUM_LONG:
-                ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger(unaryMinusExpr,"-" + text));
+                ConstantExpression constantLongExpression = new ConstantExpression(Numbers.parseInteger("-" + text));
                 configureAST(constantLongExpression, unaryMinusExpr);
                 return constantLongExpression;
 
@@ -2860,6 +2821,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:
@@ -2867,11 +2830,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;
         }
     }
@@ -2895,8 +2856,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();
 
@@ -2933,12 +2894,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();
@@ -3025,7 +2980,7 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
 
     private List<GenericsType> getTypeArgumentsList(AST node) {
         assertNodeType(TYPE_ARGUMENTS, node);
-        List<GenericsType> typeArgumentList = new LinkedList<GenericsType>();
+        List<GenericsType> typeArgumentList = new ArrayList<>();
         AST typeArgument = node.getFirstChild();
 
         while (typeArgument != null) {
@@ -3041,58 +2996,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, "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));
@@ -3108,44 +3065,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;
@@ -3186,11 +3121,9 @@ public class AntlrParserPlugin extends ASTHelper implements ParserPlugin, Groovy
         return identifier(node);
     }
 
-
     // Helper methods
     //-------------------------------------------------------------------------
 
-
     /**
      * Returns true if the modifiers flags contain a visibility modifier
      */
@@ -3200,16 +3133,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) {
@@ -3221,7 +3151,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/main/java/org/codehaus/groovy/ast/ModuleNode.java b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
index 54f7e16..ceeb58c 100644
--- a/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
+++ b/src/main/java/org/codehaus/groovy/ast/ModuleNode.java
@@ -37,6 +37,7 @@ import java.io.File;
 import java.net.URI;
 import java.net.URISyntaxException;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
@@ -87,7 +88,7 @@ public class ModuleNode extends ASTNode implements Opcodes {
     public List<ClassNode> getClasses() {
         if (createClassForStatements && (!statementBlock.isEmpty() || !methods.isEmpty() || isPackageInfo())) {
             ClassNode mainClass = createStatementsClass();
-            mainClassName = mainClass.getName(); 
+            mainClassName = mainClass.getName();
             createClassForStatements = false;
             classes.add(0, mainClass);
             mainClass.setModule(this);
@@ -233,7 +234,7 @@ public class ModuleNode extends ASTNode implements Opcodes {
             setScriptBaseClassFromConfig(scriptDummy);
             return scriptDummy;
         }
-        
+
         String name = getPackageName();
         if (name == null) {
             name = "";
@@ -273,13 +274,13 @@ public class ModuleNode extends ASTNode implements Opcodes {
             }
         }
     }
-    
+
     protected ClassNode createStatementsClass() {
         ClassNode classNode = getScriptClassDummy();
         if (classNode.getName().endsWith("package-info")) {
             return classNode;
         }
-        
+
         handleMainMethodIfPresent(methods);
 
         // return new Foo(new ShellContext(args)).run()
@@ -346,7 +347,7 @@ public class ModuleNode extends ASTNode implements Opcodes {
     }
 
     /*
-     * If a main method is provided by user, account for it under run() as scripts generate their own 'main' so they can run.  
+     * If a main method is provided by user, account for it under run() as scripts generate their own 'main' so they can run.
      */
     private void handleMainMethodIfPresent(List methods) {
         boolean found = false;
@@ -360,9 +361,8 @@ public class ModuleNode extends ASTNode implements Opcodes {
 
                     argTypeMatches = (argType.equals(ClassHelper.OBJECT_TYPE) || argType.getName().contains("String[]"));
                     retTypeMatches = (retType == ClassHelper.VOID_TYPE || retType == ClassHelper.OBJECT_TYPE);
-                    
-                    if(retTypeMatches && argTypeMatches) {
-                        if(found) {
+                    if (retTypeMatches && argTypeMatches) {
+                        if (found) {
                             throw new RuntimeException("Repetitive main method found.");
                         } else {
                             found = true;
@@ -412,8 +412,8 @@ public class ModuleNode extends ASTNode implements Opcodes {
     public boolean isEmpty() {
         return classes.isEmpty() && statementBlock.getStatements().isEmpty();
     }
-    
-    public void sortClasses(){
+
+    public void sortClasses() {
         if (isEmpty()) return;
         List<ClassNode> classes = getClasses();
         LinkedList<ClassNode> sorted = new LinkedList<ClassNode>();
@@ -449,18 +449,19 @@ public class ModuleNode extends ASTNode implements Opcodes {
     }
 
     public void addStaticImport(ClassNode type, String fieldName, String alias) {
-        addStaticImport(type, fieldName, alias, new ArrayList<AnnotationNode>());
+        addStaticImport(type, fieldName, alias, Collections.<AnnotationNode>emptyList());
     }
 
     public void addStaticImport(ClassNode type, String fieldName, String alias, List<AnnotationNode> annotations) {
         ImportNode node = new ImportNode(type, fieldName, alias);
         node.addAnnotations(annotations);
-        staticImports.put(alias, node);
+        ImportNode prev = staticImports.put(alias, node);
+        if (prev != null) staticImports.put(prev.toString(), prev);
         storeLastAddedImportNode(node);
     }
 
     public void addStaticStarImport(String name, ClassNode type) {
-        addStaticStarImport(name, type, new ArrayList<AnnotationNode>());
+        addStaticStarImport(name, type, Collections.<AnnotationNode>emptyList());
     }
 
     public void addStaticStarImport(String name, ClassNode type, List<AnnotationNode> annotations) {
diff --git a/src/test/groovy/bugs/Groovy7973Bug.groovy b/src/test/groovy/bugs/Groovy7973.groovy
similarity index 75%
rename from src/test/groovy/bugs/Groovy7973Bug.groovy
rename to src/test/groovy/bugs/Groovy7973.groovy
index a6ab96c..9c05c5b 100644
--- a/src/test/groovy/bugs/Groovy7973Bug.groovy
+++ b/src/test/groovy/bugs/Groovy7973.groovy
@@ -18,41 +18,47 @@
  */
 package groovy.bugs
 
-class Groovy7973Bug extends GroovyTestCase {
+import groovy.transform.CompileStatic
+import org.junit.Test
+
+import static groovy.test.GroovyAssert.assertScript
+
+@CompileStatic
+final class Groovy7973 {
 
     private static final String SCRIPT1 = '''
         class Test {
             def op1() { 'A'.with{ this.class.name } }
             def op2a() { new Object() { def inner() {
-                this.class.name + Test.this.class.name
+                Test.this.class.name + '::' + this.class.name
             } } }
             def op2b() { new Object() { def inner() {
-                'B'.with{ this.class.name + Test.this.class.name }
+                'B'.with { Test.this.class.name + '::' + this.class.name }
             } } }
             def op3a() { new Object() { def inner() { new Object() { def innerinner() {
-                this.class.name + Test$3.this.class.name + Test.this.class.name
+                Test.this.class.name + '::' + this.class.name
             } } } } }
             def op3b() { new Object() { def inner() { new Object() { def innerinner() {
-                'C'.with{ this.class.name + Test$5.this.class.name + Test.this.class.name }
+                'C'.with { Test.this.class.name + '::' + this.class.name }
             } } } } }
         }
 
         def t = new Test()
         assert t.op1() == 'Test'
-        assert t.op2a().inner() == 'Test$1Test'
-        assert t.op2b().inner() == 'Test$2Test'
-        assert t.op3a().inner().innerinner() == 'Test$3$4Test$3Test'
-        assert t.op3b().inner().innerinner() == 'Test$5$6Test$5Test'
+        assert t.op2a().inner() == 'Test::Test$1'
+        assert t.op2b().inner() == 'Test::Test$2'
+        assert t.op3a().inner().innerinner() == 'Test::Test$3$1'
+        assert t.op3b().inner().innerinner() == 'Test::Test$4$1'
     '''
 
     private static final String SCRIPT2 = '''
         class Test {
             def op1() { this }
-            def op2() { ''.with{ this } }
+            def op2() { ''.with { this } }
             def op3() { new Object() { def inner() { this } } }
-            def op4() { new Object() { def inner() { ''.with{ this } } } }
+            def op4() { new Object() { def inner() { ''.with { this } } } }
             def op5() { new Object() { def inner() { Test.this } } }
-            def op6() { new Object() { def inner() { ''.with{ Test.this } } } }
+            def op6() { new Object() { def inner() { ''.with { Test.this } } } }
             class Inner {
                 def inner1() { this }
                 def inner2() { ''.with { this } }
@@ -76,18 +82,22 @@ class Groovy7973Bug extends GroovyTestCase {
         assert inner.inner4().class.name == 'Test'
     '''
 
+    @Test
     void testClassDotThis() {
         assertScript SCRIPT1
     }
 
+    @Test
     void testClassDotThis_CS() {
         assertScript '@groovy.transform.CompileStatic\n' + SCRIPT1
     }
 
+    @Test
     void testClassDotThisAIC() {
         assertScript SCRIPT2
     }
 
+    @Test
     void testClassDotThisAIC_CS() {
         assertScript '@groovy.transform.CompileStatic\n' + SCRIPT2
     }
diff --git a/src/test/groovy/bugs/Groovy8446.groovy b/src/test/groovy/bugs/Groovy8446.groovy
new file mode 100644
index 0000000..4668438
--- /dev/null
+++ b/src/test/groovy/bugs/Groovy8446.groovy
@@ -0,0 +1,59 @@
+/*
+ *  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 Groovy8446 {
+
+    @Test
+    void testVoidArray0() {
+        assertScript '''
+            class C {
+                Void[] m() {}
+            }
+            println 'parsed'
+        '''
+    }
+
+    @Test
+    void testVoidArray1() {
+        def err = shouldFail '''
+            class C {
+                void[] m() {}
+            }
+        '''
+        assert err =~ /void\[\] is an invalid type/
+    }
+
+    @Test
+    void testVoidArray2() {
+        def err = shouldFail '''
+            class C {
+                def meth(void... args) {}
+            }
+        '''
+        assert err =~ /void\[\] is an invalid type|void is not allowed here/
+    }
+}