Search in sources :

Example 1 with NO_MATCH

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

the class MissingDefault method matchSwitch.

@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
    Type switchType = ASTHelpers.getType(tree.getExpression());
    if (switchType.asElement().getKind() == ElementKind.ENUM) {
        // by MissingCasesInEnumSwitch
        return NO_MATCH;
    }
    Optional<? extends CaseTree> maybeDefault = tree.getCases().stream().filter(c -> c.getExpression() == null).findFirst();
    if (!maybeDefault.isPresent()) {
        Description.Builder description = buildDescription(tree);
        if (!tree.getCases().isEmpty()) {
            // Inserting the default after the last case is easier than finding the closing brace
            // for the switch statement. Hopefully we don't often see switches with zero cases.
            description.addFix(SuggestedFix.postfixWith(getLast(tree.getCases()), "\ndefault: // fall out\n"));
        }
        return description.build();
    }
    CaseTree defaultCase = maybeDefault.get();
    if (!defaultCase.getStatements().isEmpty()) {
        return NO_MATCH;
    }
    int idx = tree.getCases().indexOf(defaultCase);
    // The default case may appear before a non-default case, in which case the documentation
    // should say "fall through" instead of "fall out".
    boolean isLast = idx == tree.getCases().size() - 1;
    int end = isLast ? state.getEndPosition(tree) : ((JCTree) tree.getCases().get(idx + 1)).getStartPosition();
    if (ErrorProneTokens.getTokens(state.getSourceCode().subSequence(state.getEndPosition(defaultCase), end).toString(), state.context).stream().anyMatch(t -> !t.comments().isEmpty())) {
        return NO_MATCH;
    }
    return buildDescription(defaultCase).setMessage("Default case should be documented with a comment").addFix(SuggestedFix.postfixWith(defaultCase, isLast ? " // fall out" : " // fall through")).build();
}
Also used : ElementKind(javax.lang.model.element.ElementKind) Iterables.getLast(com.google.common.collect.Iterables.getLast) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) CaseTree(com.sun.source.tree.CaseTree) JCTree(com.sun.tools.javac.tree.JCTree) SwitchTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher) SwitchTree(com.sun.source.tree.SwitchTree) VisitorState(com.google.errorprone.VisitorState) ErrorProneTokens(com.google.errorprone.util.ErrorProneTokens) Description(com.google.errorprone.matchers.Description) BugPattern(com.google.errorprone.BugPattern) Optional(java.util.Optional) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) JDK(com.google.errorprone.BugPattern.Category.JDK) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) CaseTree(com.sun.source.tree.CaseTree) Type(com.sun.tools.javac.code.Type) Description(com.google.errorprone.matchers.Description)

Example 2 with NO_MATCH

use of com.google.errorprone.matchers.Description.NO_MATCH 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 3 with NO_MATCH

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

the class UnnecessaryDefaultInEnumSwitch method matchSwitch.

@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
    TypeSymbol switchType = ((JCSwitch) tree).getExpression().type.tsym;
    if (switchType.getKind() != ElementKind.ENUM) {
        return NO_MATCH;
    }
    Optional<? extends CaseTree> maybeDefaultCase = tree.getCases().stream().filter(c -> c.getExpression() == null).findFirst();
    if (!maybeDefaultCase.isPresent()) {
        return NO_MATCH;
    }
    CaseTree defaultCase = maybeDefaultCase.get();
    Set<String> handledCases = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(p -> ((IdentifierTree) p).getName().toString()).collect(toImmutableSet());
    if (!ASTHelpers.enumValues(switchType).equals(handledCases)) {
        return NO_MATCH;
    }
    Fix fix;
    List<? extends StatementTree> defaultStatements = defaultCase.getStatements();
    if (trivialDefault(defaultStatements)) {
        // deleting `default:` or `default: break;` is a no-op
        fix = SuggestedFix.delete(defaultCase);
    } else if (!canCompleteNormally(tree)) {
        // if the switch statement cannot complete normally, then deleting the default
        // and moving its statements to after the switch statement is a no-op
        String defaultSource = state.getSourceCode().subSequence(((JCTree) defaultStatements.get(0)).getStartPosition(), state.getEndPosition(getLast(defaultStatements))).toString();
        fix = SuggestedFix.builder().delete(defaultCase).postfixWith(tree, defaultSource).build();
    } else {
        return NO_MATCH;
    }
    return describeMatch(defaultCase, fix);
}
Also used : SwitchTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher) VisitorState(com.google.errorprone.VisitorState) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) IdentifierTree(com.sun.source.tree.IdentifierTree) ImmutableSet.toImmutableSet(com.google.common.collect.ImmutableSet.toImmutableSet) BugPattern(com.google.errorprone.BugPattern) JDK(com.google.errorprone.BugPattern.Category.JDK) Fix(com.google.errorprone.fixes.Fix) Tree(com.sun.source.tree.Tree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) ElementKind(javax.lang.model.element.ElementKind) Set(java.util.Set) Iterables.getLast(com.google.common.collect.Iterables.getLast) Iterables.getOnlyElement(com.google.common.collect.Iterables.getOnlyElement) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) CaseTree(com.sun.source.tree.CaseTree) JCTree(com.sun.tools.javac.tree.JCTree) SwitchTree(com.sun.source.tree.SwitchTree) List(java.util.List) Description(com.google.errorprone.matchers.Description) StatementTree(com.sun.source.tree.StatementTree) Optional(java.util.Optional) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Reachability.canCompleteNormally(com.google.errorprone.util.Reachability.canCompleteNormally) ASTHelpers(com.google.errorprone.util.ASTHelpers) CaseTree(com.sun.source.tree.CaseTree) JCSwitch(com.sun.tools.javac.tree.JCTree.JCSwitch) Fix(com.google.errorprone.fixes.Fix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) IdentifierTree(com.sun.source.tree.IdentifierTree) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol)

Aggregations

BugPattern (com.google.errorprone.BugPattern)3 JDK (com.google.errorprone.BugPattern.Category.JDK)3 WARNING (com.google.errorprone.BugPattern.SeverityLevel.WARNING)3 VisitorState (com.google.errorprone.VisitorState)3 Description (com.google.errorprone.matchers.Description)3 NO_MATCH (com.google.errorprone.matchers.Description.NO_MATCH)3 Iterables.getLast (com.google.common.collect.Iterables.getLast)2 SwitchTreeMatcher (com.google.errorprone.bugpatterns.BugChecker.SwitchTreeMatcher)2 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)2 ASTHelpers (com.google.errorprone.util.ASTHelpers)2 CaseTree (com.sun.source.tree.CaseTree)2 SwitchTree (com.sun.source.tree.SwitchTree)2 Tree (com.sun.source.tree.Tree)2 JCTree (com.sun.tools.javac.tree.JCTree)2 List (java.util.List)2 Optional (java.util.Optional)2 ElementKind (javax.lang.model.element.ElementKind)2 ImmutableSet.toImmutableSet (com.google.common.collect.ImmutableSet.toImmutableSet)1 Iterables.getOnlyElement (com.google.common.collect.Iterables.getOnlyElement)1 ClassTreeMatcher (com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher)1