Search in sources :

Example 1 with Description

use of com.google.errorprone.matchers.Description in project error-prone by google.

the class FilesLinesLeak method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    if (!MATCHER.matches(tree, state)) {
        return NO_MATCH;
    }
    if (inTWR(state)) {
        return NO_MATCH;
    }
    Description.Builder description = buildDescription(tree);
    Tree parent = state.getPath().getParentPath().getLeaf();
    if (parent instanceof MemberSelectTree) {
        MemberSelectTree select = (MemberSelectTree) parent;
        StatementTree statement = state.findEnclosing(StatementTree.class);
        SuggestedFix.Builder fix = SuggestedFix.builder();
        if (statement instanceof VariableTree) {
            VariableTree var = (VariableTree) statement;
            int pos = ((JCTree) var).getStartPosition();
            int initPos = ((JCTree) var.getInitializer()).getStartPosition();
            int eqPos = pos + state.getSourceForNode(var).substring(0, initPos - pos).lastIndexOf('=');
            fix.replace(eqPos, initPos, String.format(";\ntry (Stream<String> stream = %s) {\n%s =", state.getSourceForNode(tree), var.getName().toString()));
        } else {
            fix.prefixWith(statement, String.format("try (Stream<String> stream = %s) {\n", state.getSourceForNode(tree)));
            fix.replace(select.getExpression(), "stream");
        }
        fix.replace(tree, "stream");
        fix.postfixWith(statement, "}");
        fix.addImport("java.util.stream.Stream");
        description.addFix(fix.build());
    }
    return description.build();
}
Also used : StatementTree(com.sun.source.tree.StatementTree) Description(com.google.errorprone.matchers.Description) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) MemberSelectTree(com.sun.source.tree.MemberSelectTree) VariableTree(com.sun.source.tree.VariableTree) ExpressionTree(com.sun.source.tree.ExpressionTree) VariableTree(com.sun.source.tree.VariableTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) JCTree(com.sun.tools.javac.tree.JCTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) StatementTree(com.sun.source.tree.StatementTree) Tree(com.sun.source.tree.Tree) JCTree(com.sun.tools.javac.tree.JCTree)

Example 2 with Description

use of com.google.errorprone.matchers.Description in project error-prone by google.

the class Overrides method matchMethod.

@Override
public Description matchMethod(MethodTree methodTree, VisitorState state) {
    MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodTree);
    boolean isVarargs = (methodSymbol.flags() & Flags.VARARGS) != 0;
    Set<MethodSymbol> superMethods = ASTHelpers.findSuperMethods(methodSymbol, state.getTypes());
    // If there are no super methods, we're fine:
    if (superMethods.isEmpty()) {
        return Description.NO_MATCH;
    }
    Iterator<MethodSymbol> superMethodsIterator = superMethods.iterator();
    boolean areSupersVarargs = superMethodsIterator.next().isVarArgs();
    while (superMethodsIterator.hasNext()) {
        if (areSupersVarargs != superMethodsIterator.next().isVarArgs()) {
            // current method is inconsistent with some of its supermethods, so report a match.
            return describeMatch(methodTree);
        }
    }
    // The current method is consistent with all of its supermethods:
    if (isVarargs == areSupersVarargs) {
        return Description.NO_MATCH;
    }
    // The current method is inconsistent with all of its supermethods, so flip the varargs-ness
    // of the current method.
    List<? extends VariableTree> parameterTree = methodTree.getParameters();
    Tree paramType = parameterTree.get(parameterTree.size() - 1).getType();
    CharSequence paramTypeSource = state.getSourceForNode(paramType);
    if (paramTypeSource == null) {
        // No fix if we don't have tree end positions.
        return describeMatch(methodTree);
    }
    Description.Builder descriptionBuilder = buildDescription(methodTree);
    if (isVarargs) {
        descriptionBuilder.addFix(SuggestedFix.replace(paramType, "[]", paramTypeSource.length() - 3, 0));
    } else {
        // There may be a comment that includes a '[' character between the open and closed
        // brackets of the array type.  If so, we don't return a fix.
        int arrayOpenIndex = paramTypeSource.length() - 2;
        while (paramTypeSource.charAt(arrayOpenIndex) == ' ') {
            arrayOpenIndex--;
        }
        if (paramTypeSource.charAt(arrayOpenIndex) == '[') {
            descriptionBuilder.addFix(SuggestedFix.replace(paramType, "...", arrayOpenIndex, 0));
        }
    }
    return descriptionBuilder.build();
}
Also used : Description(com.google.errorprone.matchers.Description) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) Tree(com.sun.source.tree.Tree)

