use of org.codehaus.groovy.ast.stmt.CatchStatement in project grails-core by grails.
the class ControllerActionTransformer method wrapMethodBodyWithExceptionHandling.
/**
* This will wrap the method body in a try catch block which does something
* like this:
* <pre>
* try {
* // original method body here
* } catch (Exception $caughtException) {
* Method $method = getExceptionHandlerMethod($caughtException.getClass())
* if($method) {
* return $method.invoke(this, $caughtException)
* } else {
* throw $caughtException
* }
* }
* </pre>
* @param methodNode the method to add the try catch block to
*/
protected void wrapMethodBodyWithExceptionHandling(final ClassNode controllerClassNode, final MethodNode methodNode) {
final BlockStatement catchBlockCode = new BlockStatement();
final String caughtExceptionArgumentName = "$caughtException";
final Expression caughtExceptionVariableExpression = new VariableExpression(caughtExceptionArgumentName);
final Expression caughtExceptionTypeExpression = new PropertyExpression(caughtExceptionVariableExpression, "class");
final Expression thisExpression = new VariableExpression("this");
final MethodCallExpression getExceptionHandlerMethodCall = new MethodCallExpression(thisExpression, "getExceptionHandlerMethodFor", caughtExceptionTypeExpression);
applyDefaultMethodTarget(getExceptionHandlerMethodCall, controllerClassNode);
final ClassNode reflectMethodClassNode = new ClassNode(Method.class);
final String exceptionHandlerMethodVariableName = "$method";
final Expression exceptionHandlerMethodExpression = new VariableExpression(exceptionHandlerMethodVariableName, new ClassNode(Method.class));
final Expression declareExceptionHandlerMethod = new DeclarationExpression(new VariableExpression(exceptionHandlerMethodVariableName, reflectMethodClassNode), Token.newSymbol(Types.EQUALS, 0, 0), getExceptionHandlerMethodCall);
final ArgumentListExpression invokeArguments = new ArgumentListExpression();
invokeArguments.addExpression(thisExpression);
invokeArguments.addExpression(caughtExceptionVariableExpression);
final MethodCallExpression invokeExceptionHandlerMethodExpression = new MethodCallExpression(new VariableExpression(exceptionHandlerMethodVariableName), "invoke", invokeArguments);
applyDefaultMethodTarget(invokeExceptionHandlerMethodExpression, reflectMethodClassNode);
final Statement returnStatement = new ReturnStatement(invokeExceptionHandlerMethodExpression);
final Statement throwCaughtExceptionStatement = new ThrowStatement(caughtExceptionVariableExpression);
final Statement ifExceptionHandlerMethodExistsStatement = new IfStatement(new BooleanExpression(exceptionHandlerMethodExpression), returnStatement, throwCaughtExceptionStatement);
catchBlockCode.addStatement(new ExpressionStatement(declareExceptionHandlerMethod));
catchBlockCode.addStatement(ifExceptionHandlerMethodExistsStatement);
final CatchStatement catchStatement = new CatchStatement(new Parameter(new ClassNode(Exception.class), caughtExceptionArgumentName), catchBlockCode);
final Statement methodBody = methodNode.getCode();
BlockStatement tryBlock = new BlockStatement();
BlockStatement codeToHandleAllowedMethods = getCodeToHandleAllowedMethods(controllerClassNode, methodNode.getName());
tryBlock.addStatement(codeToHandleAllowedMethods);
tryBlock.addStatement(methodBody);
final TryCatchStatement tryCatchStatement = new TryCatchStatement(tryBlock, new EmptyStatement());
tryCatchStatement.addCatch(catchStatement);
final ArgumentListExpression argumentListExpression = new ArgumentListExpression();
argumentListExpression.addExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME));
final PropertyExpression requestPropertyExpression = new PropertyExpression(new VariableExpression("this"), "request");
final Expression removeAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "removeAttribute", argumentListExpression);
final Expression getAttributeMethodCall = new MethodCallExpression(requestPropertyExpression, "getAttribute", new ArgumentListExpression(new ConstantExpression(ALLOWED_METHODS_HANDLED_ATTRIBUTE_NAME)));
final VariableExpression attributeValueExpression = new VariableExpression("$allowed_methods_attribute_value", ClassHelper.make(Object.class));
final Expression initializeAttributeValue = new DeclarationExpression(attributeValueExpression, Token.newSymbol(Types.EQUALS, 0, 0), getAttributeMethodCall);
final Expression attributeValueMatchesMethodNameExpression = new BinaryExpression(new ConstantExpression(methodNode.getName()), Token.newSymbol(Types.COMPARE_EQUAL, 0, 0), attributeValueExpression);
final Statement ifAttributeValueMatchesMethodName = new IfStatement(new BooleanExpression(attributeValueMatchesMethodNameExpression), new ExpressionStatement(removeAttributeMethodCall), new EmptyStatement());
final BlockStatement blockToRemoveAttribute = new BlockStatement();
blockToRemoveAttribute.addStatement(new ExpressionStatement(initializeAttributeValue));
blockToRemoveAttribute.addStatement(ifAttributeValueMatchesMethodName);
final TryCatchStatement tryCatchToRemoveAttribute = new TryCatchStatement(blockToRemoveAttribute, new EmptyStatement());
tryCatchToRemoveAttribute.addCatch(new CatchStatement(new Parameter(ClassHelper.make(Exception.class), "$exceptionRemovingAttribute"), new EmptyStatement()));
tryCatchStatement.setFinallyStatement(tryCatchToRemoveAttribute);
methodNode.setCode(tryCatchStatement);
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class AntlrParserPlugin method catchStatement.
protected List<CatchStatement> catchStatement(AST catchNode) {
AST node = catchNode.getFirstChild();
List<CatchStatement> catches = new LinkedList<CatchStatement>();
Statement code = statement(node.getNextSibling());
if (MULTICATCH == node.getType()) {
AST variableNode = node.getNextSibling();
final AST multicatches = node.getFirstChild();
if (multicatches.getType() != MULTICATCH_TYPES) {
// catch (e)
// catch (def e)
String variable = identifier(multicatches);
Parameter catchParameter = new Parameter(ClassHelper.DYNAMIC_TYPE, variable);
CatchStatement answer = new CatchStatement(catchParameter, code);
configureAST(answer, catchNode);
catches.add(answer);
} else {
// catch (Exception e)
// catch (Exception1 | Exception2 e)
AST exceptionNodes = multicatches.getFirstChild();
String variable = identifier(multicatches.getNextSibling());
while (exceptionNodes != null) {
ClassNode exceptionType = buildName(exceptionNodes);
Parameter catchParameter = new Parameter(exceptionType, variable);
CatchStatement answer = new CatchStatement(catchParameter, code);
configureAST(answer, catchNode);
catches.add(answer);
exceptionNodes = exceptionNodes.getNextSibling();
}
}
}
return catches;
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class StatementWriter method writeTryCatchFinally.
public void writeTryCatchFinally(final TryCatchStatement statement) {
writeStatementLabel(statement);
MethodVisitor mv = controller.getMethodVisitor();
CompileStack compileStack = controller.getCompileStack();
OperandStack operandStack = controller.getOperandStack();
Statement tryStatement = statement.getTryStatement();
Statement finallyStatement = statement.getFinallyStatement();
BlockRecorder tryBlock = makeBlockRecorder(finallyStatement);
startRange(tryBlock, mv);
tryStatement.visit(controller.getAcg());
// skip past catch block(s)
Label finallyStart = new Label();
boolean fallthroughFinally = false;
if (maybeFallsThrough(tryStatement)) {
mv.visitJumpInsn(GOTO, finallyStart);
fallthroughFinally = true;
}
closeRange(tryBlock, mv);
// pop for BlockRecorder
compileStack.pop();
BlockRecorder catches = makeBlockRecorder(finallyStatement);
for (CatchStatement catchStatement : statement.getCatchStatements()) {
Label catchBlock = startRange(catches, mv);
// create variable for the exception
compileStack.pushState();
// TODO: Is it okay that "catch (e)" makes variable type Object?
compileStack.defineVariable(catchStatement.getVariable(), true);
// handle catch body
catchStatement.visit(controller.getAcg());
// placeholder to avoid problems with empty catch block
mv.visitInsn(NOP);
// pop for the variable
compileStack.pop();
// end of catch
closeRange(catches, mv);
if (maybeFallsThrough(catchStatement.getCode())) {
mv.visitJumpInsn(GOTO, finallyStart);
fallthroughFinally = true;
}
compileStack.writeExceptionTable(tryBlock, catchBlock, BytecodeHelper.getClassInternalName(catchStatement.getExceptionType()));
}
// used to handle exceptions in catches and regularly visited finals
Label catchAll = new Label(), afterCatchAll = new Label();
// add "catch all" block to exception table for try part; we do this
// after the exception blocks so they are not superseded by this one
compileStack.writeExceptionTable(tryBlock, catchAll, null);
// same for the catch parts
compileStack.writeExceptionTable(catches, catchAll, null);
// pop for BlockRecorder
compileStack.pop();
if (fallthroughFinally) {
mv.visitLabel(finallyStart);
finallyStatement.visit(controller.getAcg());
// skip over the catch-finally-rethrow
mv.visitJumpInsn(GOTO, afterCatchAll);
}
mv.visitLabel(catchAll);
operandStack.push(ClassHelper.THROWABLE_TYPE);
int anyThrowable = compileStack.defineTemporaryVariable("throwable", true);
finallyStatement.visit(controller.getAcg());
// load the throwable and rethrow it
mv.visitVarInsn(ALOAD, anyThrowable);
mv.visitInsn(ATHROW);
if (fallthroughFinally)
mv.visitLabel(afterCatchAll);
compileStack.removeVar(anyThrowable);
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class CategoryASTTransformation method transformReferencesToThis.
// --------------------------------------------------------------------------
private void transformReferencesToThis(final ClassNode targetClass, final ClassNode sourceClass, final SourceUnit sourceUnit) {
final Reference<Parameter> selfParameter = new Reference<>();
final LinkedList<Set<String>> varStack = new LinkedList<>();
Set<String> names = new HashSet<>();
for (FieldNode fn : sourceClass.getFields()) names.add(fn.getName());
for (PropertyNode pn : sourceClass.getProperties()) names.add(pn.getName());
varStack.add(names);
ClassCodeExpressionTransformer transformer = new ClassCodeExpressionTransformer() {
// GROOVY-6510: track closure containment
private boolean inClosure;
private void addVariablesToStack(final Parameter[] parameter) {
Set<String> names = new HashSet<>(varStack.getLast());
for (Parameter p : parameter) names.add(p.getName());
varStack.add(names);
}
private Expression createThisExpression() {
VariableExpression ve = new VariableExpression("$this", targetClass);
ve.setClosureSharedVariable(true);
return ve;
}
@Override
protected SourceUnit getSourceUnit() {
return sourceUnit;
}
@Override
public Expression transform(final Expression expression) {
if (expression instanceof VariableExpression) {
VariableExpression ve = (VariableExpression) expression;
if (ve.isThisExpression()) {
Expression thisExpression = createThisExpression();
thisExpression.setSourcePosition(ve);
return thisExpression;
} else if (!inClosure && !ve.isSuperExpression() && !varStack.getLast().contains(ve.getName())) {
PropertyExpression pe = new PropertyExpression(createThisExpression(), ve.getName());
pe.setSourcePosition(ve);
return pe;
}
} else if (expression instanceof MethodCallExpression) {
MethodCallExpression mce = (MethodCallExpression) expression;
if (inClosure && mce.isImplicitThis() && isThisExpression(mce.getObjectExpression())) {
// GROOVY-6510: preserve implicit-this semantics
mce.setArguments(transform(mce.getArguments()));
mce.setMethod(transform(mce.getMethod()));
return mce;
}
} else if (expression instanceof ClosureExpression) {
ClosureExpression ce = (ClosureExpression) expression;
addVariablesToStack(hasImplicitParameter(ce) ? params(param(ClassHelper.OBJECT_TYPE, "it")) : getParametersSafe(ce));
ce.getVariableScope().putReferencedLocalVariable(selfParameter.get());
addAll(varStack.getLast(), "owner", "delegate", "thisObject");
boolean closure = inClosure;
inClosure = true;
ce.getCode().visit(this);
varStack.removeLast();
inClosure = closure;
}
return super.transform(expression);
}
@Override
public void visitBlockStatement(final BlockStatement statement) {
Set<String> names = new HashSet<>(varStack.getLast());
varStack.add(names);
super.visitBlockStatement(statement);
varStack.remove(names);
}
@Override
public void visitCatchStatement(final CatchStatement statement) {
varStack.getLast().add(statement.getVariable().getName());
super.visitCatchStatement(statement);
varStack.getLast().remove(statement.getVariable().getName());
}
@Override
public void visitClosureExpression(final ClosureExpression expression) {
}
@Override
public void visitDeclarationExpression(final DeclarationExpression expression) {
if (expression.isMultipleAssignmentDeclaration()) {
for (Expression e : expression.getTupleExpression().getExpressions()) {
VariableExpression ve = (VariableExpression) e;
varStack.getLast().add(ve.getName());
}
} else {
VariableExpression ve = expression.getVariableExpression();
varStack.getLast().add(ve.getName());
}
super.visitDeclarationExpression(expression);
}
@Override
public void visitExpressionStatement(final ExpressionStatement statement) {
// GROOVY-3543: visit the declaration expressions so that declaration variables get added on the varStack
if (statement.getExpression() instanceof DeclarationExpression) {
statement.getExpression().visit(this);
}
super.visitExpressionStatement(statement);
}
@Override
public void visitForLoop(final ForStatement statement) {
Expression exp = statement.getCollectionExpression();
exp.visit(this);
Parameter loopParam = statement.getVariable();
if (loopParam != null) {
varStack.getLast().add(loopParam.getName());
}
super.visitForLoop(statement);
}
@Override
public void visitMethod(final MethodNode node) {
addVariablesToStack(node.getParameters());
super.visitMethod(node);
varStack.removeLast();
}
};
for (MethodNode method : sourceClass.getMethods()) {
if (!method.isStatic()) {
Parameter p = new Parameter(targetClass, "$this");
p.setClosureSharedVariable(true);
selfParameter.set(p);
Parameter[] oldParams = method.getParameters();
Parameter[] newParams = new Parameter[oldParams.length + 1];
newParams[0] = p;
System.arraycopy(oldParams, 0, newParams, 1, oldParams.length);
method.setModifiers(method.getModifiers() | Opcodes.ACC_STATIC);
method.setParameters(newParams);
transformer.visitMethod(method);
}
}
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class TryWithResourcesASTTransformation method createFinallyBlockForNewTryCatchStatement.
/*
* 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);
* }
* else
* Identifier?.close();
*
* }
*
*/
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)));
String suppressedExcName = this.genSuppressedExcName();
newTryCatchStatement.addCatch(// catch (Throwable #suppressedExc) { .. }
new CatchStatement(new Parameter(ClassHelper.THROWABLE_TYPE.getPlainNodeReference(), suppressedExcName), // #primaryExc.addSuppressed(#suppressedExc);
astBuilder.createBlockStatement(this.createAddSuppressedStatement(primaryExcName, suppressedExcName))));
// if (#primaryExc != null) { ... }
IfStatement ifStatement = new IfStatement(conditionExpression, newTryCatchStatement, // Identifier?.close();
this.createCloseResourceStatement(firstResourceIdentifierName));
astBuilder.appendStatementsToBlockStatement(finallyBlock, ifStatement);
return astBuilder.createBlockStatement(finallyBlock);
}
Aggregations