use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractExpectedExceptionChecker method buildBaseFix.
protected BaseFix buildBaseFix(VisitorState state, List<Tree> expectations) {
String exceptionClass = "Throwable";
// additional assertions to perform on the captured exception (if any)
List<String> newAsserts = new ArrayList<>();
Builder fix = SuggestedFix.builder();
for (Tree expectation : expectations) {
MethodInvocationTree invocation = (MethodInvocationTree) ((ExpressionStatementTree) expectation).getExpression();
MethodSymbol symbol = ASTHelpers.getSymbol(invocation);
Symtab symtab = state.getSymtab();
List<? extends ExpressionTree> args = invocation.getArguments();
switch(symbol.getSimpleName().toString()) {
case "expect":
if (isSubtype(getOnlyElement(symbol.getParameters()).asType(), symtab.classType, state)) {
// expect(Class<?>)
exceptionClass = state.getSourceForNode(getReceiver(getOnlyElement(args)));
} else {
// expect(Matcher)
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown, %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
case "expectCause":
ExpressionTree matcher = getOnlyElement(invocation.getArguments());
if (IS_A.matches(matcher, state)) {
fix.addStaticImport("com.google.common.truth.Truth.assertThat");
newAsserts.add(String.format("assertThat(thrown).hasCauseThat().isInstanceOf(%s);", state.getSourceForNode(getOnlyElement(((MethodInvocationTree) matcher).getArguments()))));
} else {
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown.getCause(), %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
case "expectMessage":
if (isSubtype(getOnlyElement(symbol.getParameters()).asType(), symtab.stringType, state)) {
// expectedMessage(String)
fix.addStaticImport("com.google.common.truth.Truth.assertThat");
newAsserts.add(String.format("assertThat(thrown).hasMessageThat().contains(%s);", state.getSourceForNode(getOnlyElement(args))));
} else {
// expectedMessage(Matcher)
fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
newAsserts.add(String.format("assertThat(thrown.getMessage(), %s);", state.getSourceForNode(getOnlyElement(args))));
}
break;
default:
throw new AssertionError("unknown expect method: " + symbol.getSimpleName());
}
}
// remove all interactions with the ExpectedException rule
fix.replace(((JCTree) expectations.get(0)).getStartPosition(), state.getEndPosition(getLast(expectations)), "");
return new BaseFix(fix.build(), exceptionClass, newAsserts);
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractReferenceEquality method addFixes.
protected void addFixes(Description.Builder builder, BinaryTree tree, VisitorState state) {
ExpressionTree lhs = tree.getLeftOperand();
ExpressionTree rhs = tree.getRightOperand();
Optional<Fix> fixToReplaceOrStatement = inOrStatementWithEqualsCheck(state, tree);
if (fixToReplaceOrStatement.isPresent()) {
builder.addFix(fixToReplaceOrStatement.get());
return;
}
// Swap the order (e.g. rhs.equals(lhs) if the rhs is a non-null constant, and the lhs is not
if (ASTHelpers.constValue(lhs) == null && ASTHelpers.constValue(rhs) != null) {
ExpressionTree tmp = lhs;
lhs = rhs;
rhs = tmp;
}
String prefix = tree.getKind() == Kind.NOT_EQUAL_TO ? "!" : "";
String lhsSource = state.getSourceForNode(lhs);
String rhsSource = state.getSourceForNode(rhs);
Nullness nullness = getNullness(lhs, state);
// If the lhs is possibly-null, provide both options.
if (nullness != NONNULL) {
builder.addFix(SuggestedFix.builder().replace(tree, String.format("%sObjects.equals(%s, %s)", prefix, lhsSource, rhsSource)).addImport("java.util.Objects").build());
}
if (nullness != NULL) {
builder.addFix(SuggestedFix.replace(tree, String.format("%s%s.equals(%s)", prefix, lhs instanceof BinaryTree ? String.format("(%s)", lhsSource) : lhsSource, rhsSource)));
}
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractReferenceEquality method inOrStatementWithEqualsCheck.
private static Optional<Fix> inOrStatementWithEqualsCheck(VisitorState state, BinaryTree tree) {
// Only attempt to handle a == b || a.equals(b);
if (tree.getKind() == Kind.NOT_EQUAL_TO) {
return Optional.empty();
}
ExpressionTree lhs = tree.getLeftOperand();
ExpressionTree rhs = tree.getRightOperand();
Tree parent = state.getPath().getParentPath().getLeaf();
if (parent.getKind() != Kind.CONDITIONAL_OR) {
return Optional.empty();
}
BinaryTree p = (BinaryTree) parent;
if (p.getLeftOperand() != tree) {
// a == b is on the RHS, ignore this construction
return Optional.empty();
}
// If the other half of this or statement is foo.equals(bar) or Objects.equals(foo, bar)
// replace the or statement with the other half as already written.
ExpressionTree otherExpression = skipParens(p.getRightOperand());
if (!(otherExpression instanceof MethodInvocationTree)) {
return Optional.empty();
}
MethodInvocationTree other = (MethodInvocationTree) otherExpression;
// a == b || Objects.equals(a, b) => Objects.equals(a, b)
if (EQUALS_STATIC_METHODS.matches(otherExpression, state)) {
List<? extends ExpressionTree> arguments = other.getArguments();
if (treesMatch(arguments.get(0), arguments.get(1), lhs, rhs)) {
return Optional.of(SuggestedFix.replace(parent, state.getSourceForNode(otherExpression)));
}
}
// a == b || a.equals(b) => a.equals(b)
if (OBJECT_INSTANCE_EQUALS.matches(otherExpression, state)) {
if (treesMatch(ASTHelpers.getReceiver(other), other.getArguments().get(0), lhs, rhs)) {
return Optional.of(SuggestedFix.replace(parent, state.getSourceForNode(otherExpression)));
}
}
return Optional.empty();
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractReturnValueIgnored method describe.
/**
* Fixes the error by assigning the result of the call to the receiver reference, or deleting the
* method call.
*/
public Description describe(MethodInvocationTree methodInvocationTree, VisitorState state) {
// Find the root of the field access chain, i.e. a.intern().trim() ==> a.
ExpressionTree identifierExpr = ASTHelpers.getRootAssignable(methodInvocationTree);
String identifierStr = null;
Type identifierType = null;
if (identifierExpr != null) {
identifierStr = identifierExpr.toString();
if (identifierExpr instanceof JCIdent) {
identifierType = ((JCIdent) identifierExpr).sym.type;
} else if (identifierExpr instanceof JCFieldAccess) {
identifierType = ((JCFieldAccess) identifierExpr).sym.type;
} else {
throw new IllegalStateException("Expected a JCIdent or a JCFieldAccess");
}
}
Type returnType = ASTHelpers.getReturnType(((JCMethodInvocation) methodInvocationTree).getMethodSelect());
Fix fix;
if (identifierStr != null && !"this".equals(identifierStr) && returnType != null && state.getTypes().isAssignable(returnType, identifierType)) {
// Fix by assigning the assigning the result of the call to the root receiver reference.
fix = SuggestedFix.prefixWith(methodInvocationTree, identifierStr + " = ");
} else {
// Unclear what the programmer intended. Delete since we don't know what else to do.
Tree parent = state.getPath().getParentPath().getLeaf();
fix = SuggestedFix.delete(parent);
}
return describeMatch(methodInvocationTree, fix);
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractTestExceptionChecker method buildFix.
// TODO(cushon): extracting one statement into a lambda may not compile if the statement has
// side effects (e.g. it references a variable in the method that isn't effectively final).
// If this is a problem, consider trying to detect and avoid that case.
protected static SuggestedFix buildFix(VisitorState state, SuggestedFix.Builder fix, JCExpression expectedException, List<? extends StatementTree> statements) {
fix.addStaticImport("org.junit.Assert.assertThrows");
StringBuilder prefix = new StringBuilder();
prefix.append(String.format("assertThrows(%s, () -> ", state.getSourceForNode(expectedException)));
if (statements.size() == 1 && getOnlyElement(statements) instanceof ExpressionStatementTree) {
ExpressionTree expression = ((ExpressionStatementTree) getOnlyElement(statements)).getExpression();
fix.prefixWith(expression, prefix.toString());
fix.postfixWith(expression, ")");
} else {
prefix.append(" {");
fix.prefixWith(statements.iterator().next(), prefix.toString());
fix.postfixWith(getLast(statements), "});");
}
return fix.build();
}
Aggregations