Search in sources :

Example 31 with Description

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();
}
Also used : Matchers.anyOf(com.google.errorprone.matchers.Matchers.anyOf) VariableTree(com.sun.source.tree.VariableTree) IDENTIFIER(com.sun.source.tree.Tree.Kind.IDENTIFIER) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) ImmutableList(com.google.common.collect.ImmutableList) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Matcher(com.google.errorprone.matchers.Matcher) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) Matchers.staticMethod(com.google.errorprone.matchers.Matchers.staticMethod) AssignmentTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.AssignmentTreeMatcher) ERROR(com.google.errorprone.BugPattern.SeverityLevel.ERROR) MEMBER_SELECT(com.sun.source.tree.Tree.Kind.MEMBER_SELECT) ExpressionTree(com.sun.source.tree.ExpressionTree) METHOD_INVOCATION(com.sun.source.tree.Tree.Kind.METHOD_INVOCATION) Symbol(com.sun.tools.javac.code.Symbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CLASS(com.sun.source.tree.Tree.Kind.CLASS) VariableTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.VariableTreeMatcher) STATIC(javax.lang.model.element.Modifier.STATIC) Description(com.google.errorprone.matchers.Description) Preconditions(com.google.common.base.Preconditions) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Flags(com.sun.tools.javac.code.Flags) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Type(com.sun.tools.javac.code.Type) Fix(com.google.errorprone.fixes.Fix) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) VariableTree(com.sun.source.tree.VariableTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) AssignmentTree(com.sun.source.tree.AssignmentTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Example 32 with Description

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();
}
Also used : ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) Set(java.util.Set) CaseTree(com.sun.source.tree.CaseTree) SwitchTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher) SwitchTree(com.sun.source.tree.SwitchTree) Collectors(java.util.stream.Collectors) Sets(com.google.common.collect.Sets) VisitorState(com.google.errorprone.VisitorState) Description(com.google.errorprone.matchers.Description) IdentifierTree(com.sun.source.tree.IdentifierTree) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BugPattern(com.google.errorprone.BugPattern) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) JDK(com.google.errorprone.BugPattern.Category.JDK) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) Type(com.sun.tools.javac.code.Type) IdentifierTree(com.sun.source.tree.IdentifierTree)

Example 33 with Description

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();
}
Also used : Symtab(com.sun.tools.javac.code.Symtab) Symtab(com.sun.tools.javac.code.Symtab) ClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher) PUBLIC(javax.lang.model.element.Modifier.PUBLIC) Symbol(com.sun.tools.javac.code.Symbol) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) Names(com.sun.tools.javac.util.Names) TypeParameterTree(com.sun.source.tree.TypeParameterTree) Iterables.getFirst(com.google.common.collect.Iterables.getFirst) VisitorState(com.google.errorprone.VisitorState) TypeParameterTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.TypeParameterTreeMatcher) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) Description(com.google.errorprone.matchers.Description) StandardTags(com.google.errorprone.BugPattern.StandardTags) BugPattern(com.google.errorprone.BugPattern) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) JDK(com.google.errorprone.BugPattern.Category.JDK) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) Tree(com.sun.source.tree.Tree) JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) Name(com.sun.tools.javac.util.Name) ASTHelpers(com.google.errorprone.util.ASTHelpers) ClassTree(com.sun.source.tree.ClassTree) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol)

Example 34 with Description

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());
}
Also used : Optional.empty(java.util.Optional.empty) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodTreeMatcher) MethodTree(com.sun.source.tree.MethodTree) Modifier(javax.lang.model.element.Modifier) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Kind(com.sun.source.tree.Tree.Kind) ImmutableList(com.google.common.collect.ImmutableList) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) ImmutableMultimap(com.google.common.collect.ImmutableMultimap) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ImmutableMap(com.google.common.collect.ImmutableMap) ASTHelpers.getReceiver(com.google.errorprone.util.ASTHelpers.getReceiver) Optional.ofNullable(java.util.Optional.ofNullable) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) Streams(com.google.common.collect.Streams) TreeScanner(com.sun.source.util.TreeScanner) Description(com.google.errorprone.matchers.Description) Optional(java.util.Optional) SUGGESTION(com.google.errorprone.BugPattern.SeverityLevel.SUGGESTION) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree)

Example 35 with Description

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;
}
Also used : DescriptionBasedDiff(com.google.errorprone.apply.DescriptionBasedDiff) JavaFileObject(javax.tools.JavaFileObject) Description(com.google.errorprone.matchers.Description) TreePath(com.sun.source.util.TreePath) SourceFile(com.google.errorprone.apply.SourceFile) ImportOrganizer(com.google.errorprone.apply.ImportOrganizer)

Aggregations

Description (com.google.errorprone.matchers.Description)56 Tree (com.sun.source.tree.Tree)23 VisitorState (com.google.errorprone.VisitorState)22 BugPattern (com.google.errorprone.BugPattern)21 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)20 ASTHelpers (com.google.errorprone.util.ASTHelpers)20 WARNING (com.google.errorprone.BugPattern.SeverityLevel.WARNING)17 ExpressionTree (com.sun.source.tree.ExpressionTree)17 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)17 JDK (com.google.errorprone.BugPattern.Category.JDK)16 Symbol (com.sun.tools.javac.code.Symbol)16 ProvidesFix (com.google.errorprone.BugPattern.ProvidesFix)14 Type (com.sun.tools.javac.code.Type)14 DescriptionBasedDiff (com.google.errorprone.apply.DescriptionBasedDiff)11 VariableTree (com.sun.source.tree.VariableTree)11 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)11 NO_MATCH (com.google.errorprone.matchers.Description.NO_MATCH)10 ClassTree (com.sun.source.tree.ClassTree)10 Optional (java.util.Optional)10 MethodTree (com.sun.source.tree.MethodTree)9