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/21 10:46:28 UTC

[groovy] branch GROOVY_2_5_X updated: GROOVY-8446: syntax error for void[] or void...

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

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


The following commit(s) were added to refs/heads/GROOVY_2_5_X by this push:
     new 913d5c9c GROOVY-8446: syntax error for void[] or void...
913d5c9c is described below

commit 913d5c9ce2d83f95cfffb8d9712ef08eb662af1c
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..94032a6 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.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));
@@ -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/
+    }
+}