Example 3 with Description

use of com.google.errorprone.matchers.Description in project error-prone by google.

the class AbstractArgumentParameterChecker method findReplacements.

private Description findReplacements(List<? extends ExpressionTree> args, com.sun.tools.javac.util.List<VarSymbol> params, boolean isVarArgs, VisitorState state, Tree tree) {
    if (args.isEmpty()) {
        return Description.NO_MATCH;
    }
    ImmutableSet<PotentialReplacement> potentialReplacements = potentialReplacementsFunction.apply(state.withPath(new TreePath(state.getPath(), args.get(0))));
    SuggestedFix.Builder fix = SuggestedFix.builder();
    // Don't suggest for the varargs parameter.
    // TODO(eaftan): Reconsider this, especially if the argument is of array type or is itself
    // a varargs parameter.
    int maxArg = isVarArgs ? params.size() - 1 : params.size();
    for (int i = 0; i < maxArg; i++) {
        ExpressionTree arg = args.get(i);
        VarSymbol param = params.get(i);
        if (!validKinds.contains(arg.getKind()) || !parameterPredicate.test(param)) {
            continue;
        }
        String extractedArgumentName = extractArgumentName(arg);
        if (extractedArgumentName == null) {
            continue;
        }
        double currSimilarity = similarityMetric.applyAsDouble(extractedArgumentName, param.getSimpleName().toString());
        if (1.0 - currSimilarity < beta) {
            // No way for any replacement to be at least BETA better than the current argument
            continue;
        }
        ReplacementWithSimilarity bestReplacement = potentialReplacements.stream().filter(replacement -> !replacement.sym().equals(ASTHelpers.getSymbol(arg))).filter(replacement -> isSubtypeHandleCompletionFailures(replacement.sym(), param, state)).map(replacement -> ReplacementWithSimilarity.create(replacement, similarityMetric.applyAsDouble(replacement.argumentName(), param.getSimpleName().toString()))).max(Comparator.comparingDouble(ReplacementWithSimilarity::similarity)).orElse(null);
        if ((bestReplacement != null) && (bestReplacement.similarity() - currSimilarity >= beta)) {
            fix.replace(arg, bestReplacement.replacement().replacementString());
        }
    }
    if (fix.isEmpty()) {
        return Description.NO_MATCH;
    } else {
        return describeMatch(tree, fix.build());
    }
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Function(java.util.function.Function) NewClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.NewClassTreeMatcher) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Kind(com.sun.source.tree.Tree.Kind) NewClassTree(com.sun.source.tree.NewClassTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) Nullable(javax.annotation.Nullable) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MethodInvocationTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher) TreePath(com.sun.source.util.TreePath) ImmutableSet(com.google.common.collect.ImmutableSet) ExpressionTree(com.sun.source.tree.ExpressionTree) Predicate(java.util.function.Predicate) Symbol(com.sun.tools.javac.code.Symbol) MemberSelectTree(com.sun.source.tree.MemberSelectTree) ToDoubleBiFunction(java.util.function.ToDoubleBiFunction) List(java.util.List) CompletionFailure(com.sun.tools.javac.code.Symbol.CompletionFailure) Description(com.google.errorprone.matchers.Description) AutoValue(com.google.auto.value.AutoValue) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Comparator(java.util.Comparator) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ExpressionTree(com.sun.source.tree.ExpressionTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Example 4 with Description

use of com.google.errorprone.matchers.Description in project error-prone by google.

the class AmbiguousMethodReference method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ClassSymbol origin = getSymbol(tree);
    Types types = state.getTypes();
    Iterable<Symbol> members = types.membersClosure(getType(tree), /*skipInterface=*/
    false).getSymbols();
    // collect declared and inherited methods, grouped by reference descriptor
    Map<String, List<MethodSymbol>> methods = stream(members.spliterator(), false).filter(MethodSymbol.class::isInstance).map(MethodSymbol.class::cast).filter(m -> m.isConstructor() || m.owner.equals(origin)).collect(groupingBy(m -> methodReferenceDescriptor(types, m), toCollection(ArrayList::new)));
    // look for groups of ambiguous method references
    for (Tree member : tree.getMembers()) {
        if (!(member instanceof MethodTree)) {
            continue;
        }
        MethodSymbol msym = getSymbol((MethodTree) member);
        if (isSuppressed(msym)) {
            continue;
        }
        List<MethodSymbol> clash = methods.remove(methodReferenceDescriptor(types, msym));
        if (clash == null) {
            continue;
        }
        clash.remove(msym);
        // ignore overridden inherited methods and hidden interface methods
        clash.removeIf(m -> types.isSubSignature(msym.type, m.type));
        if (clash.isEmpty()) {
            continue;
        }
        String message = String.format("This method's reference is ambiguous, its name and functional interface type" + " are the same as: %s", clash.stream().map(m -> Signatures.prettyMethodSignature(origin, m)).collect(joining(", ")));
        state.reportMatch(buildDescription(member).setMessage(message).build());
    }
    return NO_MATCH;
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher) MethodTree(com.sun.source.tree.MethodTree) Collectors.groupingBy(java.util.stream.Collectors.groupingBy) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) ASTHelpers.getType(com.google.errorprone.util.ASTHelpers.getType) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) Collectors.joining(java.util.stream.Collectors.joining) ArrayList(java.util.ArrayList) Collectors.toCollection(java.util.stream.Collectors.toCollection) VisitorState(com.google.errorprone.VisitorState) List(java.util.List) Types(com.sun.tools.javac.code.Types) StreamSupport.stream(java.util.stream.StreamSupport.stream) Signatures(com.google.errorprone.util.Signatures) Description(com.google.errorprone.matchers.Description) Map(java.util.Map) BugPattern(com.google.errorprone.BugPattern) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) JDK(com.google.errorprone.BugPattern.Category.JDK) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) Types(com.sun.tools.javac.code.Types) MethodTree(com.sun.source.tree.MethodTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ASTHelpers.getSymbol(com.google.errorprone.util.ASTHelpers.getSymbol) Symbol(com.sun.tools.javac.code.Symbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) ArrayList(java.util.ArrayList) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) ArrayList(java.util.ArrayList) List(java.util.List)

