use of com.google.errorprone.matchers.Description 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.
*
* <p>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.)
*
* <p>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.
*
* <p>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.
*
* <p>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 = stripNullCheck(rhs, state);
}
ImmutableList<Fix> exploratoryFieldFixes = ImmutableList.of();
if (lhs.getKind() == MEMBER_SELECT) {
// find a method parameter of the same type and similar name and suggest it
// as the rhs
// rhs should be either identifier or field access
Preconditions.checkState(rhs.getKind() == IDENTIFIER || rhs.getKind() == MEMBER_SELECT);
Type rhsType = ASTHelpers.getType(rhs);
exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithMethodParameter(rhs, varDecl -> ASTHelpers.isSameType(rhsType, varDecl.type, state), state);
} else if (rhs.getKind() == IDENTIFIER) {
// find a field of the same type and similar name and suggest it as the lhs
// lhs should be identifier
Preconditions.checkState(lhs.getKind() == IDENTIFIER);
Type lhsType = ASTHelpers.getType(lhs);
exploratoryFieldFixes = ReplacementVariableFinder.fixesByReplacingExpressionWithLocallyDeclaredField(lhs, var -> !Flags.isStatic(var.sym) && (var.sym.flags() & Flags.FINAL) == 0 && ASTHelpers.isSameType(lhsType, var.type, state), state);
}
if (exploratoryFieldFixes.isEmpty()) {
return describeMatch(assignmentTree, fix);
}
return buildDescription(assignmentTree).addAllFixes(exploratoryFieldFixes).build();
}
use of com.google.errorprone.matchers.Description in project error-prone by google.
the class MissingCasesInEnumSwitch method matchSwitch.
@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
Type switchType = ASTHelpers.getType(tree.getExpression());
if (switchType.asElement().getKind() != ElementKind.ENUM) {
return Description.NO_MATCH;
}
// default case is present
if (tree.getCases().stream().anyMatch(c -> c.getExpression() == null)) {
return Description.NO_MATCH;
}
ImmutableSet<String> handled = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(e -> ((IdentifierTree) e).getName().toString()).collect(toImmutableSet());
Set<String> unhandled = Sets.difference(ASTHelpers.enumValues(switchType.asElement()), handled);
if (unhandled.isEmpty()) {
return Description.NO_MATCH;
}
return buildDescription(tree).setMessage(buildMessage(unhandled)).build();
}
use of com.google.errorprone.matchers.Description in project error-prone by google.
the class JavaLangClash method check.
private Description check(Tree tree, Name simpleName, VisitorState state) {
Symtab symtab = state.getSymtab();
PackageSymbol javaLang = symtab.enterPackage(symtab.java_base, Names.instance(state.context).java_lang);
Symbol other = getFirst(javaLang.members().getSymbolsByName(simpleName, s -> s.getModifiers().contains(PUBLIC)), null);
Symbol symbol = ASTHelpers.getSymbol(tree);
if (other == null || other.equals(symbol)) {
return NO_MATCH;
}
return buildDescription(tree).setMessage(String.format("%s clashes with %s\n", symbol, other)).build();
}
use of com.google.errorprone.matchers.Description in project error-prone by google.
the class LambdaFunctionalInterface method matchMethod.
/**
* Identifies methods with parameters that have a generic argument with Int, Long, or Double. If
* pre-conditions are met, it refactors them to the primitive specializations.
*
* <pre>PreConditions:
* (1): The method declaration has to be private (to do a safe refactoring)
* (2): Its parameters have to meet the following conditions:
* 2.1 Contain type java.util.function.Function
* 2.2 At least one argument type of the Function must be subtype of Number
* (3): All its invocations in the top-level enclosing class have to meet the following
* conditions as well:
* 3.1: lambda argument of Kind.LAMBDA_EXPRESSION
* 3.2: same as 2.1
* 3.3: same as 2.2
* </pre>
*
* <pre>
* Refactoring Changes for matched methods:
* (1) Add the imports
* (2) Change the method signature to use utility function instead of Function
* (3) Find and change the 'apply' calls to the corresponding applyAsT
* </pre>
*/
@Override
public Description matchMethod(MethodTree tree, VisitorState state) {
MethodSymbol methodSym = ASTHelpers.getSymbol(tree);
// precondition (1)
if (!methodSym.getModifiers().contains(Modifier.PRIVATE)) {
return Description.NO_MATCH;
}
ImmutableList<Tree> params = tree.getParameters().stream().filter(param -> hasFunctionAsArg(param, state)).filter(param -> isFunctionArgSubtypeOf(param, 0, state.getTypeFromString(JAVA_LANG_NUMBER), state) || isFunctionArgSubtypeOf(param, 1, state.getTypeFromString(JAVA_LANG_NUMBER), state)).collect(toImmutableList());
// preconditions (2) and (3)
if (params.isEmpty() || !methodCallsMeetConditions(methodSym, state)) {
return Description.NO_MATCH;
}
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
for (Tree param : params) {
getMappingForFunctionFromTree(param).ifPresent(mappedFunction -> {
fixBuilder.addImport(getImportName(mappedFunction));
fixBuilder.replace(param, getFunctionName(mappedFunction) + " " + ASTHelpers.getSymbol(param).name);
refactorInternalApplyMethods(tree, fixBuilder, param, mappedFunction);
});
}
return describeMatch(tree, fixBuilder.build());
}
use of com.google.errorprone.matchers.Description in project error-prone by google.
the class BugCheckerRefactoringTestHelper method applyDiff.
private JavaFileObject applyDiff(JavaFileObject sourceFileObject, Context context, JCCompilationUnit tree) throws IOException {
ImportOrganizer importOrganizer = ImportOrderParser.getImportOrganizer(importOrder);
final DescriptionBasedDiff diff = DescriptionBasedDiff.create(tree, importOrganizer);
transformer(refactoringBugChecker).apply(new TreePath(tree), context, new DescriptionListener() {
@Override
public void onDescribed(Description description) {
if (!description.fixes.isEmpty()) {
diff.handleFix(fixChooser.choose(description.fixes));
}
}
});
SourceFile sourceFile = SourceFile.create(sourceFileObject);
diff.applyDifferences(sourceFile);
JavaFileObject transformed = JavaFileObjects.forSourceString(getFullyQualifiedName(tree), sourceFile.getSourceText());
return transformed;
}
Aggregations