public UStatement template(StatementTree tree) { return (UStatement) tree.accept(this, null); }
/** * Visits (possibly nested) block statements and returns the first child statement with the given * class. */ private static <T> T getChild(StatementTree tree, final Class<T> clazz) { return tree.accept( new SimpleTreeVisitor<T, Void>() { @Override protected T defaultAction(Tree node, Void p) { if (clazz.isInstance(node)) { return clazz.cast(node); } return null; } @Override public T visitBlock(BlockTree node, Void p) { return visit(node.getStatements()); } private T visit(List<? extends Tree> tx) { for (Tree t : tx) { T r = t.accept(this, null); if (r != null) { return r; } } return null; } }, null); }
@Nullable private static MethodInvocationTree getSingleInvocation(StatementTree statement) { return statement.accept( new SimpleTreeVisitor<MethodInvocationTree, Void>() { @Override public MethodInvocationTree visitReturn(ReturnTree returnTree, Void unused) { return visit(returnTree.getExpression(), null); } @Override public MethodInvocationTree visitExpressionStatement( ExpressionStatementTree expressionStatement, Void unused) { return visit(expressionStatement.getExpression(), null); } @Override public MethodInvocationTree visitMethodInvocation( MethodInvocationTree methodInvocationTree, Void unused) { return methodInvocationTree; } }, null); }
/** * Returns true if the given statement can complete normally, as defined by JLS 14.21. * * <p>An exception is made for {@code System.exit}, which cannot complete normally in practice. */ public static boolean canCompleteNormally(StatementTree statement) { return statement.accept(new CanCompleteNormallyVisitor(), null); }
private Result visitStatements(Iterable<? extends StatementTree> nodes, BreakContext cxt) { Result result = NEVER_EXITS; for (StatementTree node : nodes) { result = result.then(node.accept(this, cxt)); } return result; }
public Result visitStatement(StatementTree node) { return node.accept(this, new BreakContext()); }
@Override public Description visitMethod(MethodTree node, Void aVoid) { BlockTree methodBody = node.getBody(); if (methodBody == null) { return Description.NO_MATCH; } return methodBody.getStatements().stream() .map(tree -> tree.accept(this, null)) .filter(notNull()) .findFirst() .orElse(Description.NO_MATCH); }
@Override public Result visitForLoop(ForLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }
@Override public Result visitEnhancedForLoop(EnhancedForLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }
@Override public Result visitDoWhileLoop(DoWhileLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }
@Override public Result visitWhileLoop(WhileLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }
@Override public Boolean visitBlock(BlockTree node, VisitorState state) { if (inBoxedVoidReturningMethod) { // Must have exactly 2 statements if (node.getStatements().size() != 2) { return false; } // Where the first one is a call to the methodToCall if (!node.getStatements().get(0).accept(this, state)) { return false; } // And the second one is "return null;" if (node.getStatements().get(1) instanceof ReturnTree) { ReturnTree returnTree = (ReturnTree) node.getStatements().get(1); if (returnTree.getExpression() instanceof LiteralTree) { Object returnValue = ((LiteralTree) returnTree.getExpression()).getValue(); return returnValue == null; } } return false; } else { return node.getStatements().size() == 1 && Iterables.getOnlyElement(node.getStatements()).accept(this, state); } }
@Override public Result visitLabeledStatement(LabeledStatementTree node, BreakContext cxt) { cxt.enter(node.getLabel()); try { return node.getStatement().accept(this, cxt); } finally { cxt.exit(node.getLabel()); } }
statements .get(i) .accept( new TreeScanner<Void, Void>() { @Override
@Override public TreeAnalysis visitMethod(MethodTree node, Void p) { // A method is guaranteed to call all of its statements in order // UNLESS one of them has an explicit return statement. TreeAnalysis result = new TreeAnalysis(); for (StatementTree statement : node.getBody().getStatements()) { TreeAnalysis statementAnalysis = statement.accept(this, p); result.names.addAll(statementAnalysis.names); if (statementAnalysis.explicitReturn) { result.explicitReturn = true; return result; } } return result; }
@Override public Description visitMethod(MethodTree node, Void aVoid) { BlockTree methodBody = node.getBody(); if (methodBody == null) { return Description.NO_MATCH; } return methodBody.getStatements().stream() .map(tree -> tree.accept(this, null)) .filter(notNull()) .findFirst() .orElse(Description.NO_MATCH); }
@Override public String visitLabeledStatement(LabeledStatementTree node, Void v) { StringBuilder out = new StringBuilder(); StatementTree stmt = node.getStatement(); String label = node.getLabel().toString() + ":\n"; appendAsInlineComment(out, "FIX ME: labeled statements not allowed in Gosu"); out.append(label); appendIndent(out); out.append(stmt.accept(this, v)); return out.toString(); }
@Override public Result visitWhileLoop(WhileLoopTree node, BreakContext cxt) { cxt.loopDepth++; try { return node.getStatement().accept(this, cxt).or(NEVER_EXITS); } finally { cxt.loopDepth--; } }