use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class AbstractTestExceptionChecker method matchMethod.
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
if (tree.getBody() == null) {
return NO_MATCH;
}
SuggestedFix.Builder baseFixBuilder = SuggestedFix.builder();
JCExpression expectedException = deleteExpectedException(baseFixBuilder, ((JCMethodDecl) tree).getModifiers().getAnnotations(), state);
SuggestedFix baseFix = baseFixBuilder.build();
if (expectedException == null) {
return NO_MATCH;
}
return handleStatements(tree, state, expectedException, baseFix);
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class SelfAssignment method describeForAssignment.
/**
* We expect that the lhs is a field and the rhs is an identifier, specifically
* a parameter to the method. We base our suggested fixes on this expectation.
*
* Case 1: If lhs is a field and rhs is an identifier, find a method parameter
* of the same type and similar name and suggest it as the rhs. (Guess that they
* have misspelled the identifier.)
*
* Case 2: If lhs is a field and rhs is not an identifier, find a method parameter
* of the same type and similar name and suggest it as the rhs.
*
* Case 3: If lhs is not a field and rhs is an identifier, find a class field
* of the same type and similar name and suggest it as the lhs.
*
* Case 4: Otherwise suggest deleting the assignment.
*/
public Description describeForAssignment(AssignmentTree assignmentTree, VisitorState state) {
// the statement that is the parent of the self-assignment expression
Tree parent = state.getPath().getParentPath().getLeaf();
// default fix is to delete assignment
Fix fix = SuggestedFix.delete(parent);
ExpressionTree lhs = assignmentTree.getVariable();
ExpressionTree rhs = assignmentTree.getExpression();
// if this is a method invocation, they must be calling checkNotNull()
if (assignmentTree.getExpression().getKind() == METHOD_INVOCATION) {
// change the default fix to be "checkNotNull(x)" instead of "x = checkNotNull(x)"
fix = SuggestedFix.replace(assignmentTree, rhs.toString());
// new rhs is first argument to checkNotNull()
rhs = stripCheckNotNull(rhs, state);
}
if (lhs.getKind() == MEMBER_SELECT) {
// rhs should be either identifier or field access
assert (rhs.getKind() == IDENTIFIER || rhs.getKind() == MEMBER_SELECT);
// get current name of rhs
String rhsName = null;
if (rhs.getKind() == IDENTIFIER) {
rhsName = ((JCIdent) rhs).name.toString();
} else if (rhs.getKind() == MEMBER_SELECT) {
rhsName = ((JCFieldAccess) rhs).name.toString();
}
// find method parameters of the same type
Type type = ((JCFieldAccess) lhs).type;
TreePath path = state.getPath();
while (path != null && path.getLeaf().getKind() != METHOD) {
path = path.getParentPath();
}
JCMethodDecl method = (JCMethodDecl) path.getLeaf();
int minEditDistance = Integer.MAX_VALUE;
String replacement = null;
for (JCVariableDecl var : method.params) {
if (var.type == type) {
int editDistance = EditDistance.getEditDistance(rhsName, var.name.toString());
if (editDistance < minEditDistance) {
// pick one with minimum edit distance
minEditDistance = editDistance;
replacement = var.name.toString();
}
}
}
if (replacement != null) {
// suggest replacing rhs with the parameter
fix = SuggestedFix.replace(rhs, replacement);
}
} else if (rhs.getKind() == IDENTIFIER) {
// lhs should be identifier
assert (lhs.getKind() == IDENTIFIER);
// get current name of lhs
String lhsName = ((JCIdent) rhs).name.toString();
// find class instance fields of the same type
Type type = ((JCIdent) lhs).type;
TreePath path = state.getPath();
while (path != null && !(path.getLeaf() instanceof JCClassDecl)) {
path = path.getParentPath();
}
if (path == null) {
throw new IllegalStateException("Expected to find an enclosing class declaration");
}
JCClassDecl klass = (JCClassDecl) path.getLeaf();
int minEditDistance = Integer.MAX_VALUE;
String replacement = null;
for (JCTree member : klass.getMembers()) {
if (member.getKind() == VARIABLE) {
JCVariableDecl var = (JCVariableDecl) member;
if (!Flags.isStatic(var.sym) && var.type == type) {
int editDistance = EditDistance.getEditDistance(lhsName, var.name.toString());
if (editDistance < minEditDistance) {
// pick one with minimum edit distance
minEditDistance = editDistance;
replacement = var.name.toString();
}
}
}
}
if (replacement != null) {
// suggest replacing lhs with the field
fix = SuggestedFix.replace(lhs, "this." + replacement);
}
}
return describeMatch(assignmentTree, fix);
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class UseBinds method convertMethodToBinds.
private SuggestedFix.Builder convertMethodToBinds(MethodTree method, VisitorState state) {
SuggestedFix.Builder fix = SuggestedFix.builder();
JCModifiers modifiers = ((JCMethodDecl) method).getModifiers();
ImmutableList.Builder<String> modifierStringsBuilder = new ImmutableList.Builder<String>().add("@Binds");
for (JCAnnotation annotation : modifiers.annotations) {
Name annotationQualifiedName = getSymbol(annotation).getQualifiedName();
if (annotationQualifiedName.contentEquals(PROVIDES_CLASS_NAME) || annotationQualifiedName.contentEquals(PRODUCES_CLASS_NAME)) {
List<JCExpression> arguments = annotation.getArguments();
if (!arguments.isEmpty()) {
JCExpression argument = Iterables.getOnlyElement(arguments);
checkState(argument.getKind().equals(ASSIGNMENT));
JCAssign assignment = (JCAssign) argument;
checkState(getSymbol(assignment.getVariable()).getSimpleName().contentEquals("type"));
String typeName = getSymbol(assignment.getExpression()).getSimpleName().toString();
switch(typeName) {
case "SET":
modifierStringsBuilder.add("@IntoSet");
fix.addImport(INTO_SET_CLASS_NAME);
break;
case "SET_VALUES":
modifierStringsBuilder.add("@ElementsIntoSet");
fix.addImport(ELEMENTS_INTO_SET_CLASS_NAME);
break;
case "MAP":
modifierStringsBuilder.add("@IntoMap");
fix.addImport(INTO_MAP_CLASS_NAME);
break;
default:
throw new AssertionError("Unknown type name: " + typeName);
}
}
} else {
modifierStringsBuilder.add(state.getSourceForNode(annotation));
}
}
EnumSet<Flag> methodFlags = Flags.asFlagSet(modifiers.flags);
methodFlags.remove(Flags.Flag.STATIC);
methodFlags.remove(Flags.Flag.FINAL);
methodFlags.add(Flags.Flag.ABSTRACT);
for (Flag flag : methodFlags) {
modifierStringsBuilder.add(flag.toString());
}
fix.replace(modifiers, Joiner.on(' ').join(modifierStringsBuilder.build()));
fix.replace(method.getBody(), ";");
return fix;
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class ReturnMissingNullable method matchReturn.
@Override
public Description matchReturn(ReturnTree tree, VisitorState state) {
ExpressionTree returnExpression = tree.getExpression();
if (returnExpression == null) {
return Description.NO_MATCH;
}
// TODO(kmb): bail on more non-null expressions, such as "this", arithmethic, logical, and &&/||
if (ASTHelpers.constValue(returnExpression) != null) {
// This should include literals such as "true" or a string
return Description.NO_MATCH;
}
JCMethodDecl method = findSurroundingMethod(state.getPath());
if (method == null || isIgnoredReturnType(method, state)) {
return Description.NO_MATCH;
}
if (TrustingNullnessAnalysis.hasNullableAnnotation(method.sym)) {
return Description.NO_MATCH;
}
// Don't need dataflow to tell us that null is nullable
if (returnExpression.getKind() == ExpressionTree.Kind.NULL_LITERAL) {
return makeFix(method, tree, "Returning null literal");
}
// OK let's see what dataflow says
Nullness nullness = TrustingNullnessAnalysis.instance(state.context).getNullness(new TreePath(state.getPath(), returnExpression), state.context);
switch(nullness) {
case BOTTOM:
case NONNULL:
return Description.NO_MATCH;
case NULL:
return makeFix(method, tree, "Definitely returning null");
case NULLABLE:
return makeFix(method, tree, "May return null");
default:
throw new AssertionError("Impossible: " + nullness);
}
}
use of com.sun.tools.javac.tree.JCTree.JCMethodDecl in project error-prone by google.
the class EmptySetMultibindingContributions method fixByModifyingMethod.
private Description fixByModifyingMethod(VisitorState state, JCClassDecl enclosingClass, MethodTree method) {
JCModifiers methodModifiers = ((JCMethodDecl) method).getModifiers();
String replacementModifiersString = createReplacementMethodModifiers(state, methodModifiers);
JCModifiers enclosingClassModifiers = enclosingClass.getModifiers();
String enclosingClassReplacementModifiersString = createReplacementClassModifiers(state, enclosingClassModifiers);
SuggestedFix.Builder fixBuilder = SuggestedFix.builder().addImport("dagger.multibindings.Multibinds").replace(methodModifiers, replacementModifiersString).replace(method.getBody(), ";");
fixBuilder = (enclosingClassModifiers.pos == -1) ? fixBuilder.prefixWith(enclosingClass, enclosingClassReplacementModifiersString) : fixBuilder.replace(enclosingClassModifiers, enclosingClassReplacementModifiersString);
return describeMatch(method, fixBuilder.build());
}
Aggregations