You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2017/05/08 07:32:55 UTC
[21/23] groovy git commit: rename antlr4 parser to remove groovy-
prefix since that is by convention for modules
http://git-wip-us.apache.org/repos/asf/groovy/blob/eb2f9dde/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
deleted file mode 100644
index 8228ed2..0000000
--- a/subprojects/groovy-parser-antlr4/src/main/java/org/apache/groovy/parser/antlr4/AstBuilder.java
+++ /dev/null
@@ -1,4691 +0,0 @@
-/*
- * 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.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.AnnotationNode;
-import org.codehaus.groovy.ast.ClassHelper;
-import org.codehaus.groovy.ast.ClassNode;
-import org.codehaus.groovy.ast.ConstructorNode;
-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.Logger;
-
-import static org.apache.groovy.parser.antlr4.GroovyLangParser.*;
-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);
- this.groovydocManager = new GroovydocManager(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());
-
- for (StatementContext s : ctx.statement()) {
- Object e = this.visit(s);
- if (e instanceof DeclarationListStatement) { // local variable declaration
- for (Statement ds : ((DeclarationListStatement) e).getDeclarationStatements()) {
- moduleNode.addStatement(ds);
- }
- } else if (e instanceof Statement) {
- moduleNode.addStatement((Statement) e);
- } else if (e instanceof MethodNode) { // script method
- moduleNode.addMethod((MethodNode) e);
- }
- }
- for (ClassNode cl : this.classNodeList) {
- moduleNode.addClass(cl);
- }
- 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();
-
- for (AnnotationNode e : this.visitAnnotationsOpt(ctx.annotationsOpt())) {
- packageNode.addAnnotation(e);
- }
-
- return this.configureAST(packageNode, ctx);
- }
-
- @Override
- public ImportNode visitImportDeclaration(ImportDeclarationContext ctx) {
- 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<QualifiedNameElementContext> identifierList = new LinkedList<>(ctx.qualifiedName().qualifiedNameElement());
- int identifierListSize = identifierList.size();
- String name = identifierList.get(identifierListSize - 1).getText();
- StringBuilder builder = new StringBuilder();
- long limit = identifierListSize - 1;
- for (GroovyParserRuleContext groovyParserRuleContext : identifierList) {
- if (limit-- == 0) break;
- String text = groovyParserRuleContext.getText();
- if (builder.length() > 0) {
- builder.append(DOT_STR);
- }
- builder.append(text);
- }
- ClassNode classNode =
- ClassHelper.make(
- builder.toString());
- 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());
- }
- }
-
- return this.configureAST(importNode, ctx);
- }
-
- // statement { --------------------------------------------------------------------
- @Override
- public AssertStatement visitAssertStatement(AssertStatementContext 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 AssertStatement visitAssertStmtAlt(AssertStmtAltContext ctx) {
- return this.configureAST(this.visitAssertStatement(ctx.assertStatement()), 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, (Expression)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.expressionList())) {
- return this.translateExpressionList(ctx.expressionList());
- }
-
- throw createParsingFailedException("Unsupported for init: " + ctx.getText(), ctx);
- }
-
- @Override
- public Expression visitForUpdate(ForUpdateContext ctx) {
- if (!asBoolean(ctx)) {
- return EmptyExpression.INSTANCE;
- }
-
- return this.translateExpressionList(ctx.expressionList());
- }
-
- private Expression translateExpressionList(ExpressionListContext ctx) {
- List<Expression> expressionList = this.visitExpressionList(ctx);
-
- if (expressionList.size() == 1) {
- return this.configureAST(expressionList.get(0), ctx);
- } else {
- return this.configureAST(new ClosureListExpression(expressionList), 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 Pair<Parameter, Expression> visitClassicalForControl(ClassicalForControlContext ctx) {
- 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);
- }
-
- @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())) {
- for (ExpressionStatement e : this.visitResources(ctx.resources())) {
- tryCatchStatement.addResource(e);
- }
- }
-
- for (CatchClauseContext cc : ctx.catchClause()) {
- List<CatchStatement> list = this.visitCatchClause(cc);
- for (CatchStatement cs : list) {
- tryCatchStatement.addCatch(cs);
- }
- }
- 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) {
- List<ExpressionStatement> list = new ArrayList<>();
- for (ResourceContext resourceContext : ctx.resource()) {
- ExpressionStatement expressionStatement = visitResource(resourceContext);
- list.add(expressionStatement);
- }
- return list;
- }
-
- @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*
-
- List<CatchStatement> list = new ArrayList<>();
- for (ClassNode e : this.visitCatchType(ctx.catchType())) {
- CatchStatement catchStatement = 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());
- list.add(catchStatement);
- }
- return list;
- }
-
- @Override
- public List<ClassNode> visitCatchType(CatchTypeContext ctx) {
- if (!asBoolean(ctx)) {
- return Collections.singletonList(ClassHelper.OBJECT_TYPE);
- }
-
- List<ClassNode> list = new ArrayList<>();
- for (QualifiedClassNameContext qualifiedClassNameContext : ctx.qualifiedClassName()) {
- ClassNode classNode = visitQualifiedClassName(qualifiedClassNameContext);
- list.add(classNode);
- }
- return list;
- }
-
-
- @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 = new LinkedList<>();
- for (SwitchBlockStatementGroupContext c : ctx.switchBlockStatementGroup()) {
- statementList.addAll(this.visitSwitchBlockStatementGroup(c));
- }
-
- List<CaseStatement> caseStatementList = new LinkedList<>();
- List<Statement> defaultStatementList = new LinkedList<>();
-
- for (Statement e : statementList) {
- 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);
-
- List<Statement> statementList = new ArrayList<>(4);
- for (SwitchLabelContext e : ctx.switchLabel()) {
- Pair<Token, Expression> pair = this.visitSwitchLabel(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(), (Expression) 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(this, 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);
- }
-
- groovydocManager.handle(classNode, ctx);
-
- return classNode;
- }
-
- @SuppressWarnings({"unchecked"})
- private boolean containsDefaultMethods(ClassDeclarationContext ctx) {
- for (ClassBodyDeclarationContext c : ctx.classBody().classBodyDeclaration()) {
- MemberDeclarationContext memberDeclarationContext = c.memberDeclaration();
- if(memberDeclarationContext != null) {
- MethodDeclarationContext methodDeclarationContext = memberDeclarationContext.methodDeclaration();
- if (methodDeclarationContext != null) {
- if (createModifierManager(methodDeclarationContext).contains(DEFAULT)) {
- return true;
- }
- }
- }
- }
- return false;
- }
-
- @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());
- }
-
- for (ClassBodyDeclarationContext e : ctx.classBodyDeclaration()) {
- 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");
-
- List<FieldNode> list = new LinkedList<>();
- for (EnumConstantContext e : ctx.enumConstant()) {
- e.putNodeMetaData(CLASS_DECLARATION_CLASS_NODE, classNode);
- list.add(visitEnumConstant(e));
- }
- return list;
- }
-
- @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));
-
- for (AnnotationNode a : this.visitAnnotationsOpt(ctx.annotationsOpt())) {
- enumConstant.addAnnotation(a);
- }
-
- groovydocManager.handle(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();
- List<Expression> list = new ArrayList<>();
- for (MapEntryExpression e : mapEntryExpressionList) {
- Expression e1 = (Expression) e;
- list.add(e1);
- }
- ListExpression listExpression =
- new ListExpression(
- list);
-
- 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)) {
- if (expression instanceof ListExpression) {
- ListExpression listExpression = new ListExpression();
- listExpression.addExpression(expression);
-
- return this.configureAST(listExpression, ctx);
- }
-
- return expression;
- }
-
- ListExpression listExpression = new ListExpression();
-
- if (expression instanceof ListExpression) {
- ((ListExpression) expression).getExpressions().forEach(listExpression::addExpression);
- } else {
- 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;
- }
-
- List<GenericsType> list = new ArrayList<>();
- for (TypeParameterContext typeParameterContext : ctx.typeParameter()) {
- GenericsType genericsType = visitTypeParameter(typeParameterContext);
- list.add(genericsType);
- }
- return list.toArray(new GenericsType[0]);
- }
-
- @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;
- }
-
- List<ClassNode> list = new ArrayList<>();
- for (TypeContext typeContext : ctx.type()) {
- ClassNode classNode = visitType(typeContext);
- list.add(classNode);
- }
- return list.toArray(new ClassNode[0]);
- }
-
- @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(this, modifierNodeList);
- }
-
- private void validateParametersOfMethodDeclaration(Parameter[] parameters, ClassNode classNode) {
- if (!classNode.isInterface()) {
- return;
- }
-
- Arrays.stream(parameters).forEach(e -> {
- if (e.hasInitialExpression()) {
- throw createParsingFailedException("Cannot specify default value for method parameter '" + e.getName() + " = " + e.getInitialExpression().getText() + "' inside an interface", e);
- }
- });
- }
-
- @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<InnerClassNode>());
- 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)) {
- validateParametersOfMethodDeclaration(parameters, classNode);
-
- methodNode = createConstructorOrMethodNodeForClass(ctx, modifierManager, methodName, returnType, parameters, exceptions, code, classNode);
- } else { // script method declaration
- methodNode = createScriptMethodNode(modifierManager, methodName, returnType, parameters, exceptions, code);
- }
- for (InnerClassNode e : anonymousInnerClassList) {
- 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)) {
- for (Parameter e : methodNode.getParameters()) {
- e.setInStaticContext(true);
- }
- methodNode.getVariableScope().setInStaticContext(true);
- }
-
- this.configureAST(methodNode, ctx);
-
- validateMethodDeclaration(ctx, methodNode, modifierManager, classNode);
-
- groovydocManager.handle(methodNode, ctx);
-
- return methodNode;
- }
-
- private void validateMethodDeclaration(MethodDeclarationContext ctx, MethodNode methodNode, ModifierManager modifierManager, ClassNode classNode) {
- 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);
- }
-
- boolean isInterfaceOrAbstractClass = asBoolean(classNode) && classNode.isAbstract() && !classNode.isAnnotationDefinition();
- if (isInterfaceOrAbstractClass && !modifierManager.contains(DEFAULT) && isAbstractMethod && hasMethodBody) {
- throw createParsingFailedException("You defined an abstract method[" + methodNode.getName() + "] with body. Try removing the method body" + (classNode.isInterface() ? ", or declare it default" : ""), methodNode);
- }
- }
-
- modifierManager.validate(methodNode);
-
- if (methodNode instanceof ConstructorNode) {
- modifierManager.validate((ConstructorNode) methodNode);
- }
- }
-
- private MethodNode createScriptMethodNode(ModifierManager modifierManager, String methodName, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code) {
- MethodNode methodNode;
- methodNode =
- new MethodNode(
- methodName,
- modifierManager.contains(PRIVATE) ? Opcodes.ACC_PRIVATE : Opcodes.ACC_PUBLIC,
- returnType,
- parameters,
- exceptions,
- code);
-
- modifierManager.processMethodNode(methodNode);
- return methodNode;
- }
-
- private MethodNode createConstructorOrMethodNodeForClass(MethodDeclarationContext ctx, ModifierManager modifierManager, String methodName, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code, ClassNode classNode) {
- MethodNode methodNode;
- String className = classNode.getNodeMetaData(CLASS_NAME);
- int modifiers = modifierManager.getClassMemberModifiersOpValue();
-
- if (!asBoolean(ctx.returnType())
- && asBoolean(ctx.methodBody())
- && methodName.equals(className)) { // constructor declaration
-
- methodNode = createConstructorNodeForClass(methodName, parameters, exceptions, code, classNode, modifiers);
- } else { // class memeber method declaration
- methodNode = createMethodNodeForClass(ctx, modifierManager, methodName, returnType, parameters, exceptions, code, classNode, modifiers);
- }
-
- modifierManager.attachAnnotations(methodNode);
- return methodNode;
- }
-
- private MethodNode createMethodNodeForClass(MethodDeclarationContext ctx, ModifierManager modifierManager, String methodName, ClassNode returnType, Parameter[] parameters, ClassNode[] exceptions, Statement code, ClassNode classNode, int modifiers) {
- MethodNode methodNode;
- if (asBoolean(ctx.elementValue())) { // the code of annotation method
- code = this.configureAST(
- new ExpressionStatement(
- this.visitElementValue(ctx.elementValue())),
- ctx.elementValue());
-
- }
-
- modifiers |= !modifierManager.contains(STATIC) && (classNode.isInterface() || (isTrue(classNode, IS_INTERFACE_WITH_DEFAULT_METHODS) && !modifierManager.contains(DEFAULT))) ? Opcodes.ACC_ABSTRACT : 0;
-
- checkWhetherMethodNodeWithSameSignatureExists(classNode, methodName, parameters, ctx);
-
- methodNode = classNode.addMethod(methodName, modifiers, returnType, parameters, exceptions, code);
-
- methodNode.setAnnotationDefault(asBoolean(ctx.elementValue()));
- return methodNode;
- }
-
- private void checkWhetherMethodNodeWithSameSignatureExists(ClassNode classNode, String methodName, Parameter[] parameters, MethodDeclarationContext ctx) {
- MethodNode sameSigMethodNode = classNode.getDeclaredMethod(methodName, parameters);
-
- if (null == sameSigMethodNode) {
- return;
- }
-
- throw createParsingFailedException("The method " + sameSigMethodNode.getText() + " duplicates another method of the same signature", ctx);
- }
-
- private ConstructorNode createConstructorNodeForClass(String methodName, Parameter[] parameters, ClassNode[] exceptions, Statement code, ClassNode classNode, int modifiers) {
- ConstructorCallExpression thisOrSuperConstructorCallExpression = this.checkThisAndSuperConstructorCall(code);
- if (asBoolean(thisOrSuperConstructorCallExpression)) {
- throw createParsingFailedException(thisOrSuperConstructorCallExpression.getText() + " should be the first statement in the constructor[" + methodName + "]", thisOrSuperConstructorCallExpression);
- }
-
- return classNode.addConstructor(
- modifiers,
- parameters,
- exceptions,
- code);
- }
-
- @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);
- }
-
- private ModifierManager createModifierManager(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());
- }
-
- return new ModifierManager(this, modifierNodeList);
- }
-
- private DeclarationListStatement createMultiAssignmentDeclarationListStatement(VariableDeclarationContext ctx, ModifierManager modifierManager) {
- if (!modifierManager.contains(DEF)) {
- throw createParsingFailedException("keyword def is required to declare tuple, e.g. def (int a, int b) = [1, 2]", ctx);
- }
-
- List<Expression> list = new ArrayList<>();
- for (Expression e : this.visitTypeNamePairs(ctx.typeNamePairs())) {
- modifierManager.processVariableExpression((VariableExpression) e);
- list.add(e);
- }
- return this.configureAST(
- new DeclarationListStatement(
- this.configureAST(
- modifierManager.attachAnnotations(
- new DeclarationExpression(
- new ArgumentListExpression(
- list
- ),
- this.createGroovyTokenByType(ctx.ASSIGN().getSymbol(), Types.ASSIGN),
- this.visitVariableInitializer(ctx.variableInitializer())
- )
- ),
- ctx
- )
- ),
- ctx
- );
- }
-
- @Override
- public DeclarationListStatement visitVariableDeclaration(VariableDeclarationContext ctx) {
- ModifierManager modifierManager = this.createModifierManager(ctx);
-
- if (asBoolean(ctx.typeNamePairs())) { // e.g. def (int a, int b) = [1, 2]
- return this.createMultiAssignmentDeclarationListStatement(ctx, modifierManager);
- }
-
- 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)) {
- return createFieldDeclarationListStatement(ctx, modifierManager, variableType, declarationExpressionList, classNode);
- }
-
- for (DeclarationExpression e : declarationExpressionList) {
- 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);
- }
-
- private DeclarationListStatement createFieldDeclarationListStatement(VariableDeclarationContext ctx, ModifierManager modifierManager, ClassNode variableType, List<DeclarationExpression> declarationExpressionList, ClassNode classNode) {
- for (DeclarationExpression e : declarationExpressionList) {
- 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);
-
- groovydocManager.handle(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);
-
- groovydocManager.handle(fieldNode, ctx);
- groovydocManager.handle(propertyNode, ctx);
-
- this.configureAST(fieldNode, ctx);
- this.configureAST(propertyNode, ctx);
- }
-
- }
-
- return null;
- }
-
- @Override
- public List<Expression> visitTypeNamePairs(TypeNamePairsContext ctx) {
- List<Expression> list = new ArrayList<>();
- for (TypeNamePairContext typeNamePairContext : ctx.typeNamePair()) {
- VariableExpression variableExpression = visitTypeNamePair(typeNamePairContext);
- list.add(variableExpression);
- }
- return list;
- }
-
- @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");
-
- List<DeclarationExpression> list = new LinkedList<>();
- for (VariableDeclaratorContext e : ctx.variableDeclarator()) {
- e.putNodeMetaData(VARIABLE_DECLARATION_VARIABLE_TYPE, variableType);
- list.add(this.visitVariableDeclarator(e));
- }
- return list;
- }
-
- @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.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 List<Expression> visitVariableInitializers(VariableInitializersContext ctx) {
- if (!asBoolean(ctx)) {
- return Collections.emptyList();
- }
-
- List<Expression> list = new ArrayList<>();
- for (VariableInitializerContext variableInitializerContext : ctx.variableInitializer()) {
- Expression expression = visitVariableInitializer(variableInitializerContext);
- list.add(expression);
- }
- return list;
- }
-
- @Override
- public List<Expression> visitArrayInitializer(ArrayInitializerContext ctx) {
- if (!asBoolean(ctx)) {
- return Collections.emptyList();
- }
-
- return this.visitVariableInitializers(ctx.variableInitializers());
- }
-
- @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
- ),
- arguments
- );
-
- methodCallExpression.setImplicitThis(false);
- }
-
- if (!asBoolean(ctx.commandArgument())) {
- return this.configureAST(methodCallExpression, ctx);
- }
-
- Expression r = methodCallExpression;
- for (CommandArgumentContext commandArgumentContext : ctx.commandArgument()) {
- commandArgumentContext.putNodeMetaData(CMD_EXPRESSION_BASE_EXPR, r);
- r = this.visitCommandArgument(commandArgumentContext);
- }
-
- return this.configureAST(r, ctx);
- }
-
- @Override
- public Expression visitCommandArgument(CommandArgumentContext ctx) {
- // e.g. x y a b we call "x y" as the base expression
- Expression baseExpr = ctx.getNodeMetaData(CMD_EXPRESSION_BASE_EXPR);
-
- Expression primaryExpr = (Expression) this.visit(ctx.primary());
-
- if (asBoolean(ctx.enhancedArgumentList())) { // e.g. x y a b
- if (baseExpr instanceof PropertyExpression) { // the branch should never reach, because a.b.c will be parsed as a path expression, not a method call
- throw createParsingFailedException("Unsupported command argument: " + ctx.getText(), ctx);
- }
-
- // the following code will process "a b" of "x y a b"
- MethodCallExpression methodCallExpression =
- new MethodCallExpression(
- baseExpr,
- this.createConstantExpression(primaryExpr),
- this.visitEnhancedArgumentList(ctx.enhancedArgumentList())
- );
- methodCallExpression.setImplicitThis(false);
-
- return this.configureAST(methodCallExpression, ctx);
- } else if (asBoolean(ctx.pathElement())) { // e.g. x y a.b
- Expression pathExpression =
- this.createPathExpression(
- this.configureAST(
- new PropertyExpression(baseExpr, this.createConstantExpression(primaryExpr)),
- primaryExpr
- ),
- ctx.pathElement()
- );
-
- return this.configureAST(pathExpression, ctx);
- }
-
- // e.g. x y a
- return this.configureAST(
- new PropertyExpression(
- baseExpr,
- primaryExpr instanceof VariableExpression
- ? this.createConstantExpression(primaryExpr)
- : primaryExpr
- ),
- primaryExpr
- );
- }
-
-
- // expression { --------------------------------------------------------------------
-
- @Override
- public ClassNode visitCastParExpression(CastParExpressionContext ctx) {
- return this.visitType(ctx.type());
- }
-
- @Override
- public Expression visitParExpression(ParExpressionContext ctx) {
- Expression expression;
-
- if (asBoolean(ctx.statementExpression())) {
- expression = ((ExpressionStatement) this.visit(ctx.statementExpression())).getExpression();
- } else if (asBoolean(ctx.standardLambda())) {
- expression = this.visitStandardLambda(ctx.standardLambda());
- } else {
- throw createParsingFailedException("Unsupported parentheses expression: " + ctx.getText(), ctx);
- }
-
- expression.putNodeMetaData(IS_INSIDE_PARENTHESES, true);
-
- Integer insideParenLevel = expression.getNodeMetaData(INSIDE_PARENTHESES_LEVEL);
- if (asBoolean((Object) insideParenLevel)) {
- insideParenLevel++;
- } else {
- insideParenLevel = 1;
- }
- expression.putNodeMetaData(INSIDE_PARENTHESES_LEVEL, insideParenLevel);
-
- return this.configureAST(expression, ctx);
- }
-
- @Override
- public Expression visitPathExpression(PathExpressionContext ctx) {
- return this.configureAST(
- this.createPathExpression((Expression) this.visit(ctx.primary()), ctx.pathElement()),
- ctx);
- }
-
- @Override
- public Expression visitPathElement(PathElementContext ctx) {
- Expression baseExpr = ctx.getNodeMetaData(PATH_EXPRESSION_BASE_EXPR);
- Objects.requireNonNull(baseExpr, "baseExpr is required!");
-
- if (asBoolean(ctx.namePart())) {
- Expression namePartExpr = this.visitNamePart(ctx.namePart());
- GenericsType[] genericsTypes = this.visitNonWildcardTypeArguments(ctx.nonWildcardTypeArguments());
-
-
- if (asBoolean(ctx.DOT())) {
- if (asBoolean(ctx.AT())) { // e.g. obj.@a
- return this.configureAST(new AttributeExpression(baseExpr, namePartExpr), ctx);
- } else { // e.g. obj.p
- PropertyExpression propertyExpression = new PropertyExpression(baseExpr, namePartExpr);
- propertyExpression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES, genericsTypes);
-
- return this.configureAST(propertyExpression, ctx);
- }
- } else if (asBoolean(ctx.SAFE_DOT())) {
- if (asBoolean(ctx.AT())) { // e.g. obj?.@a
- return this.configureAST(new AttributeExpression(baseExpr, namePartExpr, true), ctx);
- } else { // e.g. obj?.p
- PropertyExpression propertyExpression = new PropertyExpression(baseExpr, namePartExpr, true);
- propertyExpression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES, genericsTypes);
-
- return this.configureAST(propertyExpression, ctx);
- }
- } else if (asBoolean(ctx.METHOD_POINTER())) { // e.g. obj.&m
- return this.configureAST(new MethodPointerExpression(baseExpr, namePartExpr), ctx);
- } else if (asBoolean(ctx.METHOD_REFERENCE())) { // e.g. obj::m
- return this.configureAST(new MethodReferenceExpression(baseExpr, namePartExpr), ctx);
- } else if (asBoolean(ctx.SPREAD_DOT())) {
- if (asBoolean(ctx.AT())) { // e.g. obj*.@a
- AttributeExpression attributeExpression = new AttributeExpression(baseExpr, namePartExpr, true);
-
- attributeExpression.setSpreadSafe(true);
-
- return this.configureAST(attributeExpression, ctx);
- } else { // e.g. obj*.p
- PropertyExpression propertyExpression = new PropertyExpression(baseExpr, namePartExpr, true);
- propertyExpression.putNodeMetaData(PATH_EXPRESSION_BASE_EXPR_GENERICS_TYPES, genericsTypes);
-
- propertyExpression.setSpreadSafe(true);
-
- return this.configureAST(propertyExpression, ctx);
- }
- }
- }
-
- if (asBoolean(ctx.indexPropertyArgs())) { // e.g. list[1, 3, 5]
- Pair<Token, Expression> pair = this.visitIndexPropertyArgs(ctx.indexPropertyArgs());
-
- return this.configureAST(
- new BinaryExpression(baseExpr, createGroovyToken(pair.getKey()), pair.getValue(), asBoolean(ctx.indexPropertyArgs().QUESTION())),
- ctx);
- }
-
- if (asBoolean(ctx.namedPropertyArgs())) { // this is a special way to new instance, e.g. Person(name: 'Daniel.Sun', location: 'Shanghai')
- List<MapEntryExpression> mapEntryExpressionList =
- this.visitNamedPropertyArgs(ctx.namedPropertyArgs());
-
- Expression right;
- if (mapEntryExpressionList.size() == 1) {
- MapEntryExpression mapEntryExpression = mapEntryExpressionList.get(0);
-
- if (mapEntryExpression.getKeyExpression() instanceof SpreadMapExpression) {
- right = mapEntryExpression.getKeyExpression();
- } else {
- right = mapEntryExpression;
- }
- } else {
- List<Expression> list = new LinkedList<>();
- for (MapEntryExpression e : mapEntryExpressionList) {
- list.add(e.getKeyExpression() instanceof SpreadMapExpression ?
- e.getKeyExpression() : e);
- }
- ListExpression listExpression = this.configureAST(new ListExpression(list), ctx.namedPropertyArgs());
- listExpression.setWrapped(true);
- right = listExpression;
- }
-
- return this.configureAST(
- new BinaryExpression(baseExpr, createGroovyToken(ctx.namedPropertyArgs().LBRACK().getSymbol()), right),
- ctx);
- }
-
- if (asBoolean(ctx.arguments())) {
- Expression argumentsExpr = this.visitArguments(ctx.arguments());
-
- if (isTrue(baseExpr, IS_INSIDE_PARENTHESES)) { // e.g. (obj.x)(), (obj.@x)()
- MethodCallExpression methodCallExpression =
- new MethodCallExpression(
- baseExpr,
- CALL_STR,
- argumentsExpr
- );
-
- methodCallExpression.setImplicitThis(false);
-
- return this.configureAST(methodCallExpression, ctx);
- }
-
- if (baseExpr instanceof AttributeExpression) { // e.g. obj.@a(1, 2)
- AttributeExpression attributeExpression = (AttributeExpression) baseExpr;
- attributeExpression.setSpreadSafe(false); // whether attributeExpression is spread safe or not, we must reset it as false
-
- MethodCallExpression methodCallExpression =
- new MethodCallExpression(
- attributeExpression,
- CALL_STR,
- argumentsExpr
- );
-
- return this.configureAST(methodCallExpression, ctx);
- }
-
- if (baseExpr instanceof PropertyExpression) { // e.g. obj.a(1, 2)
- MethodCallExpression methodCallExpression =
- this.createMethodCallExpression((PropertyExpression) baseExpr, argumentsExpr);
-
- return this.configureAST(methodCallExpression, ctx);
- }
-
- if (baseExpr instanceof VariableExpression) { // void and primitive type AST node must be an instance of VariableExpression
- String baseExprText = baseExpr.getText();
- if (VOID_STR.equals(baseExprText)) { // e.g. void()
- MethodCallExpression methodCallExpression =
- new MethodCallExpression(
- this.createConstantExpression(baseExpr),
- CALL_STR,
- argumentsExpr
- );
-
- methodCallExpression.setImplicitThis(false);
-
- return this.configureAST(methodCallExpression, ctx);
- } else if (PRIMITIVE_TYPE_SET.contains(baseExprText)) { // e.g. int(), long(), float(), etc.
- throw createParsingFailedException("Primitive type literal: " + baseExprText + " cannot be used as a method name", ctx);
- }
- }
-
- if (baseExpr instanceof VariableExpression
<TRUNCATED>