Example 5 with Description

use of com.google.errorprone.matchers.Description in project error-prone by google.

the class BigDecimalLiteralDouble method createDescription.

public Description createDescription(ExpressionTree tree, ExpressionTree arg, VisitorState state, boolean suggestIntegral) {
    String literal = state.getSourceForNode(arg);
    if (literal == null) {
        return describeMatch(tree);
    }
    // BigDecimal doesn't seem to support underscores or terminal Ds in its string parsing
    literal = literal.replaceAll("[_dD]", "");
    BigDecimal intendedValue = new BigDecimal(literal);
    Optional<BigInteger> integralValue = asBigInteger(intendedValue);
    Description.Builder description = buildDescription(tree);
    if (suggestIntegral && integralValue.isPresent() && isWithinLongRange(integralValue.get())) {
        long longValue = integralValue.get().longValue();
        String suggestedString;
        switch(Ints.saturatedCast(longValue)) {
            case 0:
                suggestedString = "BigDecimal.ZERO";
                break;
            case 1:
                suggestedString = "BigDecimal.ONE";
                break;
            case 10:
                suggestedString = "BigDecimal.TEN";
                break;
            default:
                suggestedString = "new BigDecimal(" + longValue + "L)";
        }
        description.addFix(SuggestedFix.builder().addImport("java.math.BigDecimal").replace(tree, suggestedString).build());
    }
    description.addFix(SuggestedFix.builder().addImport("java.math.BigDecimal").replace(tree, "new BigDecimal(\"" + literal + "\")").build());
    return description.build();
}
Also used : Description(com.google.errorprone.matchers.Description) BigInteger(java.math.BigInteger) BigDecimal(java.math.BigDecimal)

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