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

[groovy] 16/18: GROOVY-8446: Antlr2: 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_3_0_X
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 193267de8021367537654c6b05d3601d31788ba1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Nov 16 21:00:47 2019 -0600

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

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