private boolean hasFinally(TryTree tree) { return tree.getFinallyBlock() != null; }
/** Match a tree in the ancestor chain given the ancestor's immediate descendant. */ protected MatchResult matchAncestor(Tree leaf, Tree prevTree) { if (leaf instanceof TryTree) { TryTree tryTree = (TryTree) leaf; if (tryTree.getFinallyBlock() != null && tryTree.getFinallyBlock().equals(prevTree)) { return MatchResult.FOUND_ERROR; } } return MatchResult.KEEP_LOOKING; } }
private static boolean releases(TryTree tryTree, ExpressionTree lockee, VisitorState state) { if (tryTree.getFinallyBlock() == null) { return false; } // False if a different lock was released, true if 'lockee' was released, null otherwise. Boolean released = new TreeScanner<Boolean, Void>() { @Override public Boolean reduce(Boolean r1, Boolean r2) { return r1 == null ? r2 : (r2 == null ? null : r1 && r2); } @Override public Boolean visitMethodInvocation(MethodInvocationTree node, Void unused) { if (UNLOCK.matches(node, state)) { return releases(node, lockee, state); } return super.visitMethodInvocation(node, null); } }.scan(tryTree.getFinallyBlock(), null); return released == null ? false : released; }
@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 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); }
@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; }
result.addAll(getSafeInitMethods(tryTree.getBlock(), classSymbol, state)); if (tryTree.getFinallyBlock() != null) { result.addAll(getSafeInitMethods(tryTree.getFinallyBlock(), classSymbol, state));
@Override public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) { if (!FENCE_MATCHER.matches(tree, state)) { return NO_MATCH; } Tree previous = null; OUTER: for (Tree enclosing : state.getPath().getParentPath()) { switch (enclosing.getKind()) { case TRY: if (((TryTree) enclosing).getFinallyBlock().equals(previous)) { return NO_MATCH; } break; case CLASS: case METHOD: case LAMBDA_EXPRESSION: break OUTER; default: // fall out } previous = enclosing; } return describeMatch(tree); } }
if (tryTree.getFinallyBlock() == null) { return false; .getFinallyBlock() .accept( new TreeScanner<Void, Void>() {
@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; } }
Optional<Fix> deleteFix(TryTree tree, ImmutableList<CatchTree> catchBlocks, VisitorState state) { SuggestedFix.Builder fix = SuggestedFix.builder(); if (tree.getFinallyBlock() != null || catchBlocks.size() < tree.getCatches().size()) {
@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 @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())); } }
pathToRead, state, new TreePath(enclosingBlockPath, tryTree.getBlock()))); if (tryTree.getFinallyBlock() != null) { result.addAll( safeInitByCalleeBefore( pathToRead, state, new TreePath(enclosingBlockPath, tryTree.getFinallyBlock())));
@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)); }
return Description.NO_MATCH; if (tryTree.getFinallyBlock() != null) { return Description.NO_MATCH;
@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; }
@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; }
@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; }