@Override protected Iterable<? extends StatementTree> getChildNodes(TryTree tree, VisitorState state) { return tree.getBlock().getStatements(); } }
@Override protected MatchResult matchAncestor(Tree tree, Tree prevTree) { if (tree instanceof TryTree) { TryTree tryTree = (TryTree) tree; if (tryTree.getBlock().equals(prevTree) && !tryTree.getCatches().isEmpty()) { // The current ancestor is a try block with associated catch blocks. return MatchResult.NO_MATCH; } } return super.matchAncestor(tree, prevTree); } }
private static boolean hasOtherInvocationsOrAssignments( MethodInvocationTree methodInvocationTree, TryTree tryTree, VisitorState state) { AtomicInteger count = new AtomicInteger(0); Type threadType = state.getTypeFromString("java.lang.Thread"); new TreeScanner<Void, Void>() { @Override public Void visitMethodInvocation(MethodInvocationTree tree, Void unused) { if (!tree.equals(methodInvocationTree)) { count.incrementAndGet(); } return super.visitMethodInvocation(tree, null); } @Override public Void visitAssignment(AssignmentTree tree, Void unused) { if (isSubtype(getType(tree.getVariable()), threadType, state)) { count.incrementAndGet(); } return super.visitAssignment(tree, null); } }.scan(tryTree.getBlock(), null); return count.get() > 0; } }
@Override public Description matchTry(TryTree tree, VisitorState state) { List<? extends StatementTree> body = tree.getBlock().getStatements(); if (body.isEmpty() || tree.getFinallyBlock() != null || tree.getCatches().size() != 1) { // TODO(cushon): support finally // TODO(cushon): support multiple catch blocks return NO_MATCH; } CatchTree catchTree = getOnlyElement(tree.getCatches()); if (catchTree.getParameter().getType().getKind() == UNION_TYPE) { // TODO(cushon): handle multi-catch return NO_MATCH; } if (!FAIL_METHOD.matches(getLast(body), state)) { return NO_MATCH; } // try body statements, excluding the trailing `fail()` List<? extends StatementTree> throwingStatements = tree.getBlock().getStatements().subList(0, tree.getBlock().getStatements().size() - 1); Optional<Fix> fix = AssertThrowsUtils.tryFailToAssertThrows(tree, throwingStatements, state); return fix.isPresent() ? describeMatch(tree, fix) : NO_MATCH; } }
@Override public Description matchTry(TryTree tree, VisitorState state) { if (tryTreeMatches(tree, state)) { List<? extends StatementTree> tryStatements = tree.getBlock().getStatements(); StatementTree lastTryStatement = tryStatements.get(tryStatements.size() - 1); Optional<Fix> assertThrowsFix = AssertThrowsUtils.tryFailToAssertThrows(tree, tryStatements, state); Fix failFix = addFailCall(tree, lastTryStatement, state); return buildDescription(lastTryStatement).addFix(assertThrowsFix).addFix(failFix).build(); } else { return Description.NO_MATCH; } }
@Override public UTry visitTry(TryTree tree, Void v) { @SuppressWarnings({"unchecked", "rawtypes"}) List<UTree<?>> resources = cast(templateTrees(tree.getResources()), (Class<UTree<?>>) (Class) UTree.class); UBlock block = visitBlock(tree.getBlock(), null); ImmutableList.Builder<UCatch> catchesBuilder = ImmutableList.builder(); for (CatchTree catchTree : tree.getCatches()) { catchesBuilder.add(visitCatch(catchTree, null)); } UBlock finallyBlock = (tree.getFinallyBlock() == null) ? null : visitBlock(tree.getFinallyBlock(), null); return UTry.create(resources, block, catchesBuilder.build(), finallyBlock); }
List<? extends StatementTree> tryStatements = tree.getBlock().getStatements();
@Override @Nullable public Choice<Unifier> visitTry(TryTree node, @Nullable Unifier unifier) { return unifyList(unifier, getResources(), node.getResources()) .thenChoose(unifications(getBlock(), node.getBlock())) .thenChoose(unifications(getCatches(), node.getCatches())) .thenChoose(unifications(getFinallyBlock(), node.getFinallyBlock())); } }
@Override public Boolean visitTry(TryTree that, Void unused) { boolean completes = scan(that.getBlock()); // assume all catch blocks are reachable; javac has already rejected unreachable // checked exception handlers for (CatchTree catchTree : that.getCatches()) { completes |= scan(catchTree.getBlock()); } if (that.getFinallyBlock() != null && !scan(that.getFinallyBlock())) { completes = false; } return completes; } }
@Override public Result visitTry(TryTree node, BreakContext cxt) { Result result = node.getBlock().accept(this, cxt); for (CatchTree catchTree : node.getCatches()) { result = result.or(catchTree.accept(this, cxt)); } if (node.getFinallyBlock() != null) { result = result.then(node.getFinallyBlock().accept(this, cxt)); } return result; }
} else if (tryTree.getBlock().equals(prev)) {
@Override public Void visitTry(TryTree tree, HeldLockSet locks) { scan(tree.getResources(), locks); List<? extends Tree> resources = tree.getResources(); scan(resources, locks); // Cheesy try/finally heuristic: assume that all locks released in the finally // are held for the entirety of the try and catch statements. Collection<GuardedByExpression> releasedLocks = ReleasedLockFinder.find(tree.getFinallyBlock(), visitorState); if (resources.isEmpty()) { scan(tree.getBlock(), locks.plusAll(releasedLocks)); } else { // We don't know what to do with the try-with-resources block. // TODO(cushon) - recognize common try-with-resources patterns. Currently there is no // standard implementation of an AutoCloseable lock resource to detect. } scan(tree.getCatches(), locks.plusAll(releasedLocks)); scan(tree.getFinallyBlock(), locks); return null; }
@Override public Choice<State<JCTry>> visitTry(final TryTree node, State<?> state) { return chooseSubtrees( state, s -> unify(node.getResources(), s), s -> unifyStatement(node.getBlock(), s), s -> unify(node.getCatches(), s), s -> unifyStatement(node.getFinallyBlock(), s), (resources, block, catches, finallyBlock) -> maker() .Try( resources, (JCBlock) block, List.convert(JCCatch.class, catches), (JCBlock) finallyBlock)); }
private static MatchResult tryTreeMatches(TryTree tryTree, VisitorState state) { BlockTree tryBlock = tryTree.getBlock(); List<? extends StatementTree> statements = tryBlock.getStatements(); if (statements.isEmpty()) {
if (tree.getBlock().getStatements().isEmpty()) { return false;
@Override public Void visitTry(TryTree expected, Tree actual) { Optional<TryTree> other = checkTypeAndCast(expected, actual); if (!other.isPresent()) { addTypeMismatch(expected, actual); return null; } scan(expected.getBlock(), other.get().getBlock()); parallelScan(expected.getCatches(), other.get().getCatches()); scan(expected.getFinallyBlock(), other.get().getFinallyBlock()); return null; }
private TryTree modifyTryCatch(TryTree traj, int index, CatchTree kec, Operation op) { TryTree copy = Try( traj.getResources(), traj.getBlock(), c(traj.getCatches(), index, kec, op), traj.getFinallyBlock() ); return copy; }
@Override @Nullable public Choice<Unifier> visitTry(TryTree node, @Nullable Unifier unifier) { return unifyList(unifier, getResources(), node.getResources()) .thenChoose(unifications(getBlock(), node.getBlock())) .thenChoose(unifications(getCatches(), node.getCatches())) .thenChoose(unifications(getFinallyBlock(), node.getFinallyBlock())); } }