groovy-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sun...@apache.org
Subject [18/39] groovy git commit: Keep same name rule with groovy-parser-antlr2
Date Wed, 21 Dec 2016 16:36:38 GMT
http://git-wip-us.apache.org/repos/asf/groovy/blob/fc23a2ed/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
----------------------------------------------------------------------
diff --git a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
new file mode 100644
index 0000000..3f78bbf
--- /dev/null
+++ b/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
@@ -0,0 +1,4742 @@
+/*
+ *  Licensed to the Apache Software Foundation (ASF) under one
+ *  or more contributor license agreements.  See the NOTICE file
+ *  distributed with this work for additional information
+ *  regarding copyright ownership.  The ASF licenses this file
+ *  to you under the Apache License, Version 2.0 (the
+ *  "License"); you may not use this file except in compliance
+ *  with the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing,
+ *  software distributed under the License is distributed on an
+ *  "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ *  KIND, either express or implied.  See the License for the
+ *  specific language governing permissions and limitations
+ *  under the License.
+ */
+package org.apache.groovy.parser.antlr4;
+
+import groovy.lang.IntRange;
+import org.antlr.v4.runtime.ANTLRErrorListener;
+import org.antlr.v4.runtime.ANTLRInputStream;
+import org.antlr.v4.runtime.CommonTokenStream;
+import org.antlr.v4.runtime.ParserRuleContext;
+import org.antlr.v4.runtime.RecognitionException;
+import org.antlr.v4.runtime.Recognizer;
+import org.antlr.v4.runtime.Token;
+import org.antlr.v4.runtime.atn.PredictionMode;
+import org.antlr.v4.runtime.misc.ParseCancellationException;
+import org.antlr.v4.runtime.tree.ParseTree;
+import org.antlr.v4.runtime.tree.TerminalNode;
+import org.apache.groovy.parser.antlr4.internal.AtnManager;
+import org.apache.groovy.parser.antlr4.internal.DescriptiveErrorStrategy;
+import org.apache.groovy.parser.antlr4.util.StringUtils;
+import org.codehaus.groovy.GroovyBugError;
+import org.codehaus.groovy.antlr.EnumHelper;
+import org.codehaus.groovy.ast.ASTNode;
+import org.codehaus.groovy.ast.AnnotatedNode;
+import org.codehaus.groovy.ast.AnnotationNode;
+import org.codehaus.groovy.ast.ClassHelper;
+import org.codehaus.groovy.ast.ClassNode;
+import org.codehaus.groovy.ast.EnumConstantClassNode;
+import org.codehaus.groovy.ast.FieldNode;
+import org.codehaus.groovy.ast.GenericsType;
+import org.codehaus.groovy.ast.ImportNode;
+import org.codehaus.groovy.ast.InnerClassNode;
+import org.codehaus.groovy.ast.MethodNode;
+import org.codehaus.groovy.ast.ModuleNode;
+import org.codehaus.groovy.ast.PackageNode;
+import org.codehaus.groovy.ast.Parameter;
+import org.codehaus.groovy.ast.PropertyNode;
+import org.codehaus.groovy.ast.expr.AnnotationConstantExpression;
+import org.codehaus.groovy.ast.expr.ArgumentListExpression;
+import org.codehaus.groovy.ast.expr.ArrayExpression;
+import org.codehaus.groovy.ast.expr.AttributeExpression;
+import org.codehaus.groovy.ast.expr.BinaryExpression;
+import org.codehaus.groovy.ast.expr.BitwiseNegationExpression;
+import org.codehaus.groovy.ast.expr.BooleanExpression;
+import org.codehaus.groovy.ast.expr.CastExpression;
+import org.codehaus.groovy.ast.expr.ClassExpression;
+import org.codehaus.groovy.ast.expr.ClosureExpression;
+import org.codehaus.groovy.ast.expr.ClosureListExpression;
+import org.codehaus.groovy.ast.expr.ConstantExpression;
+import org.codehaus.groovy.ast.expr.ConstructorCallExpression;
+import org.codehaus.groovy.ast.expr.DeclarationExpression;
+import org.codehaus.groovy.ast.expr.ElvisOperatorExpression;
+import org.codehaus.groovy.ast.expr.EmptyExpression;
+import org.codehaus.groovy.ast.expr.Expression;
+import org.codehaus.groovy.ast.expr.GStringExpression;
+import org.codehaus.groovy.ast.expr.LambdaExpression;
+import org.codehaus.groovy.ast.expr.ListExpression;
+import org.codehaus.groovy.ast.expr.MapEntryExpression;
+import org.codehaus.groovy.ast.expr.MapExpression;
+import org.codehaus.groovy.ast.expr.MethodCallExpression;
+import org.codehaus.groovy.ast.expr.MethodPointerExpression;
+import org.codehaus.groovy.ast.expr.MethodReferenceExpression;
+import org.codehaus.groovy.ast.expr.NamedArgumentListExpression;
+import org.codehaus.groovy.ast.expr.NotExpression;
+import org.codehaus.groovy.ast.expr.PostfixExpression;
+import org.codehaus.groovy.ast.expr.PrefixExpression;
+import org.codehaus.groovy.ast.expr.PropertyExpression;
+import org.codehaus.groovy.ast.expr.RangeExpression;
+import org.codehaus.groovy.ast.expr.SpreadExpression;
+import org.codehaus.groovy.ast.expr.SpreadMapExpression;
+import org.codehaus.groovy.ast.expr.TernaryExpression;
+import org.codehaus.groovy.ast.expr.TupleExpression;
+import org.codehaus.groovy.ast.expr.UnaryMinusExpression;
+import org.codehaus.groovy.ast.expr.UnaryPlusExpression;
+import org.codehaus.groovy.ast.expr.VariableExpression;
+import org.codehaus.groovy.ast.stmt.AssertStatement;
+import org.codehaus.groovy.ast.stmt.BlockStatement;
+import org.codehaus.groovy.ast.stmt.BreakStatement;
+import org.codehaus.groovy.ast.stmt.CaseStatement;
+import org.codehaus.groovy.ast.stmt.CatchStatement;
+import org.codehaus.groovy.ast.stmt.ContinueStatement;
+import org.codehaus.groovy.ast.stmt.DoWhileStatement;
+import org.codehaus.groovy.ast.stmt.EmptyStatement;
+import org.codehaus.groovy.ast.stmt.ExpressionStatement;
+import org.codehaus.groovy.ast.stmt.ForStatement;
+import org.codehaus.groovy.ast.stmt.IfStatement;
+import org.codehaus.groovy.ast.stmt.ReturnStatement;
+import org.codehaus.groovy.ast.stmt.Statement;
+import org.codehaus.groovy.ast.stmt.SwitchStatement;
+import org.codehaus.groovy.ast.stmt.SynchronizedStatement;
+import org.codehaus.groovy.ast.stmt.ThrowStatement;
+import org.codehaus.groovy.ast.stmt.TryCatchStatement;
+import org.codehaus.groovy.ast.stmt.WhileStatement;
+import org.codehaus.groovy.control.CompilationFailedException;
+import org.codehaus.groovy.control.CompilePhase;
+import org.codehaus.groovy.control.SourceUnit;
+import org.codehaus.groovy.control.messages.SyntaxErrorMessage;
+import org.codehaus.groovy.runtime.IOGroovyMethods;
+import org.codehaus.groovy.runtime.StringGroovyMethods;
+import org.codehaus.groovy.syntax.Numbers;
+import org.codehaus.groovy.syntax.SyntaxException;
+import org.codehaus.groovy.syntax.Types;
+import org.objectweb.asm.Opcodes;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.util.ArrayDeque;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.LinkedHashMap;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ABSTRACT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ADD;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AS;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AdditiveExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AndExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnnotationsOptContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AnonymousInnerClassDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ArgumentsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ArrayInitializerContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AssertStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.AssignmentExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BlockStatementsOptContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BooleanLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BreakStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.BuiltInTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CASE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CastParExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CatchClauseContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CatchTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassBodyDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifierContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceModifiersOptContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClassOrInterfaceTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClosureContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ClosurePrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandArgumentContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CommandExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CompilationUnitContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ConditionalExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ContinueStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ContinueStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CreatedNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.CreatorContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEF;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DEFAULT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DoWhileStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.DynamicMemberNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueArrayInitializerContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValueContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ElementValuePairsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedArgumentListElementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnhancedForControlContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EnumConstantsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.EqualityExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExclusiveOrExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionListElementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ExpressionStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FINAL;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FieldDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FinallyBlockContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FloatingPointLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForControlContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForInitContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ForUpdateContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParameterListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.FormalParametersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GroovyParserRuleContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringPathContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.GstringValueContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IN;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.INC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.INSTANCEOF;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IdentifierPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IfElseStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ImportDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ImportStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.InclusiveOrExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IndexPropertyArgsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.IntegerLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.KeywordsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LabeledStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LambdaBodyContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LambdaPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LastFormalParameterContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ListPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LiteralPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LocalVariableDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LocalVariableDeclarationStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalAndExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LogicalOrExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.LoopStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryLabelContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapEntryListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MapPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MemberDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodBodyContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodDeclarationStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MethodNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifierContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ModifiersOptContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MultipleAssignmentExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.MultiplicativeExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NATIVE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_IN;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NOT_INSTANCEOF;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NamePartContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NamedPropertyArgsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NewPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NlsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NonWildcardTypeArgumentsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NormalExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.NullLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PRIVATE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PROTECTED;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PUBLIC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PackageDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ParExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ParenPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PathElementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PathExpressionContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PostfixExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PowerExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.PrimitiveTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedClassNameListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.QualifiedStandardClassNameContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.RegexExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.RelationalExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourceListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ResourcesContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ReturnTypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.STATIC;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.STRICTFP;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SUB;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SYNCHRONIZED;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SepContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ShiftExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.StandardLambdaParametersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.StringLiteralAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.StringLiteralContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SuperPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchBlockStatementGroupContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchLabelContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SwitchStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.SynchronizedStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TRANSIENT;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ThisPrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.ThrowStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TryCatchStatementContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TryCatchStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeArgumentsOrDiamondContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeBoundContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeDeclarationStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeListContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeNamePairsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParameterContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypeParametersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.TypePrmrAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryAddExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.UnaryNotExprAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VOLATILE;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclarationContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorIdContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableDeclaratorsContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableInitializerContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifierContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableModifiersOptContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.VariableNamesContext;
+import static org.apache.groovy.parser.antlr4.GroovyLangParser.WhileStmtAltContext;
+import static org.apache.groovy.parser.antlr4.GroovyParser.ElementValuesContext;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
+import static org.codehaus.groovy.runtime.DefaultGroovyMethods.last;
+
+/**
+ * Building the AST from the parse tree generated by Antlr4
+ *
+ * @author <a href="mailto:realbluesun@hotmail.com">Daniel.Sun</a>
+ *         Created on 2016/08/14
+ */
+public class AstBuilder extends GroovyParserBaseVisitor<Object> implements GroovyParserVisitor<Object> {
+
+    public AstBuilder(SourceUnit sourceUnit, ClassLoader classLoader) {
+        this.sourceUnit = sourceUnit;
+        this.moduleNode = new ModuleNode(sourceUnit);
+        this.classLoader = classLoader; // unused for the time being
+
+        this.lexer = new GroovyLangLexer(
+                new ANTLRInputStream(
+                        this.readSourceCode(sourceUnit)));
+        this.parser = new GroovyLangParser(
+                new CommonTokenStream(this.lexer));
+
+        this.parser.setErrorHandler(new DescriptiveErrorStrategy());
+
+        this.tryWithResourcesASTTransformation = new TryWithResourcesASTTransformation(this);
+    }
+
+    private GroovyParserRuleContext buildCST() {
+        GroovyParserRuleContext result;
+
+        // parsing have to wait util clearing is complete.
+        AtnManager.RRWL.readLock().lock();
+        try {
+            result = buildCST(PredictionMode.SLL);
+        } catch (Throwable t) {
+            // if some syntax error occurred in the lexer, no need to retry the powerful LL mode
+            if (t instanceof GroovySyntaxError && GroovySyntaxError.LEXER == ((GroovySyntaxError) t).getSource()) {
+                throw t;
+            }
+
+            result = buildCST(PredictionMode.LL);
+        } finally {
+            AtnManager.RRWL.readLock().unlock();
+        }
+
+        return result;
+    }
+
+    private GroovyParserRuleContext buildCST(PredictionMode predictionMode) {
+        parser.getInterpreter().setPredictionMode(predictionMode);
+
+        if (PredictionMode.SLL.equals(predictionMode)) {
+            this.removeErrorListeners();
+        } else {
+            ((CommonTokenStream) parser.getInputStream()).reset();
+            this.addErrorListeners();
+        }
+
+        return parser.compilationUnit();
+    }
+
+    public ModuleNode buildAST() {
+        try {
+            return (ModuleNode) this.visit(this.buildCST());
+        } catch (Throwable t) {
+            CompilationFailedException cfe;
+
+            if (t instanceof CompilationFailedException) {
+                cfe = (CompilationFailedException) t;
+            } else if (t instanceof ParseCancellationException) {
+                cfe = createParsingFailedException(t.getCause());
+            } else {
+                cfe = createParsingFailedException(t);
+            }
+
+            LOGGER.log(Level.SEVERE, "Failed to build AST", cfe);
+
+            throw cfe;
+        }
+    }
+
+    @Override
+    public ModuleNode visitCompilationUnit(CompilationUnitContext ctx) {
+        this.visit(ctx.packageDeclaration());
+
+        ctx.statement().stream()
+                .map(this::visit)
+//                .filter(e -> e instanceof Statement)
+                .forEach(e -> {
+                    if (e instanceof DeclarationListStatement) { // local variable declaration
+                        ((DeclarationListStatement) e).getDeclarationStatements().forEach(moduleNode::addStatement);
+                    } else if (e instanceof Statement) {
+                        moduleNode.addStatement((Statement) e);
+                    } else if (e instanceof MethodNode) { // script method
+                        moduleNode.addMethod((MethodNode) e);
+                    }
+                });
+
+        this.classNodeList.forEach(moduleNode::addClass);
+
+        if (this.isPackageInfoDeclaration()) {
+            this.addPackageInfoClassNode();
+        } else {
+            // if groovy source file only contains blank(including EOF), add "return null" to the AST
+            if (this.isBlankScript(ctx)) {
+                this.addEmptyReturnStatement();
+            }
+        }
+
+        this.configureScriptClassNode();
+
+        return moduleNode;
+    }
+
+    @Override
+    public PackageNode visitPackageDeclaration(PackageDeclarationContext ctx) {
+        String packageName = this.visitQualifiedName(ctx.qualifiedName());
+        moduleNode.setPackageName(packageName + DOT_STR);
+
+        PackageNode packageNode = moduleNode.getPackage();
+
+        this.visitAnnotationsOpt(ctx.annotationsOpt()).stream()
+                .forEach(packageNode::addAnnotation);
+
+        return this.configureAST(packageNode, ctx);
+    }
+
+    @Override
+    public ImportNode visitImportDeclaration(ImportDeclarationContext ctx) {
+        // GROOVY-6094
+        moduleNode.putNodeMetaData(IMPORT_NODE_CLASS, IMPORT_NODE_CLASS);
+
+        ImportNode importNode;
+
+        boolean hasStatic = asBoolean(ctx.STATIC());
+        boolean hasStar = asBoolean(ctx.MUL());
+        boolean hasAlias = asBoolean(ctx.alias);
+
+        List<AnnotationNode> annotationNodeList = this.visitAnnotationsOpt(ctx.annotationsOpt());
+
+        if (hasStatic) {
+            if (hasStar) { // e.g. import static java.lang.Math.*
+                String qualifiedName = this.visitQualifiedName(ctx.qualifiedName());
+                ClassNode type = ClassHelper.make(qualifiedName);
+
+
+                moduleNode.addStaticStarImport(type.getText(), type, annotationNodeList);
+
+                importNode = last(moduleNode.getStaticStarImports().values());
+            } else { // e.g. import static java.lang.Math.pow
+                List<GroovyParserRuleContext> identifierList = new LinkedList<>(ctx.qualifiedName().qualifiedNameElement());
+                int identifierListSize = identifierList.size();
+                String name = identifierList.get(identifierListSize - 1).getText();
+                ClassNode classNode =
+                        ClassHelper.make(
+                                identifierList.stream()
+                                        .limit(identifierListSize - 1)
+                                        .map(ParseTree::getText)
+                                        .collect(Collectors.joining(DOT_STR)));
+                String alias = hasAlias
+                        ? ctx.alias.getText()
+                        : name;
+
+                moduleNode.addStaticImport(classNode, name, alias, annotationNodeList);
+
+                importNode = last(moduleNode.getStaticImports().values());
+            }
+        } else {
+            if (hasStar) { // e.g. import java.util.*
+                String qualifiedName = this.visitQualifiedName(ctx.qualifiedName());
+
+                moduleNode.addStarImport(qualifiedName + DOT_STR, annotationNodeList);
+
+                importNode = last(moduleNode.getStarImports());
+            } else { // e.g. import java.util.Map
+                String qualifiedName = this.visitQualifiedName(ctx.qualifiedName());
+                String name = last(ctx.qualifiedName().qualifiedNameElement()).getText();
+                ClassNode classNode = ClassHelper.make(qualifiedName);
+                String alias = hasAlias
+                        ? ctx.alias.getText()
+                        : name;
+
+                moduleNode.addImport(alias, classNode, annotationNodeList);
+
+                importNode = last(moduleNode.getImports());
+            }
+        }
+
+        // TODO verify whether the following code is useful or not
+        // we're using node metadata here in order to fix GROOVY-6094
+        // without breaking external APIs
+        Object node = moduleNode.getNodeMetaData(IMPORT_NODE_CLASS);
+        if (null != node && IMPORT_NODE_CLASS != node) {
+            this.configureAST((ImportNode) node, importNode);
+        }
+        moduleNode.removeNodeMetaData(IMPORT_NODE_CLASS);
+
+        return this.configureAST(importNode, ctx);
+    }
+
+    // statement {    --------------------------------------------------------------------
+    @Override
+    public AssertStatement visitAssertStmtAlt(AssertStmtAltContext ctx) {
+        Expression conditionExpression = (Expression) this.visit(ctx.ce);
+        BooleanExpression booleanExpression =
+                this.configureAST(
+                        new BooleanExpression(conditionExpression), conditionExpression);
+
+        if (!asBoolean(ctx.me)) {
+            return this.configureAST(
+                    new AssertStatement(booleanExpression), ctx);
+        }
+
+        return this.configureAST(new AssertStatement(booleanExpression,
+                        (Expression) this.visit(ctx.me)),
+                ctx);
+
+    }
+
+    @Override
+    public IfStatement visitIfElseStmtAlt(IfElseStmtAltContext ctx) {
+        Expression conditionExpression = this.visitParExpression(ctx.parExpression());
+        BooleanExpression booleanExpression =
+                this.configureAST(
+                        new BooleanExpression(conditionExpression), conditionExpression);
+
+        Statement ifBlock =
+                this.unpackStatement(
+                        (Statement) this.visit(ctx.tb));
+        Statement elseBlock =
+                this.unpackStatement(
+                        asBoolean(ctx.ELSE())
+                                ? (Statement) this.visit(ctx.fb)
+                                : EmptyStatement.INSTANCE);
+
+        return this.configureAST(new IfStatement(booleanExpression, ifBlock, elseBlock), ctx);
+    }
+
+    @Override
+    public Statement visitLoopStmtAlt(LoopStmtAltContext ctx) {
+        return this.configureAST((Statement) this.visit(ctx.loopStatement()), ctx);
+    }
+
+    @Override
+    public ForStatement visitForStmtAlt(ForStmtAltContext ctx) {
+        Pair<Parameter, Expression> controlPair = this.visitForControl(ctx.forControl());
+
+        Statement loopBlock = this.unpackStatement((Statement) this.visit(ctx.statement()));
+
+        return this.configureAST(
+                new ForStatement(controlPair.getKey(), controlPair.getValue(), asBoolean(loopBlock) ? loopBlock : EmptyStatement.INSTANCE),
+                ctx);
+    }
+
+    @Override
+    public Pair<Parameter, Expression> visitForControl(ForControlContext ctx) {
+        if (asBoolean(ctx.enhancedForControl())) { // e.g. for(int i in 0..<10) {}
+            return this.visitEnhancedForControl(ctx.enhancedForControl());
+        }
+
+        if (asBoolean(ctx.SEMI())) { // e.g. for(int i = 0; i < 10; i++) {}
+            ClosureListExpression closureListExpression = new ClosureListExpression();
+
+            closureListExpression.addExpression(this.visitForInit(ctx.forInit()));
+            closureListExpression.addExpression(asBoolean(ctx.expression()) ? (Expression) this.visit(ctx.expression()) : EmptyExpression.INSTANCE);
+            closureListExpression.addExpression(this.visitForUpdate(ctx.forUpdate()));
+
+            return new Pair<>(ForStatement.FOR_LOOP_DUMMY, closureListExpression);
+        }
+
+        throw createParsingFailedException("Unsupported for control: " + ctx.getText(), ctx);
+    }
+
+    @Override
+    public Expression visitForInit(ForInitContext ctx) {
+        if (!asBoolean(ctx)) {
+            return EmptyExpression.INSTANCE;
+        }
+
+        if (asBoolean(ctx.localVariableDeclaration())) {
+            DeclarationListStatement declarationListStatement = this.visitLocalVariableDeclaration(ctx.localVariableDeclaration());
+
+            List<?> declarationExpressionList = declarationListStatement.getDeclarationExpressions();
+
+            if (declarationExpressionList.size() == 1) {
+                return this.configureAST((Expression) declarationExpressionList.get(0), ctx);
+            } else {
+                return this.configureAST(new ClosureListExpression((List<Expression>) declarationExpressionList), ctx);
+            }
+        }
+
+        if (asBoolean(ctx.expression())) {
+            return this.configureAST((Expression) this.visit(ctx.expression()), ctx);
+        }
+
+        throw createParsingFailedException("Unsupported for init: " + ctx.getText(), ctx);
+    }
+
+    @Override
+    public Expression visitForUpdate(ForUpdateContext ctx) {
+        if (!asBoolean(ctx)) {
+            return EmptyExpression.INSTANCE;
+        }
+
+        return this.configureAST((Expression) this.visit(ctx.expression()), ctx);
+    }
+
+
+    @Override
+    public Pair<Parameter, Expression> visitEnhancedForControl(EnhancedForControlContext ctx) {
+        Parameter parameter = this.configureAST(
+                new Parameter(this.visitType(ctx.type()), this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName()),
+                ctx.variableDeclaratorId());
+
+        // FIXME Groovy will ignore variableModifier of parameter in the for control
+        // In order to make the new parser behave same with the old one, we do not process variableModifier*
+
+        return new Pair<>(parameter, (Expression) this.visit(ctx.expression()));
+    }
+
+
+    @Override
+    public WhileStatement visitWhileStmtAlt(WhileStmtAltContext ctx) {
+        Expression conditionExpression = this.visitParExpression(ctx.parExpression());
+        BooleanExpression booleanExpression =
+                this.configureAST(
+                        new BooleanExpression(conditionExpression), conditionExpression);
+
+        Statement loopBlock = this.unpackStatement((Statement) this.visit(ctx.statement()));
+
+        return this.configureAST(
+                new WhileStatement(booleanExpression, asBoolean(loopBlock) ? loopBlock : EmptyStatement.INSTANCE),
+                ctx);
+    }
+
+    @Override
+    public DoWhileStatement visitDoWhileStmtAlt(DoWhileStmtAltContext ctx) {
+        Expression conditionExpression = this.visitParExpression(ctx.parExpression());
+
+        BooleanExpression booleanExpression =
+                this.configureAST(
+                        new BooleanExpression(conditionExpression),
+                        conditionExpression
+                );
+
+        Statement loopBlock = this.unpackStatement((Statement) this.visit(ctx.statement()));
+
+        return this.configureAST(
+                new DoWhileStatement(booleanExpression, asBoolean(loopBlock) ? loopBlock : EmptyStatement.INSTANCE),
+                ctx);
+    }
+
+    @Override
+    public Statement visitTryCatchStmtAlt(TryCatchStmtAltContext ctx) {
+        return this.configureAST(this.visitTryCatchStatement(ctx.tryCatchStatement()), ctx);
+    }
+
+    @Override
+    public Statement visitTryCatchStatement(TryCatchStatementContext ctx) {
+        TryCatchStatement tryCatchStatement =
+                new TryCatchStatement((Statement) this.visit(ctx.block()),
+                        this.visitFinallyBlock(ctx.finallyBlock()));
+
+        if (asBoolean(ctx.resources())) {
+            this.visitResources(ctx.resources()).stream()
+                    .forEach(tryCatchStatement::addResource);
+        }
+
+        ctx.catchClause().stream().map(this::visitCatchClause)
+                .reduce(new LinkedList<CatchStatement>(), (r, e) -> {
+                    r.addAll(e); // merge several LinkedList<CatchStatement> instances into one LinkedList<CatchStatement> instance
+                    return r;
+                })
+                .forEach(tryCatchStatement::addCatch);
+
+        return this.configureAST(
+                tryWithResourcesASTTransformation.transform(
+                        this.configureAST(tryCatchStatement, ctx)),
+                ctx);
+    }
+
+
+    @Override
+    public List<ExpressionStatement> visitResources(ResourcesContext ctx) {
+        return this.visitResourceList(ctx.resourceList());
+    }
+
+    @Override
+    public List<ExpressionStatement> visitResourceList(ResourceListContext ctx) {
+        return ctx.resource().stream().map(this::visitResource).collect(Collectors.toList());
+    }
+
+    @Override
+    public ExpressionStatement visitResource(ResourceContext ctx) {
+        if (asBoolean(ctx.localVariableDeclaration())) {
+            List<ExpressionStatement> declarationStatements = this.visitLocalVariableDeclaration(ctx.localVariableDeclaration()).getDeclarationStatements();
+
+            if (declarationStatements.size() > 1) {
+                throw createParsingFailedException("Multi resources can not be declared in one statement", ctx);
+            }
+
+            return declarationStatements.get(0);
+        } else if (asBoolean(ctx.expression())) {
+            Expression expression = (Expression) this.visit(ctx.expression());
+            if (!(expression instanceof BinaryExpression
+                    && Types.ASSIGN == ((BinaryExpression) expression).getOperation().getType()
+                    && ((BinaryExpression) expression).getLeftExpression() instanceof VariableExpression)) {
+
+                throw createParsingFailedException("Only variable declarations are allowed to declare resource", ctx);
+            }
+
+            BinaryExpression assignmentExpression = (BinaryExpression) expression;
+
+            return this.configureAST(
+                    new ExpressionStatement(
+                            this.configureAST(
+                                    new DeclarationExpression(
+                                            this.configureAST(
+                                                    new VariableExpression(assignmentExpression.getLeftExpression().getText()),
+                                                    assignmentExpression.getLeftExpression()
+                                            ),
+                                            assignmentExpression.getOperation(),
+                                            assignmentExpression.getRightExpression()
+                                    ), ctx)
+                    ), ctx);
+        }
+
+        throw createParsingFailedException("Unsupported resource declaration: " + ctx.getText(), ctx);
+    }
+
+    /**
+     * Multi-catch(1..*) clause will be unpacked to several normal catch clauses, so the return type is List
+     *
+     * @param ctx the parse tree
+     * @return
+     */
+    @Override
+    public List<CatchStatement> visitCatchClause(CatchClauseContext ctx) {
+        // FIXME Groovy will ignore variableModifier of parameter in the catch clause
+        // In order to make the new parser behave same with the old one, we do not process variableModifier*
+
+        return this.visitCatchType(ctx.catchType()).stream()
+                .map(e -> this.configureAST(
+                        new CatchStatement(
+                                // FIXME The old parser does not set location info for the parameter of the catch clause.
+                                // we could make it better
+                                //this.configureAST(new Parameter(e, this.visitIdentifier(ctx.identifier())), ctx.Identifier()),
+
+                                new Parameter(e, this.visitIdentifier(ctx.identifier())),
+                                this.visitBlock(ctx.block())),
+                        ctx.block()))
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public List<ClassNode> visitCatchType(CatchTypeContext ctx) {
+        if (!asBoolean(ctx)) {
+            return Collections.singletonList(ClassHelper.OBJECT_TYPE);
+        }
+
+        return ctx.qualifiedClassName().stream()
+                .map(this::visitQualifiedClassName)
+                .collect(Collectors.toList());
+    }
+
+
+    @Override
+    public Statement visitFinallyBlock(FinallyBlockContext ctx) {
+        if (!asBoolean(ctx)) {
+            return EmptyStatement.INSTANCE;
+        }
+
+        return this.configureAST(
+                this.createBlockStatement((Statement) this.visit(ctx.block())),
+                ctx);
+    }
+
+    @Override
+    public SwitchStatement visitSwitchStmtAlt(SwitchStmtAltContext ctx) {
+        return this.configureAST(this.visitSwitchStatement(ctx.switchStatement()), ctx);
+    }
+
+    public SwitchStatement visitSwitchStatement(SwitchStatementContext ctx) {
+        List<Statement> statementList =
+                ctx.switchBlockStatementGroup().stream()
+                        .map(this::visitSwitchBlockStatementGroup)
+                        .reduce(new LinkedList<>(), (r, e) -> {
+                            r.addAll(e);
+                            return r;
+                        });
+
+        List<CaseStatement> caseStatementList = new LinkedList<>();
+        List<Statement> defaultStatementList = new LinkedList<>();
+
+        statementList.stream().forEach(e -> {
+            if (e instanceof CaseStatement) {
+                caseStatementList.add((CaseStatement) e);
+            } else if (isTrue(e, IS_SWITCH_DEFAULT)) {
+                defaultStatementList.add(e);
+            }
+        });
+
+        int defaultStatementListSize = defaultStatementList.size();
+        if (defaultStatementListSize > 1) {
+            throw createParsingFailedException("switch statement should have only one default case, which should appear at last", defaultStatementList.get(0));
+        }
+
+        if (defaultStatementListSize > 0 && last(statementList) instanceof CaseStatement) {
+            throw createParsingFailedException("default case should appear at last", defaultStatementList.get(0));
+        }
+
+        return this.configureAST(
+                new SwitchStatement(
+                        this.visitParExpression(ctx.parExpression()),
+                        caseStatementList,
+                        defaultStatementListSize == 0 ? EmptyStatement.INSTANCE : defaultStatementList.get(0)
+                ),
+                ctx);
+
+    }
+
+
+    @Override
+    @SuppressWarnings({"unchecked"})
+    public List<Statement> visitSwitchBlockStatementGroup(SwitchBlockStatementGroupContext ctx) {
+        int labelCnt = ctx.switchLabel().size();
+        List<Token> firstLabelHolder = new ArrayList<>(1);
+
+        return (List<Statement>) ctx.switchLabel().stream()
+                .map(e -> (Object) this.visitSwitchLabel(e))
+                .reduce(new ArrayList<Statement>(4), (r, e) -> {
+                    List<Statement> statementList = (List<Statement>) r;
+                    Pair<Token, Expression> pair = (Pair<Token, Expression>) e;
+
+                    boolean isLast = labelCnt - 1 == statementList.size();
+
+                    switch (pair.getKey().getType()) {
+                        case CASE: {
+                            if (!asBoolean(statementList)) {
+                                firstLabelHolder.add(pair.getKey());
+                            }
+
+                            statementList.add(
+                                    this.configureAST(
+                                            new CaseStatement(
+                                                    pair.getValue(),
+
+                                                    // check whether processing the last label. if yes, block statement should be attached.
+                                                    isLast ? this.visitBlockStatements(ctx.blockStatements())
+                                                            : EmptyStatement.INSTANCE
+                                            ),
+                                            firstLabelHolder.get(0)));
+
+                            break;
+                        }
+                        case DEFAULT: {
+
+                            BlockStatement blockStatement = this.visitBlockStatements(ctx.blockStatements());
+                            blockStatement.putNodeMetaData(IS_SWITCH_DEFAULT, true);
+
+                            statementList.add(
+                                    // this.configureAST(blockStatement, pair.getKey())
+                                    blockStatement
+                            );
+
+                            break;
+                        }
+                    }
+
+                    return statementList;
+                });
+
+    }
+
+    @Override
+    public Pair<Token, Expression> visitSwitchLabel(SwitchLabelContext ctx) {
+        if (asBoolean(ctx.CASE())) {
+            return new Pair<>(ctx.CASE().getSymbol(), (Expression) this.visit(ctx.expression()));
+        } else if (asBoolean(ctx.DEFAULT())) {
+            return new Pair<>(ctx.DEFAULT().getSymbol(), EmptyExpression.INSTANCE);
+        }
+
+        throw createParsingFailedException("Unsupported switch label: " + ctx.getText(), ctx);
+    }
+
+
+    @Override
+    public SynchronizedStatement visitSynchronizedStmtAlt(SynchronizedStmtAltContext ctx) {
+        return this.configureAST(
+                new SynchronizedStatement(this.visitParExpression(ctx.parExpression()), this.visitBlock(ctx.block())),
+                ctx);
+    }
+
+
+    @Override
+    public ExpressionStatement visitExpressionStmtAlt(ExpressionStmtAltContext ctx) {
+        return (ExpressionStatement) this.visit(ctx.statementExpression());
+    }
+
+    @Override
+    public ReturnStatement visitReturnStmtAlt(ReturnStmtAltContext ctx) {
+        return this.configureAST(new ReturnStatement(asBoolean(ctx.expression())
+                        ? (Expression) this.visit(ctx.expression())
+                        : ConstantExpression.EMPTY_EXPRESSION),
+                ctx);
+    }
+
+    @Override
+    public ThrowStatement visitThrowStmtAlt(ThrowStmtAltContext ctx) {
+        return this.configureAST(
+                new ThrowStatement((Expression) this.visit(ctx.expression())),
+                ctx);
+    }
+
+    @Override
+    public Statement visitLabeledStmtAlt(LabeledStmtAltContext ctx) {
+        Statement statement = (Statement) this.visit(ctx.statement());
+
+        statement.addStatementLabel(this.visitIdentifier(ctx.identifier()));
+
+        return statement; // this.configureAST(statement, ctx);
+    }
+
+    @Override
+    public BreakStatement visitBreakStatement(BreakStatementContext ctx) {
+        String label = asBoolean(ctx.identifier())
+                ? this.visitIdentifier(ctx.identifier())
+                : null;
+
+        return this.configureAST(new BreakStatement(label), ctx);
+    }
+
+    @Override
+    public BreakStatement visitBreakStmtAlt(BreakStmtAltContext ctx) {
+        return this.configureAST(this.visitBreakStatement(ctx.breakStatement()), ctx);
+    }
+
+    @Override
+    public ContinueStatement visitContinueStatement(ContinueStatementContext ctx) {
+        String label = asBoolean(ctx.identifier())
+                ? this.visitIdentifier(ctx.identifier())
+                : null;
+
+        return this.configureAST(new ContinueStatement(label), ctx);
+
+    }
+
+    @Override
+    public ContinueStatement visitContinueStmtAlt(ContinueStmtAltContext ctx) {
+        return this.configureAST(this.visitContinueStatement(ctx.continueStatement()), ctx);
+    }
+
+    @Override
+    public ImportNode visitImportStmtAlt(ImportStmtAltContext ctx) {
+        return this.configureAST(this.visitImportDeclaration(ctx.importDeclaration()), ctx);
+    }
+
+    @Override
+    public ClassNode visitTypeDeclarationStmtAlt(TypeDeclarationStmtAltContext ctx) {
+        return this.configureAST(this.visitTypeDeclaration(ctx.typeDeclaration()), ctx);
+    }
+
+
+    @Override
+    public Statement visitLocalVariableDeclarationStmtAlt(LocalVariableDeclarationStmtAltContext ctx) {
+        return this.configureAST(this.visitLocalVariableDeclaration(ctx.localVariableDeclaration()), ctx);
+    }
+
+    @Override
+    public MethodNode visitMethodDeclarationStmtAlt(MethodDeclarationStmtAltContext ctx) {
+        return this.configureAST(this.visitMethodDeclaration(ctx.methodDeclaration()), ctx);
+    }
+
+    // } statement    --------------------------------------------------------------------
+
+    @Override
+    public ClassNode visitTypeDeclaration(TypeDeclarationContext ctx) {
+        if (asBoolean(ctx.classDeclaration())) { // e.g. class A {}
+            ctx.classDeclaration().putNodeMetaData(TYPE_DECLARATION_MODIFIERS, this.visitClassOrInterfaceModifiersOpt(ctx.classOrInterfaceModifiersOpt()));
+            return this.configureAST(this.visitClassDeclaration(ctx.classDeclaration()), ctx);
+        }
+
+        throw createParsingFailedException("Unsupported type declaration: " + ctx.getText(), ctx);
+    }
+
+    private void initUsingGenerics(ClassNode classNode) {
+        if (classNode.isUsingGenerics()) {
+            return;
+        }
+
+        if (!classNode.isEnum()) {
+            classNode.setUsingGenerics(classNode.getSuperClass().isUsingGenerics());
+        }
+
+        if (!classNode.isUsingGenerics() && asBoolean((Object) classNode.getInterfaces())) {
+            for (ClassNode anInterface : classNode.getInterfaces()) {
+                classNode.setUsingGenerics(classNode.isUsingGenerics() || anInterface.isUsingGenerics());
+
+                if (classNode.isUsingGenerics())
+                    break;
+            }
+        }
+    }
+
+    @Override
+    public ClassNode visitClassDeclaration(ClassDeclarationContext ctx) {
+        String packageName = moduleNode.getPackageName();
+        packageName = asBoolean((Object) packageName) ? packageName : "";
+
+        List<ModifierNode> modifierNodeList = ctx.getNodeMetaData(TYPE_DECLARATION_MODIFIERS);
+        Objects.requireNonNull(modifierNodeList, "modifierNodeList should not be null");
+
+        ModifierManager modifierManager = new ModifierManager(modifierNodeList);
+        int modifiers = modifierManager.getClassModifiersOpValue();
+
+        boolean syntheticPublic = ((modifiers & Opcodes.ACC_SYNTHETIC) != 0);
+        modifiers &= ~Opcodes.ACC_SYNTHETIC;
+
+        final ClassNode outerClass = classNodeStack.peek();
+        ClassNode classNode;
+        String className = this.visitIdentifier(ctx.identifier());
+        if (asBoolean(ctx.ENUM())) {
+            classNode =
+                    EnumHelper.makeEnumNode(
+                            asBoolean(outerClass) ? className : packageName + className,
+                            modifiers, null, outerClass);
+        } else {
+            if (asBoolean(outerClass)) {
+                classNode =
+                        new InnerClassNode(
+                                outerClass,
+                                outerClass.getName() + "$" + className,
+                                modifiers | (outerClass.isInterface() ? Opcodes.ACC_STATIC : 0),
+                                ClassHelper.OBJECT_TYPE);
+            } else {
+                classNode =
+                        new ClassNode(
+                                packageName + className,
+                                modifiers,
+                                ClassHelper.OBJECT_TYPE);
+            }
+
+        }
+
+        this.configureAST(classNode, ctx);
+        classNode.putNodeMetaData(CLASS_NAME, className);
+        classNode.setSyntheticPublic(syntheticPublic);
+
+        if (asBoolean(ctx.TRAIT())) {
+            classNode.addAnnotation(new AnnotationNode(ClassHelper.make(GROOVY_TRANSFORM_TRAIT)));
+        }
+        classNode.addAnnotations(modifierManager.getAnnotations());
+        classNode.setGenericsTypes(this.visitTypeParameters(ctx.typeParameters()));
+
+        boolean isInterface = asBoolean(ctx.INTERFACE()) && !asBoolean(ctx.AT());
+        boolean isInterfaceWithDefaultMethods = false;
+
+        // declaring interface with default method
+        if (isInterface && this.containsDefaultMethods(ctx)) {
+            isInterfaceWithDefaultMethods = true;
+            classNode.addAnnotation(new AnnotationNode(ClassHelper.make(GROOVY_TRANSFORM_TRAIT)));
+            classNode.putNodeMetaData(IS_INTERFACE_WITH_DEFAULT_METHODS, true);
+        }
+
+        if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()) || isInterfaceWithDefaultMethods) { // class OR trait OR interface with default methods
+            classNode.setSuperClass(this.visitType(ctx.sc));
+            classNode.setInterfaces(this.visitTypeList(ctx.is));
+
+            this.initUsingGenerics(classNode);
+        } else if (isInterface) { // interface(NOT annotation)
+            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT);
+
+            classNode.setSuperClass(ClassHelper.OBJECT_TYPE);
+            classNode.setInterfaces(this.visitTypeList(ctx.scs));
+
+            this.initUsingGenerics(classNode);
+
+            this.hackMixins(classNode);
+        } else if (asBoolean(ctx.ENUM())) { // enum
+            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_ENUM | Opcodes.ACC_FINAL);
+
+            classNode.setInterfaces(this.visitTypeList(ctx.is));
+
+            this.initUsingGenerics(classNode);
+        } else if (asBoolean(ctx.AT())) { // annotation
+            classNode.setModifiers(classNode.getModifiers() | Opcodes.ACC_INTERFACE | Opcodes.ACC_ABSTRACT | Opcodes.ACC_ANNOTATION);
+
+            classNode.addInterface(ClassHelper.Annotation_TYPE);
+
+            this.hackMixins(classNode);
+        } else {
+            throw createParsingFailedException("Unsupported class declaration: " + ctx.getText(), ctx);
+        }
+
+        // we put the class already in output to avoid the most inner classes
+        // will be used as first class later in the loader. The first class
+        // there determines what GCL#parseClass for example will return, so we
+        // have here to ensure it won't be the inner class
+        if (asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT())) {
+            classNodeList.add(classNode);
+        }
+
+        int oldAnonymousInnerClassCounter = this.anonymousInnerClassCounter;
+        classNodeStack.push(classNode);
+        ctx.classBody().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+        this.visitClassBody(ctx.classBody());
+        classNodeStack.pop();
+        this.anonymousInnerClassCounter = oldAnonymousInnerClassCounter;
+
+        if (!(asBoolean(ctx.CLASS()) || asBoolean(ctx.TRAIT()))) {
+            classNodeList.add(classNode);
+        }
+
+        this.attachDocCommentAsMetaData(classNode, ctx);
+
+        return classNode;
+    }
+
+    @SuppressWarnings({"unchecked"})
+    private boolean containsDefaultMethods(ClassDeclarationContext ctx) {
+        List<MethodDeclarationContext> methodDeclarationContextList =
+                (List<MethodDeclarationContext>) ctx.classBody().classBodyDeclaration().stream()
+                .map(ClassBodyDeclarationContext::memberDeclaration)
+                .filter(Objects::nonNull)
+                .map(e -> (Object) e.methodDeclaration())
+                .filter(Objects::nonNull).reduce(new LinkedList<MethodDeclarationContext>(), (r, e) -> {
+                    MethodDeclarationContext methodDeclarationContext = (MethodDeclarationContext) e;
+
+                    if (createModifierManager(methodDeclarationContext).contains(DEFAULT)) {
+                        ((List) r).add(methodDeclarationContext);
+                    }
+
+                    return r;
+        });
+
+        return !methodDeclarationContextList.isEmpty();
+    }
+
+    @Override
+    public Void visitClassBody(ClassBodyContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        if (asBoolean(ctx.enumConstants())) {
+            ctx.enumConstants().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitEnumConstants(ctx.enumConstants());
+        }
+
+        ctx.classBodyDeclaration().stream().forEach(e -> {
+            e.putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitClassBodyDeclaration(e);
+        });
+
+        return null;
+    }
+
+    @Override
+    public List<FieldNode> visitEnumConstants(EnumConstantsContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        return ctx.enumConstant().stream()
+                .map(e -> {
+                    e.putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+                    return this.visitEnumConstant(e);
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public FieldNode visitEnumConstant(EnumConstantContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        InnerClassNode anonymousInnerClassNode = null;
+        if (asBoolean(ctx.anonymousInnerClassDeclaration())) {
+            ctx.anonymousInnerClassDeclaration().putNodeMetaData(ANONYMOUS_INNER_CLASS_SUPER_CLASS, classNode);
+            anonymousInnerClassNode = this.visitAnonymousInnerClassDeclaration(ctx.anonymousInnerClassDeclaration());
+        }
+
+        FieldNode enumConstant =
+                EnumHelper.addEnumConstant(
+                        classNode,
+                        this.visitIdentifier(ctx.identifier()),
+                        createEnumConstantInitExpression(ctx.arguments(), anonymousInnerClassNode));
+
+        this.visitAnnotationsOpt(ctx.annotationsOpt()).forEach(enumConstant::addAnnotation);
+
+        this.attachDocCommentAsMetaData(enumConstant, ctx);
+
+        return this.configureAST(enumConstant, ctx);
+    }
+
+    private Expression createEnumConstantInitExpression(ArgumentsContext ctx, InnerClassNode anonymousInnerClassNode) {
+        if (!asBoolean(ctx) && !asBoolean(anonymousInnerClassNode)) {
+            return null;
+        }
+
+        TupleExpression argumentListExpression = (TupleExpression) this.visitArguments(ctx);
+        List<Expression> expressions = argumentListExpression.getExpressions();
+
+        if (expressions.size() == 1) {
+            Expression expression = expressions.get(0);
+
+            if (expression instanceof NamedArgumentListExpression) { // e.g. SOME_ENUM_CONSTANT(a: "1", b: "2")
+                List<MapEntryExpression> mapEntryExpressionList = ((NamedArgumentListExpression) expression).getMapEntryExpressions();
+                ListExpression listExpression =
+                        new ListExpression(
+                                mapEntryExpressionList.stream()
+                                        .map(e -> (Expression) e)
+                                        .collect(Collectors.toList()));
+
+                if (asBoolean(anonymousInnerClassNode)) {
+                    listExpression.addExpression(
+                            this.configureAST(
+                                    new ClassExpression(anonymousInnerClassNode),
+                                    anonymousInnerClassNode));
+                }
+
+                if (mapEntryExpressionList.size() > 1) {
+                    listExpression.setWrapped(true);
+                }
+
+                return this.configureAST(listExpression, ctx);
+            }
+
+            if (!asBoolean(anonymousInnerClassNode)) {
+                return expression;
+            }
+
+            ListExpression listExpression = new ListExpression();
+            listExpression.addExpression(expression);
+            listExpression.addExpression(
+                    this.configureAST(
+                            new ClassExpression(anonymousInnerClassNode),
+                            anonymousInnerClassNode));
+
+            return this.configureAST(listExpression, ctx);
+        }
+
+        ListExpression listExpression = new ListExpression(expressions);
+        if (asBoolean(anonymousInnerClassNode)) {
+            listExpression.addExpression(
+                    this.configureAST(
+                            new ClassExpression(anonymousInnerClassNode),
+                            anonymousInnerClassNode));
+        }
+
+        if (asBoolean(ctx)) {
+            listExpression.setWrapped(true);
+        }
+
+        return asBoolean(ctx)
+                ? this.configureAST(listExpression, ctx)
+                : this.configureAST(listExpression, anonymousInnerClassNode);
+    }
+
+
+    @Override
+    public Void visitClassBodyDeclaration(ClassBodyDeclarationContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        if (asBoolean(ctx.memberDeclaration())) {
+            ctx.memberDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitMemberDeclaration(ctx.memberDeclaration());
+        } else if (asBoolean(ctx.block())) {
+            Statement statement = this.visitBlock(ctx.block());
+
+            if (asBoolean(ctx.STATIC())) { // e.g. static { }
+                classNode.addStaticInitializerStatements(Collections.singletonList(statement), false);
+            } else { // e.g.  { }
+                classNode.addObjectInitializerStatements(
+                        this.configureAST(
+                                this.createBlockStatement(statement),
+                                statement));
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public Void visitMemberDeclaration(MemberDeclarationContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        if (asBoolean(ctx.methodDeclaration())) {
+            ctx.methodDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitMethodDeclaration(ctx.methodDeclaration());
+        } else if (asBoolean(ctx.fieldDeclaration())) {
+            ctx.fieldDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitFieldDeclaration(ctx.fieldDeclaration());
+        } else if (asBoolean(ctx.classDeclaration())) {
+            ctx.classDeclaration().putNodeMetaData(TYPE_DECLARATION_MODIFIERS, this.visitModifiersOpt(ctx.modifiersOpt()));
+            ctx.classDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+            this.visitClassDeclaration(ctx.classDeclaration());
+        }
+
+        return null;
+    }
+
+    @Override
+    public GenericsType[] visitTypeParameters(TypeParametersContext ctx) {
+        if (!asBoolean(ctx)) {
+            return null;
+        }
+
+        return ctx.typeParameter().stream()
+                .map(this::visitTypeParameter)
+                .toArray(GenericsType[]::new);
+    }
+
+    @Override
+    public GenericsType visitTypeParameter(TypeParameterContext ctx) {
+        return this.configureAST(
+                new GenericsType(
+                        ClassHelper.make(this.visitClassName(ctx.className())),
+                        this.visitTypeBound(ctx.typeBound()),
+                        null
+                ),
+                ctx);
+    }
+
+    @Override
+    public ClassNode[] visitTypeBound(TypeBoundContext ctx) {
+        if (!asBoolean(ctx)) {
+            return null;
+        }
+
+        return ctx.type().stream()
+                .map(this::visitType)
+                .toArray(ClassNode[]::new);
+    }
+
+    @Override
+    public Void visitFieldDeclaration(FieldDeclarationContext ctx) {
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        Objects.requireNonNull(classNode, "classNode should not be null");
+
+        ctx.variableDeclaration().putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
+        this.visitVariableDeclaration(ctx.variableDeclaration());
+
+        return null;
+    }
+
+    private ConstructorCallExpression checkThisAndSuperConstructorCall(Statement statement) {
+        if (!(statement instanceof BlockStatement)) { // method code must be a BlockStatement
+            return null;
+        }
+
+        BlockStatement blockStatement = (BlockStatement) statement;
+        List<Statement> statementList = blockStatement.getStatements();
+
+        for (int i = 0, n = statementList.size(); i < n; i++) {
+            Statement s = statementList.get(i);
+            if (s instanceof ExpressionStatement) {
+                Expression expression = ((ExpressionStatement) s).getExpression();
+                if ((expression instanceof ConstructorCallExpression) && 0 != i) {
+                    return (ConstructorCallExpression) expression;
+                }
+            }
+        }
+
+        return null;
+    }
+
+    private ModifierManager createModifierManager(MethodDeclarationContext ctx) {
+        List<ModifierNode> modifierNodeList = Collections.emptyList();
+
+        if (asBoolean(ctx.modifiers())) {
+            modifierNodeList = this.visitModifiers(ctx.modifiers());
+        } else if (asBoolean(ctx.modifiersOpt())) {
+            modifierNodeList = this.visitModifiersOpt(ctx.modifiersOpt());
+        }
+
+        return new ModifierManager(modifierNodeList);
+    }
+
+    @Override
+    public MethodNode visitMethodDeclaration(MethodDeclarationContext ctx) {
+        ModifierManager modifierManager = createModifierManager(ctx);
+        String methodName = this.visitMethodName(ctx.methodName());
+        ClassNode returnType = this.visitReturnType(ctx.returnType());
+        Parameter[] parameters = this.visitFormalParameters(ctx.formalParameters());
+        ClassNode[] exceptions = this.visitQualifiedClassNameList(ctx.qualifiedClassNameList());
+
+        anonymousInnerClassesDefinedInMethodStack.push(new LinkedList<>());
+        Statement code = this.visitMethodBody(ctx.methodBody());
+        List<InnerClassNode> anonymousInnerClassList = anonymousInnerClassesDefinedInMethodStack.pop();
+
+        MethodNode methodNode;
+        // if classNode is not null, the method declaration is for class declaration
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+        if (asBoolean(classNode)) {
+            String className = classNode.getNodeMetaData(CLASS_NAME);
+            int modifiers = modifierManager.getClassMemberModifiersOpValue();
+
+            if (!asBoolean(ctx.returnType())
+                    && asBoolean(ctx.methodBody())
+                    && methodName.equals(className)) { // constructor declaration
+
+                ConstructorCallExpression thisOrSuperConstructorCallExpression = this.checkThisAndSuperConstructorCall(code);
+                if (asBoolean(thisOrSuperConstructorCallExpression)) {
+                    throw createParsingFailedException(thisOrSuperConstructorCallExpression.getText() + " should be the first statement in the constructor[" + methodName + "]", thisOrSuperConstructorCallExpression);
+                }
+
+                methodNode =
+                        classNode.addConstructor(
+                                modifiers,
+                                parameters,
+                                exceptions,
+                                code);
+
+            } else { // class memeber method declaration
+                if (asBoolean(ctx.elementValue())) { // the code of annotation method
+                    code = this.configureAST(
+                            new ExpressionStatement(
+                                    this.visitElementValue(ctx.elementValue())),
+                            ctx.elementValue());
+
+                }
+
+                modifiers |= classNode.isInterface() || (isTrue(classNode, IS_INTERFACE_WITH_DEFAULT_METHODS) && !modifierManager.contains(DEFAULT)) ? Opcodes.ACC_ABSTRACT : 0;
+                methodNode = classNode.addMethod(methodName, modifiers, returnType, parameters, exceptions, code);
+
+                methodNode.setAnnotationDefault(asBoolean(ctx.elementValue()));
+            }
+
+            modifierManager.attachAnnotations(methodNode);
+        } else { // script method declaration
+            methodNode =
+                    new MethodNode(
+                            methodName,
+                            modifierManager.contains(PRIVATE) ? Opcodes.ACC_PRIVATE : Opcodes.ACC_PUBLIC,
+                            returnType,
+                            parameters,
+                            exceptions,
+                            code);
+
+            modifierManager.processMethodNode(methodNode);
+        }
+        anonymousInnerClassList.stream().forEach(e -> e.setEnclosingMethod(methodNode));
+
+        methodNode.setGenericsTypes(this.visitTypeParameters(ctx.typeParameters()));
+        methodNode.setSyntheticPublic(
+                this.isSyntheticPublic(
+                        this.isAnnotationDeclaration(classNode),
+                        classNode instanceof EnumConstantClassNode,
+                        asBoolean(ctx.returnType()),
+                        modifierManager));
+
+        if (modifierManager.contains(STATIC)) {
+            Arrays.stream(methodNode.getParameters()).forEach(e -> e.setInStaticContext(true));
+            methodNode.getVariableScope().setInStaticContext(true);
+        }
+
+        this.configureAST(methodNode, ctx);
+
+        boolean isAbstractMethod = methodNode.isAbstract();
+        boolean hasMethodBody = asBoolean(methodNode.getCode());
+
+        if (9 == ctx.ct) { // script
+            if (isAbstractMethod || !hasMethodBody) { // method should not be declared abstract in the script
+                throw createParsingFailedException("You can not define a " + (isAbstractMethod ? "abstract" : "") + " method[" + methodNode.getName() + "] " + (!hasMethodBody ? "without method body" : "") + " in the script. Try " + (isAbstractMethod ? "removing the 'abstract'" : "") + (isAbstractMethod && !hasMethodBody ? " and" : "") + (!hasMethodBody ? " adding a method body" : ""), methodNode);
+            }
+        } else {
+            if (!isAbstractMethod && !hasMethodBody) { // non-abstract method without body in the non-script(e.g. class, enum, trait) is not allowed!
+                throw createParsingFailedException("You defined a method[" + methodNode.getName() + "] without body. Try adding a method body, or declare it abstract", methodNode);
+            }
+        }
+
+        this.attachDocCommentAsMetaData(methodNode, ctx);
+
+        return methodNode;
+    }
+
+    @Override
+    public String visitMethodName(MethodNameContext ctx) {
+        if (asBoolean(ctx.identifier())) {
+            return this.visitIdentifier(ctx.identifier());
+        }
+
+        if (asBoolean(ctx.stringLiteral())) {
+            return this.visitStringLiteral(ctx.stringLiteral()).getText();
+        }
+
+        throw createParsingFailedException("Unsupported method name: " + ctx.getText(), ctx);
+    }
+
+    @Override
+    public ClassNode visitReturnType(ReturnTypeContext ctx) {
+        if (!asBoolean(ctx)) {
+            return ClassHelper.OBJECT_TYPE;
+        }
+
+        if (asBoolean(ctx.type())) {
+            return this.visitType(ctx.type());
+        }
+
+        if (asBoolean(ctx.VOID())) {
+            return ClassHelper.VOID_TYPE;
+        }
+
+        throw createParsingFailedException("Unsupported return type: " + ctx.getText(), ctx);
+    }
+
+    @Override
+    public Statement visitMethodBody(MethodBodyContext ctx) {
+        if (!asBoolean(ctx)) {
+            return null;
+        }
+
+        return this.configureAST(this.visitBlock(ctx.block()), ctx);
+    }
+
+    @Override
+    public DeclarationListStatement visitLocalVariableDeclaration(LocalVariableDeclarationContext ctx) {
+        return this.configureAST(this.visitVariableDeclaration(ctx.variableDeclaration()), ctx);
+    }
+
+    @Override
+    public DeclarationListStatement visitVariableDeclaration(VariableDeclarationContext ctx) {
+        List<ModifierNode> modifierNodeList = Collections.emptyList();
+
+        if (asBoolean(ctx.variableModifiers())) {
+            modifierNodeList = this.visitVariableModifiers(ctx.variableModifiers());
+        } else if (asBoolean(ctx.variableModifiersOpt())) {
+            modifierNodeList = this.visitVariableModifiersOpt(ctx.variableModifiersOpt());
+        } else if (asBoolean(ctx.modifiers())) {
+            modifierNodeList = this.visitModifiers(ctx.modifiers());
+        } else if (asBoolean(ctx.modifiersOpt())) {
+            modifierNodeList = this.visitModifiersOpt(ctx.modifiersOpt());
+        }
+
+        ModifierManager modifierManager = new ModifierManager(modifierNodeList);
+
+        if (asBoolean(ctx.typeNamePairs())) { // e.g. def (int a, int b) = [1, 2]
+            if (!modifierManager.contains(DEF)) {
+                throw createParsingFailedException("keyword def is required to declare tuple, e.g. def (int a, int b) = [1, 2]", ctx);
+            }
+
+            return this.configureAST(
+                    new DeclarationListStatement(
+                            this.configureAST(
+                                    modifierManager.attachAnnotations(
+                                            new DeclarationExpression(
+                                                    new ArgumentListExpression(
+                                                            this.visitTypeNamePairs(ctx.typeNamePairs()).stream()
+                                                                    .peek(e -> modifierManager.processVariableExpression((VariableExpression) e))
+                                                                    .collect(Collectors.toList())
+                                                    ),
+                                                    this.createGroovyTokenByType(ctx.ASSIGN().getSymbol(), Types.ASSIGN),
+                                                    this.visitVariableInitializer(ctx.variableInitializer())
+                                            )
+                                    ),
+                                    ctx
+                            )
+                    ),
+                    ctx
+            );
+        }
+
+        ClassNode variableType = this.visitType(ctx.type());
+        ctx.variableDeclarators().putNodeMetaData(VARIABLE_DECLARATION_VARIABLE_TYPE, variableType);
+        List<DeclarationExpression> declarationExpressionList = this.visitVariableDeclarators(ctx.variableDeclarators());
+
+        // if classNode is not null, the variable declaration is for class declaration. In other words, it is a field declaration
+        ClassNode classNode = ctx.getNodeMetaData(CLASS_DECLARATION_CLASS_NODE);
+
+        if (asBoolean(classNode)) {
+            declarationExpressionList.stream().forEach(e -> {
+                VariableExpression variableExpression = (VariableExpression) e.getLeftExpression();
+
+                int modifiers = modifierManager.getClassMemberModifiersOpValue();
+
+                Expression initialValue = EmptyExpression.INSTANCE.equals(e.getRightExpression()) ? null : e.getRightExpression();
+                Object defaultValue = findDefaultValueByType(variableType);
+
+                if (classNode.isInterface()) {
+                    if (!asBoolean(initialValue)) {
+                        initialValue = !asBoolean(defaultValue) ? null : new ConstantExpression(defaultValue);
+                    }
+
+                    modifiers |= Opcodes.ACC_PUBLIC | Opcodes.ACC_STATIC | Opcodes.ACC_FINAL;
+                }
+
+                if (classNode.isInterface() || modifierManager.containsVisibilityModifier()) {
+                    FieldNode fieldNode =
+                            classNode.addField(
+                                    variableExpression.getName(),
+                                    modifiers,
+                                    variableType,
+                                    initialValue);
+                    modifierManager.attachAnnotations(fieldNode);
+
+                    this.attachDocCommentAsMetaData(fieldNode, ctx);
+
+                    this.configureAST(fieldNode, ctx);
+                } else {
+                    PropertyNode propertyNode =
+                            classNode.addProperty(
+                                    variableExpression.getName(),
+                                    modifiers | Opcodes.ACC_PUBLIC,
+                                    variableType,
+                                    initialValue,
+                                    null,
+                                    null);
+
+                    FieldNode fieldNode = propertyNode.getField();
+                    fieldNode.setModifiers(modifiers & ~Opcodes.ACC_PUBLIC | Opcodes.ACC_PRIVATE);
+                    fieldNode.setSynthetic(!classNode.isInterface());
+                    modifierManager.attachAnnotations(fieldNode);
+
+                    this.attachDocCommentAsMetaData(fieldNode, ctx);
+                    this.attachDocCommentAsMetaData(propertyNode, ctx);
+
+                    this.configureAST(fieldNode, ctx);
+                    this.configureAST(propertyNode, ctx);
+                }
+
+            });
+
+
+            return null;
+        }
+
+        declarationExpressionList.stream().forEach(e -> {
+            VariableExpression variableExpression = (VariableExpression) e.getLeftExpression();
+
+            modifierManager.processVariableExpression(variableExpression);
+            modifierManager.attachAnnotations(e);
+
+        });
+
+        int size = declarationExpressionList.size();
+        if (size > 0) {
+            DeclarationExpression declarationExpression = declarationExpressionList.get(0);
+
+            if (1 == size) {
+                this.configureAST(declarationExpression, ctx);
+            } else {
+                // Tweak start of first declaration
+                declarationExpression.setLineNumber(ctx.getStart().getLine());
+                declarationExpression.setColumnNumber(ctx.getStart().getCharPositionInLine() + 1);
+            }
+        }
+
+        return this.configureAST(new DeclarationListStatement(declarationExpressionList), ctx);
+    }
+
+    @Override
+    public List<Expression> visitTypeNamePairs(TypeNamePairsContext ctx) {
+        return ctx.typeNamePair().stream().map(this::visitTypeNamePair).collect(Collectors.toList());
+    }
+
+    @Override
+    public VariableExpression visitTypeNamePair(TypeNamePairContext ctx) {
+        return this.configureAST(
+                new VariableExpression(
+                        this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName(),
+                        this.visitType(ctx.type())),
+                ctx);
+    }
+
+    @Override
+    public List<DeclarationExpression> visitVariableDeclarators(VariableDeclaratorsContext ctx) {
+        ClassNode variableType = ctx.getNodeMetaData(VARIABLE_DECLARATION_VARIABLE_TYPE);
+        Objects.requireNonNull(variableType, "variableType should not be null");
+
+        return ctx.variableDeclarator().stream()
+                .map(e -> {
+                    e.putNodeMetaData(VARIABLE_DECLARATION_VARIABLE_TYPE, variableType);
+                    return this.visitVariableDeclarator(e);
+//                    return this.configureAST(this.visitVariableDeclarator(e), ctx);
+                })
+                .collect(Collectors.toList());
+    }
+
+    @Override
+    public DeclarationExpression visitVariableDeclarator(VariableDeclaratorContext ctx) {
+        ClassNode variableType = ctx.getNodeMetaData(VARIABLE_DECLARATION_VARIABLE_TYPE);
+        Objects.requireNonNull(variableType, "variableType should not be null");
+
+        org.codehaus.groovy.syntax.Token token;
+        if (asBoolean(ctx.ASSIGN())) {
+            token = createGroovyTokenByType(ctx.ASSIGN().getSymbol(), Types.ASSIGN);
+        } else {
+            token = new org.codehaus.groovy.syntax.Token(Types.ASSIGN, ASSIGN_STR, ctx.start.getLine(), 1);
+        }
+
+        return this.configureAST(
+                new DeclarationExpression(
+                        this.configureAST(
+                                new VariableExpression(
+                                        this.visitVariableDeclaratorId(ctx.variableDeclaratorId()).getName(),
+                                        variableType
+                                ),
+                                ctx.variableDeclaratorId()),
+                        token,
+                        this.visitVariableInitializer(ctx.variableInitializer())),
+                ctx);
+    }
+
+    @Override
+    public Expression visitVariableInitializer(VariableInitializerContext ctx) {
+        if (!asBoolean(ctx)) {
+            return EmptyExpression.INSTANCE;
+        }
+
+        if (asBoolean(ctx.arrayInitializer())) {
+            return this.configureAST(this.visitArrayInitializer(ctx.arrayInitializer()), ctx);
+        }
+
+        if (asBoolean(ctx.statementExpression())) {
+            return this.configureAST(
+                    ((ExpressionStatement) this.visit(ctx.statementExpression())).getExpression(),
+                    ctx);
+        }
+
+        if (asBoolean(ctx.standardLambda())) {
+            return this.configureAST(this.visitStandardLambda(ctx.standardLambda()), ctx);
+        }
+
+        throw createParsingFailedException("Unsupported variable initializer: " + ctx.getText(), ctx);
+    }
+
+    @Override
+    public ListExpression visitArrayInitializer(ArrayInitializerContext ctx) {
+        return this.configureAST(
+                new ListExpression(
+                        ctx.variableInitializer().stream()
+                                .map(this::visitVariableInitializer)
+                                .collect(Collectors.toList())),
+                ctx);
+    }
+
+
+    @Override
+    public Statement visitBlock(BlockContext ctx) {
+        if (!asBoolean(ctx)) {
+            return this.createBlockStatement();
+        }
+
+        return this.configureAST(
+                this.visitBlockStatementsOpt(ctx.blockStatementsOpt()),
+                ctx);
+    }
+
+
+    @Override
+    public ExpressionStatement visitNormalExprAlt(NormalExprAltContext ctx) {
+        return this.configureAST(new ExpressionStatement((Expression) this.visit(ctx.expression())), ctx);
+    }
+
+    @Override
+    public ExpressionStatement visitCommandExprAlt(CommandExprAltContext ctx) {
+        return this.configureAST(new ExpressionStatement(this.visitCommandExpression(ctx.commandExpression())), ctx);
+    }
+
+    @Override
+    public Expression visitCommandExpression(CommandExpressionContext ctx) {
+        Expression baseExpr = this.visitPathExpression(ctx.pathExpression());
+        Expression arguments = this.visitEnhancedArgumentList(ctx.enhancedArgumentList());
+
+        MethodCallExpression methodCallExpression;
+        if (baseExpr instanceof PropertyExpression) { // e.g. obj.a 1, 2
+            methodCallExpression =
+                    this.configureAST(
+                            this.createMethodCallExpression(
+                                    (PropertyExpression) baseExpr, arguments),
+                            arguments);
+
+        } else if (baseExpr instanceof MethodCallExpression && !isTrue(baseExpr, IS_INSIDE_PARENTHESES)) { // e.g. m {} a, b  OR  m(...) a, b
+            if (asBoolean(arguments)) {
+                // The error should never be thrown.
+                throw new GroovyBugError("When baseExpr is a instance of MethodCallExpression, which should follow NO argumentList");
+            }
+
+            methodCallExpression = (MethodCallExpression) baseExpr;
+        } else if (
+                !isTrue(baseExpr, IS_INSIDE_PARENTHESES)
+                        && (baseExpr instanceof VariableExpression /* e.g. m 1, 2 */
+                        || baseExpr instanceof GStringExpression /* e.g. "$m" 1, 2 */
+                        || (baseExpr instanceof ConstantExpression && isTrue(baseExpr, IS_STRING)) /* e.g. "m" 1, 2 */)
+                ) {
+            methodCallExpression =
+                    this.configureAST(
+                            this.createMethodCallExpression(baseExpr, arguments),
+                            arguments);
+        } else { // e.g. a[x] b, new A() b, etc.
+            methodCallExpression =
+                    this.configureAST(
+                            new MethodCallExpression(
+                                    baseExpr,
+                                    CALL_STR,
+                                    arguments
+                           

<TRUNCATED>

Mime
View raw message