You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by em...@apache.org on 2022/04/30 19:45:31 UTC
[groovy] 02/02: minor refactor
This is an automated email from the ASF dual-hosted git repository.
emilles pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git
commit e183dc8e04a8ca8762e85e21ac3ee0c03138b6e1
Author: Eric Milles <er...@thomsonreuters.com>
AuthorDate: Sat Apr 30 14:41:47 2022 -0500
minor refactor
---
.../antlr4/TryWithResourcesASTTransformation.java | 453 +++++++++------------
1 file changed, 190 insertions(+), 263 deletions(-)
diff --git a/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java b/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
index 11c2f08fc6..624666c8d8 100644
--- a/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
+++ b/src/main/java/org/apache/groovy/parser/antlr4/TryWithResourcesASTTransformation.java
@@ -20,10 +20,7 @@ package org.apache.groovy.parser.antlr4;
import org.codehaus.groovy.ast.ClassHelper;
import org.codehaus.groovy.ast.Parameter;
-import org.codehaus.groovy.ast.expr.ArgumentListExpression;
import org.codehaus.groovy.ast.expr.BinaryExpression;
-import org.codehaus.groovy.ast.expr.BooleanExpression;
-import org.codehaus.groovy.ast.expr.ConstantExpression;
import org.codehaus.groovy.ast.expr.DeclarationExpression;
import org.codehaus.groovy.ast.expr.Expression;
import org.codehaus.groovy.ast.expr.MethodCallExpression;
@@ -32,61 +29,81 @@ import org.codehaus.groovy.ast.stmt.BlockStatement;
import org.codehaus.groovy.ast.stmt.CatchStatement;
import org.codehaus.groovy.ast.stmt.EmptyStatement;
import org.codehaus.groovy.ast.stmt.ExpressionStatement;
-import org.codehaus.groovy.ast.stmt.IfStatement;
import org.codehaus.groovy.ast.stmt.Statement;
-import org.codehaus.groovy.ast.stmt.ThrowStatement;
import org.codehaus.groovy.ast.stmt.TryCatchStatement;
-import org.codehaus.groovy.syntax.Types;
import org.objectweb.asm.Opcodes;
-import java.util.Collections;
-import java.util.List;
-
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ASSIGN;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.assignS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.binX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.block;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.callX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.catchS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.declS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.ifElseS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.localVarX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.notNullX;
import static org.codehaus.groovy.ast.tools.GeneralUtils.nullX;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.stmt;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.throwS;
import static org.codehaus.groovy.ast.tools.GeneralUtils.tryCatchS;
+import static org.codehaus.groovy.ast.tools.GeneralUtils.varX;
import static org.codehaus.groovy.runtime.DefaultGroovyMethods.asBoolean;
-import static org.codehaus.groovy.syntax.Token.newSymbol;
/**
* Transform try-with-resources to try-catch-finally
* Reference JLS "14.20.3. try-with-resources"(https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html)
*/
public class TryWithResourcesASTTransformation {
- private AstBuilder astBuilder;
- public TryWithResourcesASTTransformation(AstBuilder astBuilder) {
+ public TryWithResourcesASTTransformation(final AstBuilder astBuilder) {
this.astBuilder = astBuilder;
}
+ private AstBuilder astBuilder;
+
+ private int resourceCount;
+ private String nextResourceName() {
+ return "__$$resource" + resourceCount++;
+ }
+
+ private int throwableCount;
+ private String nextThrowableName() {
+ return "__$$t" + throwableCount++;
+ }
+
+ private int primaryExCount;
+ private String nextPrimaryExName() {
+ return "__$$primaryExc" + primaryExCount++;
+ }
+
+ private int suppressedExCount;
+ private String nextSuppressedExName() {
+ return "__$$suppressedExc" + suppressedExCount++;
+ }
+
+ //--------------------------------------------------------------------------
/**
- * Reference JLS "14.20.3. try-with-resources"(https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html)
- *
* @param tryCatchStatement the try-with-resources statement to transform
- * @return try-catch-finally statement, which contains no resources clause
+ * @return try-catch-finally statement which contains no resources clause
*/
- public Statement transform(TryCatchStatement tryCatchStatement) {
+ public Statement transform(final TryCatchStatement tryCatchStatement) {
if (!asBoolean(tryCatchStatement.getResourceStatements())) {
return tryCatchStatement;
}
-
- if (this.isBasicTryWithResourcesStatement(tryCatchStatement)) {
- return this.transformBasicTryWithResourcesStatement(tryCatchStatement);
+ if (isBasicTryWithResourcesStatement(tryCatchStatement)) {
+ return transformBasicTryWithResourcesStatement(tryCatchStatement);
} else {
- return this.transformExtendedTryWithResourcesStatement(tryCatchStatement);
+ return transformExtendedTryWithResourcesStatement(tryCatchStatement);
}
}
- private boolean isBasicTryWithResourcesStatement(TryCatchStatement tryCatchStatement) {
- if (tryCatchStatement.getFinallyStatement() instanceof EmptyStatement &&
- !asBoolean(tryCatchStatement.getCatchStatements())) {
- return true;
- }
-
- return false;
+ private boolean isBasicTryWithResourcesStatement(final TryCatchStatement tryCatchStatement) {
+ return (!asBoolean(tryCatchStatement.getCatchStatements())
+ && tryCatchStatement.getFinallyStatement() instanceof EmptyStatement);
}
- private ExpressionStatement makeVariableDeclarationFinal(ExpressionStatement variableDeclaration) {
+ private Statement makeVariableDeclarationFinal(final ExpressionStatement variableDeclaration) {
if (!asBoolean(variableDeclaration)) {
return variableDeclaration;
}
@@ -95,268 +112,188 @@ public class TryWithResourcesASTTransformation {
throw new IllegalArgumentException("variableDeclaration is not a declaration statement");
}
- DeclarationExpression declarationExpression = (DeclarationExpression) variableDeclaration.getExpression();
- if (!(declarationExpression.getLeftExpression() instanceof VariableExpression)) {
+ Expression targetExpression = ((DeclarationExpression) variableDeclaration.getExpression()).getLeftExpression();
+ if (!(targetExpression instanceof VariableExpression)) {
throw astBuilder.createParsingFailedException("The expression statement is not a variable delcaration statement", variableDeclaration);
}
- VariableExpression variableExpression = (VariableExpression) declarationExpression.getLeftExpression();
+ VariableExpression variableExpression = (VariableExpression) targetExpression;
variableExpression.setModifiers(variableExpression.getModifiers() | Opcodes.ACC_FINAL);
return variableDeclaration;
}
- private int primaryExcCnt = 0;
- private String genPrimaryExcName() {
- return "__$$primaryExc" + primaryExcCnt++;
- }
-
- /*
- * try ResourceSpecification
- * Block
- * Catchesopt
- * Finallyopt
- *
- * **The above AST should be transformed to the following AST**
- *
- * try {
- * try ResourceSpecification
- * Block
- * }
- * Catchesopt
- * Finallyopt
+ /**
+ * Transforms:
+ * <pre>
+ * try ResourceSpecification
+ * Block
+ * Catchesopt
+ * Finallyopt
+ * </pre>
+ * into:
+ * <pre>
+ * try {
+ * try ResourceSpecification
+ * Block
+ * }
+ * Catchesopt
+ * Finallyopt
+ * </pre>
*/
- private Statement transformExtendedTryWithResourcesStatement(TryCatchStatement tryCatchStatement) {
+ private Statement transformExtendedTryWithResourcesStatement(final TryCatchStatement tryCatchFinally) {
/*
- * try ResourceSpecification
- * Block
+ * try ResourceSpecification
+ * Block
*/
- TryCatchStatement newTryWithResourcesStatement = tryCatchS(tryCatchStatement.getTryStatement());
- tryCatchStatement.getResourceStatements().forEach(newTryWithResourcesStatement::addResource);
+ TryCatchStatement newTryWithResources = tryCatchS(tryCatchFinally.getTryStatement());
+ tryCatchFinally.getResourceStatements().forEach(newTryWithResources::addResource);
/*
- * try {
- * << the following try-with-resources has been transformed >>
- * try ResourceSpecification
- * Block
- * }
- * Catchesopt
- * Finallyopt
+ * try {
+ * << the following try-with-resources has been transformed >>
+ * try ResourceSpecification
+ * Block
+ * }
+ * Catchesopt
+ * Finallyopt
*/
- TryCatchStatement newTryCatchStatement = tryCatchS(
- astBuilder.createBlockStatement(this.transform(newTryWithResourcesStatement)),
- tryCatchStatement.getFinallyStatement());
- tryCatchStatement.getCatchStatements().forEach(newTryCatchStatement::addCatch);
-
- return newTryCatchStatement;
+ TryCatchStatement newTryCatchFinally = tryCatchS(
+ block(transform(newTryWithResources)),
+ tryCatchFinally.getFinallyStatement()
+ );
+ tryCatchFinally.getCatchStatements().forEach(newTryCatchFinally::addCatch);
+ return newTryCatchFinally;
}
- /*
- * try (VariableModifiersopt R Identifier = Expression ...)
- * Block
- *
- * **The above AST should be transformed to the following AST**
- *
- * {
- * final VariableModifiers_minus_final R Identifier = Expression;
- * Throwable #primaryExc = null;
- *
- * try ResourceSpecification_tail
- * Block
- * catch (Throwable #t) {
- * #primaryExc = #t;
- * throw #t;
- * } finally {
- * if (Identifier != null) {
- * if (#primaryExc != null) {
- * try {
- * Identifier.close();
- * } catch (Throwable #suppressedExc) {
- * #primaryExc.addSuppressed(#suppressedExc);
- * }
- * } else {
- * Identifier.close();
- * }
- * }
- * }
- * }
- *
+ /**
+ * Transforms:
+ * <pre>
+ * try (VariableModifiersopt R Identifier = Expression ...)
+ * Block
+ * </pre>
+ * into:
+ * <pre>
+ * {
+ * final VariableModifiers_minus_final R resourceIdentifier = Expression;
+ * Throwable #primaryException = null;
+ * try ResourceSpecification_tail
+ * Block
+ * catch (Throwable #t) {
+ * #primaryException = #t;
+ * throw #t;
+ * } finally {
+ * if (resourceIdentifier != null) {
+ * if (#primaryException != null) {
+ * try {
+ * resourceIdentifier?.close();
+ * } catch (Throwable #suppressedException) {
+ * #primaryException.addSuppressed(#suppressedException);
+ * }
+ * } else {
+ * resourceIdentifier?.close();
+ * }
+ * }
+ * }
+ * }
+ * </pre>
*/
- private Statement transformBasicTryWithResourcesStatement(TryCatchStatement tryCatchStatement) {
- // { ... }
+ private Statement transformBasicTryWithResourcesStatement(final TryCatchStatement tryWithResources) {
BlockStatement blockStatement = new BlockStatement();
// final VariableModifiers_minus_final R Identifier = Expression;
- ExpressionStatement firstResourceStatement =
- this.makeVariableDeclarationFinal(
- tryCatchStatement.getResourceStatement(0));
- astBuilder.appendStatementsToBlockStatement(blockStatement, firstResourceStatement);
-
- // Throwable #primaryExc = null;
- String primaryExcName = this.genPrimaryExcName();
- VariableExpression primaryExcX = localVarX(primaryExcName, ClassHelper.THROWABLE_TYPE.getPlainNodeReference());
- ExpressionStatement primaryExcDeclarationStatement =
- new ExpressionStatement(
- new DeclarationExpression(
- primaryExcX,
- newSymbol(Types.ASSIGN, -1, -1),
- nullX()
- )
- );
- astBuilder.appendStatementsToBlockStatement(blockStatement, primaryExcDeclarationStatement);
-
- // The generated try-catch-finally statement
- String firstResourceIdentifierName =
- ((DeclarationExpression) tryCatchStatement.getResourceStatement(0).getExpression()).getLeftExpression().getText();
-
- TryCatchStatement newTryCatchStatement = tryCatchS(
- tryCatchStatement.getTryStatement(),
- this.createFinallyBlockForNewTryCatchStatement(primaryExcName, firstResourceIdentifierName));
-
- List<ExpressionStatement> resourceStatements = tryCatchStatement.getResourceStatements();
- // 2nd, 3rd, ..., n'th resources declared in resources
- List<ExpressionStatement> tailResourceStatements = resourceStatements.subList(1, resourceStatements.size());
- tailResourceStatements.stream().forEach(newTryCatchStatement::addResource);
+ ExpressionStatement firstResourceDeclaration = tryWithResources.getResourceStatement(0);
+ blockStatement.addStatement(makeVariableDeclarationFinal(firstResourceDeclaration));
- newTryCatchStatement.addCatch(this.createCatchBlockForOuterNewTryCatchStatement(primaryExcName));
- astBuilder.appendStatementsToBlockStatement(blockStatement, this.transform(newTryCatchStatement));
+ // Throwable #primaryException = null;
+ String primaryExceptionName = nextPrimaryExName();
+ blockStatement.addStatement(declS(
+ localVarX(primaryExceptionName, ClassHelper.THROWABLE_TYPE.getPlainNodeReference()),
+ nullX()
+ ));
- return blockStatement;
- }
+ String firstResourceIdentifier = ((DeclarationExpression) firstResourceDeclaration.getExpression()).getLeftExpression().getText();
- /*
- * catch (Throwable #t) {
- * #primaryExc = #t;
- * throw #t;
- * }
- *
- */
- private CatchStatement createCatchBlockForOuterNewTryCatchStatement(String primaryExcName) {
- // { ... }
- BlockStatement blockStatement = new BlockStatement();
- String tExcName = this.genTExcName();
-
- // #primaryExc = #t;
- ExpressionStatement primaryExcAssignStatement =
- new ExpressionStatement(
- new BinaryExpression(
- new VariableExpression(primaryExcName),
- newSymbol(Types.ASSIGN, -1, -1),
- new VariableExpression(tExcName)));
- astBuilder.appendStatementsToBlockStatement(blockStatement, primaryExcAssignStatement);
-
- // throw #t;
- ThrowStatement throwTExcStatement = new ThrowStatement(new VariableExpression(tExcName));
- astBuilder.appendStatementsToBlockStatement(blockStatement, throwTExcStatement);
+ TryCatchStatement newTryCatchFinally = tryCatchS(
+ tryWithResources.getTryStatement(), // Block
+ createFinallyBlockForNewTryCatchStatement(primaryExceptionName, firstResourceIdentifier) // close resource and propagate throwable(s)
+ );
+ // 2nd, 3rd, ..., n'th resources declared in resources
+ tryWithResources.getResourceStatements().stream().skip(1).forEach(newTryCatchFinally::addResource);
+ newTryCatchFinally.addCatch(createCatchBlockForOuterNewTryCatchStatement(primaryExceptionName));
- // Throwable #t
- Parameter tExcParameter = new Parameter(ClassHelper.THROWABLE_TYPE.getPlainNodeReference(), tExcName);
+ blockStatement.addStatement(transform(newTryCatchFinally)); // transform remaining resources
- return new CatchStatement(tExcParameter, blockStatement);
+ return blockStatement;
}
- private int tExcCnt = 0;
- private String genTExcName() {
- return "__$$t" + tExcCnt++;
+ private CatchStatement createCatchBlockForOuterNewTryCatchStatement(final String primaryExceptionName) {
+ String throwableName = nextThrowableName();
+ Parameter catchParameter = new Parameter(ClassHelper.THROWABLE_TYPE.getPlainNodeReference(), throwableName);
+
+ return catchS(catchParameter, block( // catch (Throwable #t) {
+ assignS(varX(primaryExceptionName), varX(throwableName)), // #primaryException = #t;
+ throwS(varX(throwableName)) // throw #t;
+ )); // }
}
- /*
- * finally {
- * if (Identifier != null) {
- * if (#primaryExc != null) {
- * try {
- * Identifier.close();
- * } catch (Throwable #suppressedExc) {
- * #primaryExc.addSuppressed(#suppressedExc);
- * }
- * } else {
- * Identifier.close();
- * }
- * }
- * }
- *
- * We can simplify the above code to a Groovy version as follows:
- *
- * finally {
- * if (#primaryExc != null)
- * try {
- * Identifier?.close();
- * } catch (Throwable #suppressedExc) {
- * #primaryExc.addSuppressed(#suppressedExc);
+ /**
+ * Transforms:
+ * <pre>
+ * finally {
+ * if (#resourceIdentifier != null) {
+ * if (#primaryException != null) {
+ * try {
+ * #resourceIdentifier?.close();
+ * } catch (Throwable #suppressedException) {
+ * #primaryException.addSuppressed(#suppressedException);
+ * }
+ * } else {
+ * #resourceIdentifier?.close();
* }
- * else
- * Identifier?.close();
- *
- * }
- *
+ * }
+ * }
+ * </pre>
+ * into:
+ * <pre>
+ * finally {
+ * if (#primaryException != null)
+ * try {
+ * #resourceIdentifier?.close();
+ * } catch (Throwable #suppressedException) {
+ * #primaryException.addSuppressed(#suppressedException);
+ * }
+ * else
+ * #resourceIdentifier?.close();
+ * }
+ * </pre>
*/
- private BlockStatement createFinallyBlockForNewTryCatchStatement(String primaryExcName, String firstResourceIdentifierName) {
- BlockStatement finallyBlock = new BlockStatement();
-
- // primaryExc != null
- BooleanExpression conditionExpression =
- new BooleanExpression(
- new BinaryExpression(
- new VariableExpression(primaryExcName),
- newSymbol(Types.COMPARE_NOT_EQUAL, -1, -1),
- new ConstantExpression(null)));
-
- // try-catch statement
- TryCatchStatement newTryCatchStatement = tryCatchS(
- astBuilder.createBlockStatement(this.createCloseResourceStatement(firstResourceIdentifierName)) /* { Identifier?.close(); }*/);
-
- String suppressedExcName = this.genSuppressedExcName();
- newTryCatchStatement.addCatch(
- // catch (Throwable #suppressedExc) { .. }
- new CatchStatement(
- new Parameter(ClassHelper.THROWABLE_TYPE.getPlainNodeReference(), suppressedExcName),
- astBuilder.createBlockStatement(this.createAddSuppressedStatement(primaryExcName, suppressedExcName)) // #primaryExc.addSuppressed(#suppressedExc);
- )
- );
-
- // if (#primaryExc != null) { ... }
- IfStatement ifStatement =
- new IfStatement(
- conditionExpression,
- newTryCatchStatement,
- this.createCloseResourceStatement(firstResourceIdentifierName) // Identifier?.close();
- );
- astBuilder.appendStatementsToBlockStatement(finallyBlock, ifStatement);
-
- return astBuilder.createBlockStatement(finallyBlock);
- }
-
- private int suppressedExcCnt = 0;
- private String genSuppressedExcName() {
- return "__$$suppressedExc" + suppressedExcCnt++;
+ private Statement createFinallyBlockForNewTryCatchStatement(final String primaryExceptionName, final String firstResourceIdentifierName) {
+ String suppressedExceptionName = nextSuppressedExName();
+ TryCatchStatement newTryCatch = tryCatchS(block(createCloseResourceStatement(firstResourceIdentifierName)));
+ newTryCatch.addCatch(catchS(
+ new Parameter(ClassHelper.THROWABLE_TYPE.getPlainNodeReference(), suppressedExceptionName),
+ block(createAddSuppressedStatement(primaryExceptionName, suppressedExceptionName))
+ ));
+
+ return block(ifElseS(notNullX(varX(primaryExceptionName)), // if (#primaryException != null)
+ newTryCatch, // try { #resource?.close() } catch (Throwable #suppressed) { #primary.addSuppressed(#suppressed) }
+ createCloseResourceStatement(firstResourceIdentifierName) // else #resource?.close()
+ ));
}
- /*
- * Identifier?.close();
- */
- private ExpressionStatement createCloseResourceStatement(String firstResourceIdentifierName) {
- MethodCallExpression closeMethodCallExpression =
- new MethodCallExpression(new VariableExpression(firstResourceIdentifierName), "close", new ArgumentListExpression());
-
+ private static Statement createCloseResourceStatement(final String resourceIdentifierName) {
+ MethodCallExpression closeMethodCallExpression = callX(varX(resourceIdentifierName), "close");
closeMethodCallExpression.setImplicitThis(false);
closeMethodCallExpression.setSafe(true);
-
- return new ExpressionStatement(closeMethodCallExpression);
+ return stmt(closeMethodCallExpression);
}
- /*
- * #primaryExc.addSuppressed(#suppressedExc);
- */
- private ExpressionStatement createAddSuppressedStatement(String primaryExcName, String suppressedExcName) {
- MethodCallExpression addSuppressedMethodCallExpression =
- new MethodCallExpression(
- new VariableExpression(primaryExcName),
- "addSuppressed",
- new ArgumentListExpression(Collections.singletonList(new VariableExpression(suppressedExcName))));
+ private static Statement createAddSuppressedStatement(final String primaryException, final String suppressedException) {
+ MethodCallExpression addSuppressedMethodCallExpression = callX(varX(primaryException), "addSuppressed", varX(suppressedException));
addSuppressedMethodCallExpression.setImplicitThis(false);
addSuppressedMethodCallExpression.setSafe(true);
-
- return new ExpressionStatement(addSuppressedMethodCallExpression);
+ return stmt(addSuppressedMethodCallExpression);
}
/**
@@ -372,17 +309,7 @@ public class TryWithResourcesASTTransformation {
* Block
* }
*/
- public BinaryExpression transformResourceAccess(Expression variableAccessExpression) {
- return new BinaryExpression(
- new VariableExpression(genResourceName()),
- newSymbol(Types.ASSIGN, -1, -1),
- variableAccessExpression
- );
- }
-
- private int resourceCnt = 0;
- private String genResourceName() {
- return "__$$resource" + resourceCnt++;
+ public BinaryExpression transformResourceAccess(final Expression variableExpression) {
+ return binX(varX(nextResourceName()), ASSIGN, variableExpression);
}
-
}