use of org.codehaus.groovy.ast.stmt.ReturnStatement 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.ReturnStatement in project groovy by apache.
the class AnnotationVisitor method checkCircularReference.
public void checkCircularReference(ClassNode searchClass, ClassNode attrType, Expression startExp) {
if (!isValidAnnotationClass(attrType))
return;
if (!(startExp instanceof AnnotationConstantExpression)) {
addError("Found '" + startExp.getText() + "' when expecting an Annotation Constant", startExp);
return;
}
AnnotationConstantExpression ace = (AnnotationConstantExpression) startExp;
AnnotationNode annotationNode = (AnnotationNode) ace.getValue();
if (annotationNode.getClassNode().equals(searchClass)) {
addError("Circular reference discovered in " + searchClass.getName(), startExp);
return;
}
ClassNode cn = annotationNode.getClassNode();
for (MethodNode method : cn.getMethods()) {
if (method.getReturnType().equals(searchClass)) {
addError("Circular reference discovered in " + cn.getName(), startExp);
}
ReturnStatement code = (ReturnStatement) method.getCode();
if (code == null)
continue;
checkCircularReference(searchClass, method.getReturnType(), code.getExpression());
}
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class AnnotationConstantsVisitor method visitStatement.
private static void visitStatement(Statement statement, ClassNode returnType) {
if (statement instanceof ReturnStatement) {
// normal path
ReturnStatement rs = (ReturnStatement) statement;
rs.setExpression(transformConstantExpression(rs.getExpression(), returnType));
} else if (statement instanceof ExpressionStatement) {
// path for JavaStubGenerator
ExpressionStatement es = (ExpressionStatement) statement;
es.setExpression(transformConstantExpression(es.getExpression(), returnType));
}
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class FinalVariableAnalyzer method fallsThrough.
/**
* @return true if the block falls through, i.e. no break/return
*/
private boolean fallsThrough(Statement statement) {
if (statement instanceof EmptyStatement) {
return true;
}
if (statement instanceof ReturnStatement) {
// from ReturnAdder
return false;
}
// currently only possibility
BlockStatement block = (BlockStatement) statement;
if (block.getStatements().size() == 0) {
return true;
}
Statement last = DefaultGroovyMethods.last(block.getStatements());
boolean completesAbruptly = last instanceof ReturnStatement || last instanceof BreakStatement || last instanceof ThrowStatement || last instanceof ContinueStatement;
return !completesAbruptly;
}
use of org.codehaus.groovy.ast.stmt.ReturnStatement in project groovy by apache.
the class StaticTypeCheckingSupport method evaluateExpression.
/**
* A helper method that can be used to evaluate expressions as found in annotation
* parameters. For example, it will evaluate a constant, be it referenced directly as
* an integer or as a reference to a field.
* <p>
* If this method throws an exception, then the expression cannot be evaluated on its own.
*
* @param expr the expression to be evaluated
* @param config the compiler configuration
* @return the result of the expression
*/
public static Object evaluateExpression(final Expression expr, final CompilerConfiguration config) {
Expression ce = expr instanceof CastExpression ? ((CastExpression) expr).getExpression() : expr;
if (ce instanceof ConstantExpression) {
if (expr.getType().equals(ce.getType()))
return ((ConstantExpression) ce).getValue();
} else if (ce instanceof ListExpression) {
if (expr.getType().isArray() && expr.getType().getComponentType().equals(STRING_TYPE))
return ((ListExpression) ce).getExpressions().stream().map(e -> evaluateExpression(e, config)).toArray(String[]::new);
}
String className = "Expression$" + UUID.randomUUID().toString().replace('-', '$');
ClassNode simpleClass = new ClassNode(className, Opcodes.ACC_PUBLIC, OBJECT_TYPE);
addGeneratedMethod(simpleClass, "eval", Opcodes.ACC_PUBLIC + Opcodes.ACC_STATIC, OBJECT_TYPE, Parameter.EMPTY_ARRAY, ClassNode.EMPTY_ARRAY, new ReturnStatement(expr));
// adjust configuration so class can be inspected by this JVM
CompilerConfiguration cc = new CompilerConfiguration(config);
// unlikely to be required by expression
cc.setPreviewFeatures(false);
cc.setTargetBytecode(CompilerConfiguration.DEFAULT.getTargetBytecode());
CompilationUnit cu = new CompilationUnit(cc);
try {
cu.addClassNode(simpleClass);
cu.compile(Phases.CLASS_GENERATION);
List<GroovyClass> classes = cu.getClasses();
Class<?> aClass = cu.getClassLoader().defineClass(className, classes.get(0).getBytes());
try {
return aClass.getMethod("eval").invoke(null);
} catch (ReflectiveOperationException e) {
throw new GroovyBugError(e);
}
} finally {
closeQuietly(cu.getClassLoader());
}
}
Aggregations