use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class InfiniteRecursion method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (tree.getBody() == null || tree.getBody().getStatements().size() != 1) {
return NO_MATCH;
}
Tree statement = TreeInfo.skipParens((JCTree) Iterables.getOnlyElement(tree.getBody().getStatements()));
ExpressionTree expr = statement.accept(new SimpleTreeVisitor<ExpressionTree, Void>() {
@Override
public ExpressionTree visitExpressionStatement(ExpressionStatementTree tree, Void unused) {
return tree.getExpression();
}
@Override
public ExpressionTree visitReturn(ReturnTree tree, Void unused) {
return tree.getExpression();
}
}, null);
if (!(expr instanceof MethodInvocationTree)) {
return NO_MATCH;
}
ExpressionTree select = ((MethodInvocationTree) expr).getMethodSelect();
switch(select.getKind()) {
case IDENTIFIER:
break;
case MEMBER_SELECT:
ExpressionTree receiver = ((MemberSelectTree) select).getExpression();
if (receiver.getKind() != Kind.IDENTIFIER) {
return NO_MATCH;
}
if (!((IdentifierTree) receiver).getName().contentEquals("this")) {
return NO_MATCH;
}
break;
default:
return NO_MATCH;
}
MethodSymbol sym = ASTHelpers.getSymbol(tree);
if (sym == null || !sym.equals(ASTHelpers.getSymbol(expr))) {
return NO_MATCH;
}
return describeMatch(statement);
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class InvalidPatternSyntax method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState state) {
if (!BAD_REGEX_USAGE.matches(methodInvocationTree, state)) {
return Description.NO_MATCH;
}
// TODO: Suggest fixes for more situations.
Description.Builder descriptionBuilder = buildDescription(methodInvocationTree);
ExpressionTree arg = methodInvocationTree.getArguments().get(0);
String value = (String) ((JCExpression) arg).type.constValue();
String reasonInvalid = "";
if (".".equals(value)) {
descriptionBuilder.addFix(SuggestedFix.replace(arg, "\"\\\\.\""));
reasonInvalid = "\".\" is a valid but useless regex";
} else {
try {
Pattern.compile(value);
} catch (PatternSyntaxException e) {
reasonInvalid = e.getMessage();
}
}
descriptionBuilder.setMessage(MESSAGE_BASE + reasonInvalid);
return descriptionBuilder.build();
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class MockitoUsage method buildFix.
/**
* Create fixes for invalid assertions.
*
* <ul>
* <li>Rewrite `verify(mock.bar())` to `verify(mock).bar()`
* <li>Rewrite `verify(mock.bar(), times(N))` to `verify(mock, times(N)).bar()`
* <li>Rewrite `verify(mock, never())` to `verifyZeroInteractions(mock)`
* <li>Finally, offer to delete the mock statement.
* </ul>
*/
private void buildFix(Description.Builder builder, MethodInvocationTree tree, VisitorState state) {
MethodInvocationTree mockitoCall = tree;
List<? extends ExpressionTree> args = mockitoCall.getArguments();
Tree mock = mockitoCall.getArguments().get(0);
boolean isVerify = ASTHelpers.getSymbol(tree).getSimpleName().contentEquals("verify");
if (isVerify && mock.getKind() == Kind.METHOD_INVOCATION) {
MethodInvocationTree invocation = (MethodInvocationTree) mock;
String verify = state.getSourceForNode(mockitoCall.getMethodSelect());
String receiver = state.getSourceForNode(ASTHelpers.getReceiver(invocation));
String mode = args.size() > 1 ? ", " + state.getSourceForNode(args.get(1)) : "";
String call = state.getSourceForNode(invocation).substring(receiver.length());
builder.addFix(SuggestedFix.replace(tree, String.format("%s(%s%s)%s", verify, receiver, mode, call)));
}
if (isVerify && args.size() > 1 && NEVER_METHOD.matches(args.get(1), state)) {
// TODO(cushon): handle times(0) the same as never()
builder.addFix(SuggestedFix.builder().addStaticImport("org.mockito.Mockito.verifyZeroInteractions").replace(tree, String.format("verifyZeroInteractions(%s)", mock)).build());
}
// Always suggest the naive semantics-preserving option, which is just to
// delete the assertion:
Tree parent = state.getPath().getParentPath().getLeaf();
if (parent.getKind() == Kind.EXPRESSION_STATEMENT) {
// delete entire expression statement
builder.addFix(SuggestedFix.delete(parent));
} else {
builder.addFix(SuggestedFix.delete(tree));
}
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class PreconditionsCheckNotNullPrimitive method describe.
/**
* If the call to Preconditions.checkNotNull is part of an expression (assignment, return, etc.),
* we substitute the argument for the method call. E.g.:
* {@code bar = Preconditions.checkNotNull(foo); ==> bar = foo;}
*
* <p>If the argument to Preconditions.checkNotNull is a comparison using == or != and one of the
* operands is null, we call checkNotNull on the non-null operand. E.g.:
* {@code checkNotNull(a == null); ==> checkNotNull(a);}
*
* <p>If the argument is a method call or binary tree and its return type is boolean, change it to a
* checkArgument/checkState. E.g.:
* {@code Preconditions.checkNotNull(foo.hasFoo()) ==> Preconditions.checkArgument(foo.hasFoo())}
*
* <p>Otherwise, delete the checkNotNull call. E.g.:
* {@code Preconditions.checkNotNull(foo); ==> [delete the line]}
*/
public Description describe(MethodInvocationTree methodInvocationTree, VisitorState state) {
ExpressionTree arg1 = methodInvocationTree.getArguments().get(0);
Tree parent = state.getPath().getParentPath().getLeaf();
// Assignment, return, etc.
if (parent.getKind() != Kind.EXPRESSION_STATEMENT) {
return describeMatch(arg1, SuggestedFix.replace(methodInvocationTree, arg1.toString()));
}
// Comparison to null
if (arg1.getKind() == Kind.EQUAL_TO || arg1.getKind() == Kind.NOT_EQUAL_TO) {
BinaryTree binaryExpr = (BinaryTree) arg1;
if (binaryExpr.getLeftOperand().getKind() == Kind.NULL_LITERAL) {
return describeMatch(arg1, SuggestedFix.replace(arg1, binaryExpr.getRightOperand().toString()));
}
if (binaryExpr.getRightOperand().getKind() == Kind.NULL_LITERAL) {
return describeMatch(arg1, SuggestedFix.replace(arg1, binaryExpr.getLeftOperand().toString()));
}
}
if ((arg1 instanceof BinaryTree || arg1.getKind() == Kind.METHOD_INVOCATION || arg1.getKind() == Kind.LOGICAL_COMPLEMENT) && ((JCExpression) arg1).type == state.getSymtab().booleanType) {
return describeMatch(arg1, createCheckArgumentOrStateCall(methodInvocationTree, state, arg1));
}
return describeMatch(arg1, SuggestedFix.delete(parent));
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractToString method checkToString.
/**
* Tests if the given expression is converted to a String by its parent (i.e. its parent
* is a string concat expression, {@code String.format}, or {@code println(Object)}).
*/
private Description checkToString(ExpressionTree tree, VisitorState state) {
Symbol sym = ASTHelpers.getSymbol(tree);
if (!(sym instanceof VarSymbol || sym instanceof MethodSymbol)) {
return NO_MATCH;
}
Type type = ASTHelpers.getType(tree);
if (type instanceof MethodType) {
type = type.getReturnType();
}
Tree parent = state.getPath().getParentPath().getLeaf();
ToStringKind toStringKind = isToString(parent, tree, state);
if (toStringKind == ToStringKind.NONE) {
return NO_MATCH;
}
Optional<Fix> fix;
switch(toStringKind) {
case IMPLICIT:
fix = implicitToStringFix(tree, state);
break;
case EXPLICIT:
fix = toStringFix(parent, tree, state);
break;
default:
throw new AssertionError(toStringKind);
}
if (!typePredicate().apply(type, state)) {
return NO_MATCH;
}
return maybeFix(tree, fix);
}
Aggregations