private boolean hasToleratedException(TryTree tree) { for (CatchTree catchTree : tree.getCatches()) { if (catchTree.getParameter().getName().contentEquals("tolerated")) { return true; } } return false; }
private boolean hasExpectedException(TryTree tree) { for (CatchTree catchTree : tree.getCatches()) { if (catchTree.getParameter().getName().contentEquals("expected")) { return true; } } return false; }
private boolean isInapplicableExceptionType(TryTree tree, VisitorState state) { for (CatchTree catchTree : tree.getCatches()) { if (INAPPLICABLE_EXCEPTION.matches(catchTree.getParameter(), state)) { return true; } } return false; }
private static Fix fixByCatchingException(TryTree tryTree) { VariableTree catchParameter = getOnlyCatch(tryTree).getParameter(); return replace(catchParameter, "Exception " + catchParameter.getName()); }
@Override @Nullable public Choice<Unifier> visitCatch(CatchTree node, @Nullable Unifier unifier) { return getParameter() .unify(node.getParameter(), unifier) .thenChoose(unifications(getBlock(), node.getBlock())); } }
/** * Returns a string describing the exception type caught by the given try tree's catch * statement(s), defaulting to {@code "Exception"} if more than one exception type is caught. */ private static String exceptionToString(TryTree tree, VisitorState state) { if (tree.getCatches().size() != 1) { return "Exception"; } Tree exceptionType = tree.getCatches().iterator().next().getParameter().getType(); Type type = ASTHelpers.getType(exceptionType); if (type != null && type.isUnion()) { return "Exception"; } return state.getSourceForNode(exceptionType); }
private boolean catchVariableIsUsed(CatchTree c) { VarSymbol sym = ASTHelpers.getSymbol(c.getParameter()); boolean[] found = {false}; c.getBlock() .accept( new TreeScanner<Void, Void>() { @Override public Void visitIdentifier(IdentifierTree node, Void aVoid) { if (Objects.equals(sym, ASTHelpers.getSymbol(node))) { found[0] = true; } return super.visitIdentifier(node, aVoid); } }, null); return found[0]; }
@Override public UCatch visitCatch(CatchTree tree, Void v) { return UCatch.create( visitVariable(tree.getParameter(), null), visitBlock(tree.getBlock(), null)); }
@Override public Description matchCatch(CatchTree tree, VisitorState state) { if (isSuppressed(tree.getParameter())) { return Description.NO_MATCH; VarSymbol exceptionSymbol = ASTHelpers.getSymbol(tree.getParameter()); AtomicBoolean symbolUsed = new AtomicBoolean(false); ((JCTree) tree)
@Override public Choice<State<JCCatch>> visitCatch(final CatchTree node, State<?> state) { return chooseSubtrees( state, s -> unifyStatement(node.getBlock(), s), block -> maker().Catch((JCVariableDecl) node.getParameter(), (JCBlock) block)); }
/** Return whether the given try-tree will catch the given exception type. */ private boolean tryCatchesException(TryTree tryTree, Type exceptionToCatch, VisitorState state) { Types types = state.getTypes(); return tryTree.getCatches().stream() .anyMatch( (CatchTree catchClause) -> { Type catchesException = getType(catchClause.getParameter().getType()); // Examine all alternative types of a union type. if (catchesException != null && catchesException.isUnion()) { return Streams.stream(((UnionClassType) catchesException).getAlternativeTypes()) .anyMatch(caught -> types.isSuperType(caught, exceptionToCatch)); } // Simple type, just check superclass. return types.isSuperType(catchesException, exceptionToCatch); }); }
@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; } }
private Optional<Fix> rethrowFix(ImmutableList<CatchTree> catchBlocks, VisitorState state) { SuggestedFix.Builder fix = SuggestedFix.builder(); catchBlocks.forEach( c -> { // e.g. // fail("message") -> throw new AssertionError("message", cause); // assertWithMessage("message format %s", 42) -> // throw new AssertionError(String.format("message format %s", 42), cause); StatementTree statementTree = getOnlyElement(c.getBlock().getStatements()); MethodInvocationTree methodInvocationTree = (MethodInvocationTree) ((ExpressionStatementTree) statementTree).getExpression(); String message = null; if (message == null && !methodInvocationTree.getArguments().isEmpty()) { message = getMessageOrFormat(methodInvocationTree, state); } if (message != null) { // only catch and rethrow to add additional context, not for raw `fail()` calls fix.replace( statementTree, String.format( "throw new AssertionError(%s, %s);", message, c.getParameter().getName())); } }); return fix.isEmpty() ? Optional.empty() : Optional.of(fix.build()); }
if (!catchStatements.isEmpty()) { fixPrefix.append(String.format("%s = ", state.getSourceForNode(catchTree.getParameter()))); state.getSourceForNode(catchTree.getParameter().getType()))); boolean useExpressionLambda = throwingStatements.size() == 1
.map(c -> ASTHelpers.getType(c.getParameter()))
catches.put(ASTHelpers.getType(c.getParameter().getType()), c); Tree lastType = last.getParameter().getType(); if (lastType.getKind() == Tree.Kind.UNION_TYPE) { Type roe = state.getTypeFromString(ReflectiveOperationException.class.getName()); String name = last.getParameter().getName().toString(); fix.postfixWith( last, if (newInstanceInCatch.get()) { fix.replace( Iterables.getLast(result.handles.values()).getParameter().getType(), "ReflectiveOperationException"); return true; for (CatchTree ct : result.handles.values()) { if (first) { fix.replace(ct.getParameter().getType(), "ReflectiveOperationException"); first = false; } else {
@Override public Description matchTry(TryTree tree, VisitorState state) { MatchResult matchResult = tryTreeMatches(tree, state); if (!matchResult.matched()) { return NO_MATCH; } Description.Builder builder = buildDescription(tree.getCatches().get(0).getParameter()); if (matchResult.caughtType == JAVA_LANG_THROWABLE) { builder.addFix(fixByCatchingException(tree)); } if (matchResult.caughtType == SOME_ASSERTION_FAILURE) { builder.addFix(fixByThrowingJavaLangError(matchResult.failStatement, state)); } builder.addFix(fixWithReturnOrBoolean(tree, matchResult.failStatement, state)); return builder.build(); }
VariableTree catchType = catchTree.getParameter(); boolean catchesThrowable = javaLangThrowable.matches(catchType, state); boolean catchesError = javaLangError.matches(catchType, state);
Type typeSym = getType(tree.getParameter().getType()); if (ASTHelpers.isCastable(typeSym, interruptedType, state)) {
String.format("throw new RuntimeException(%s);", enclosingCatch.getParameter().getName()); Fix throwRuntimeExceptionFix = SuggestedFix.replace(returnTree, replacement); return buildDescription(returnTree)