use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class ReturnAdder method addReturnsIfNeeded.
private Statement addReturnsIfNeeded(final Statement statement, final VariableScope scope) {
if (statement instanceof ReturnStatement || statement instanceof ThrowStatement || statement instanceof EmptyStatement || statement instanceof BytecodeSequence) {
return statement;
}
if (statement == null) {
ReturnStatement returnStatement = new ReturnStatement(nullX());
listener.returnStatementAdded(returnStatement);
return returnStatement;
}
if (statement instanceof ExpressionStatement) {
Expression expression = ((ExpressionStatement) statement).getExpression();
ReturnStatement returnStatement = new ReturnStatement(expression);
returnStatement.copyStatementLabels(statement);
returnStatement.setSourcePosition(statement.getLineNumber() < 0 ? expression : statement);
listener.returnStatementAdded(returnStatement);
return returnStatement;
}
if (statement instanceof SynchronizedStatement) {
SynchronizedStatement syncStatement = (SynchronizedStatement) statement;
Statement code = addReturnsIfNeeded(syncStatement.getCode(), scope);
if (doAdd)
syncStatement.setCode(code);
return syncStatement;
}
if (statement instanceof IfStatement) {
IfStatement ifElseStatement = (IfStatement) statement;
Statement ifBlock = addReturnsIfNeeded(ifElseStatement.getIfBlock(), scope);
Statement elseBlock = addReturnsIfNeeded(ifElseStatement.getElseBlock(), scope);
if (doAdd) {
ifElseStatement.setIfBlock(ifBlock);
ifElseStatement.setElseBlock(elseBlock);
}
return ifElseStatement;
}
if (statement instanceof SwitchStatement) {
SwitchStatement switchStatement = (SwitchStatement) statement;
Statement defaultStatement = switchStatement.getDefaultStatement();
List<CaseStatement> caseStatements = switchStatement.getCaseStatements();
for (Iterator<CaseStatement> it = caseStatements.iterator(); it.hasNext(); ) {
CaseStatement caseStatement = it.next();
Statement code = adjustSwitchCaseCode(caseStatement.getCode(), scope, // GROOVY-9896: return if no default and last case lacks break
defaultStatement == EmptyStatement.INSTANCE && !it.hasNext());
if (doAdd)
caseStatement.setCode(code);
}
defaultStatement = adjustSwitchCaseCode(defaultStatement, scope, true);
if (doAdd)
switchStatement.setDefaultStatement(defaultStatement);
return switchStatement;
}
if (statement instanceof TryCatchStatement) {
TryCatchStatement tryCatchFinally = (TryCatchStatement) statement;
boolean[] missesReturn = new boolean[1];
new ReturnAdder(returnStatement -> missesReturn[0] = true).addReturnsIfNeeded(tryCatchFinally.getFinallyStatement(), scope);
boolean hasFinally = !(tryCatchFinally.getFinallyStatement() instanceof EmptyStatement);
// there is nothing to do
if (hasFinally && !missesReturn[0])
return tryCatchFinally;
// add returns to try and catch blocks
Statement tryStatement = addReturnsIfNeeded(tryCatchFinally.getTryStatement(), scope);
if (doAdd)
tryCatchFinally.setTryStatement(tryStatement);
for (CatchStatement catchStatement : tryCatchFinally.getCatchStatements()) {
Statement code = addReturnsIfNeeded(catchStatement.getCode(), scope);
if (doAdd)
catchStatement.setCode(code);
}
return tryCatchFinally;
}
if (statement instanceof BlockStatement) {
BlockStatement blockStatement = (BlockStatement) statement;
if (blockStatement.isEmpty()) {
ReturnStatement returnStatement = new ReturnStatement(nullX());
returnStatement.copyStatementLabels(blockStatement);
returnStatement.setSourcePosition(blockStatement);
listener.returnStatementAdded(returnStatement);
return returnStatement;
} else {
List<Statement> statements = blockStatement.getStatements();
int lastIndex = statements.size() - 1;
Statement last = addReturnsIfNeeded(statements.get(lastIndex), blockStatement.getVariableScope());
if (doAdd)
statements.set(lastIndex, last);
return blockStatement;
}
}
List<Statement> statements = new ArrayList<>(2);
statements.add(statement);
ReturnStatement returnStatement = new ReturnStatement(nullX());
listener.returnStatementAdded(returnStatement);
statements.add(returnStatement);
BlockStatement blockStatement = new BlockStatement(statements, new VariableScope(scope));
blockStatement.setSourcePosition(statement);
return blockStatement;
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class FinalVariableAnalyzer method visitTryCatchFinally.
@Override
public void visitTryCatchFinally(final TryCatchStatement statement) {
visitStatement(statement);
Map<Variable, VariableState> beforeTryState = new HashMap<>(getState());
pushState();
Statement tryStatement = statement.getTryStatement();
tryStatement.visit(this);
Map<Variable, VariableState> afterTryState = new HashMap<>(getState());
Statement finallyStatement = statement.getFinallyStatement();
List<Map<Variable, VariableState>> afterStates = new ArrayList<>();
// the try finally case
finallyStatement.visit(this);
if (!returningBlock(tryStatement)) {
afterStates.add(new HashMap<>(getState()));
}
popState();
// now the finally only case but only if no catches
if (statement.getCatchStatements().isEmpty()) {
finallyStatement.visit(this);
if (!returningBlock(tryStatement)) {
afterStates.add(new HashMap<>(getState()));
}
}
for (CatchStatement catchStatement : statement.getCatchStatements()) {
// We don't try to analyse which statement within the try block might have thrown an exception.
// We make a crude assumption that anywhere from none to all of the statements might have been executed.
// Run visitor for both scenarios so the eager checks will be performed for either of these cases.
visitCatchFinally(beforeTryState, afterStates, catchStatement, finallyStatement);
visitCatchFinally(afterTryState, afterStates, catchStatement, finallyStatement);
}
// after states can only be empty if try and catch statements all return in which case nothing to do
if (afterStates.isEmpty())
return;
// now adjust the state variables - any early returns won't have gotten here
// but we need to check that the same status was observed by all paths
// and mark as ambiguous if needed
Map<Variable, VariableState> corrected = afterStates.remove(0);
for (Map<Variable, VariableState> nextState : afterStates) {
for (Map.Entry<Variable, VariableState> entry : corrected.entrySet()) {
Variable var = entry.getKey();
VariableState currentCorrectedState = entry.getValue();
VariableState candidateCorrectedState = nextState.get(var);
if (currentCorrectedState == VariableState.is_ambiguous)
continue;
if (currentCorrectedState != candidateCorrectedState) {
if (currentCorrectedState == VariableState.is_uninitialized || candidateCorrectedState == VariableState.is_uninitialized) {
corrected.put(var, VariableState.is_ambiguous);
} else {
corrected.put(var, VariableState.is_var);
}
}
}
}
getState().putAll(corrected);
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class CodeVisitorSupport method visitTryCatchFinally.
@Override
public void visitTryCatchFinally(TryCatchStatement statement) {
statement.getTryStatement().visit(this);
for (CatchStatement catchStatement : statement.getCatchStatements()) {
catchStatement.visit(this);
}
statement.getFinallyStatement().visit(this);
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class StaticTypeCheckingVisitor method visitTryCatchFinally.
@Override
public void visitTryCatchFinally(final TryCatchStatement statement) {
List<CatchStatement> catchStatements = statement.getCatchStatements();
for (CatchStatement catchStatement : catchStatements) {
ClassNode exceptionType = catchStatement.getExceptionType();
typeCheckingContext.controlStructureVariables.put(catchStatement.getVariable(), exceptionType);
}
try {
super.visitTryCatchFinally(statement);
} finally {
for (CatchStatement catchStatement : catchStatements) {
typeCheckingContext.controlStructureVariables.remove(catchStatement.getVariable());
}
}
}
use of org.codehaus.groovy.ast.stmt.CatchStatement in project groovy by apache.
the class TryCatchBlockGenerator method generateTryCatchBlockForInlineMode.
public static BlockStatement generateTryCatchBlockForInlineMode(final ClassNode assertionErrorClass, final String message, final Statement assertStatement) {
final Class powerAssertionErrorClass = loadPowerAssertionErrorClass();
if (powerAssertionErrorClass == null)
throw new GroovyBugError("groovy-contracts needs Groovy 1.7 or above!");
VariableExpression newError = localVarX("newError", assertionErrorClass);
Statement block = block(// newError = message + error.message
declS(newError, ctorX(assertionErrorClass, args(binX(constX(message), PLUS, callX(varX(param(ClassHelper.makeWithoutCaching(powerAssertionErrorClass), "error")), "getMessage"))))), // newError.stackTrace = error.stackTrace
stmt(callX(newError, "setStackTrace", args(callX(varX(param(ClassHelper.makeWithoutCaching(powerAssertionErrorClass), "error")), "getStackTrace")))), throwS(newError));
CatchStatement catchStatement = catchS(param(ClassHelper.makeWithoutCaching(powerAssertionErrorClass), "error"), block);
return block(tryCatchS(assertStatement, EmptyStatement.INSTANCE, catchStatement));
}
Aggregations