Search in sources :

Example 71 with MethodSymbol

use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.

the class MutableMethodReturnType method matchMethod.

@Override
public Description matchMethod(MethodTree methodTree, VisitorState state) {
    MethodSymbol methodSymbol = ASTHelpers.getSymbol(methodTree);
    if (methodSymbol.isConstructor()) {
        return Description.NO_MATCH;
    }
    if (isMethodCanBeOverridden(methodSymbol, state)) {
        return Description.NO_MATCH;
    }
    if (ANNOTATED_WITH_PRODUCES_OR_PROVIDES.matches(methodTree, state)) {
        return Description.NO_MATCH;
    }
    Type returnType = methodSymbol.getReturnType();
    if (ImmutableCollections.isImmutableType(returnType)) {
        return Description.NO_MATCH;
    }
    ImmutableSet<ClassType> returnStatementsTypes = getMethodReturnTypes(methodTree);
    if (returnStatementsTypes.isEmpty()) {
        return Description.NO_MATCH;
    }
    boolean alwaysReturnsImmutableType = returnStatementsTypes.stream().allMatch(ImmutableCollections::isImmutableType);
    if (!alwaysReturnsImmutableType) {
        return Description.NO_MATCH;
    }
    Optional<String> immutableReturnType = ImmutableCollections.mutableToImmutable(getTypeQualifiedName(returnType));
    if (!immutableReturnType.isPresent()) {
        immutableReturnType = getCommonImmutableTypeForAllReturnStatementsTypes(returnStatementsTypes);
    }
    if (!immutableReturnType.isPresent()) {
        return Description.NO_MATCH;
    }
    Type newReturnType = state.getTypeFromString(immutableReturnType.get());
    SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
    fixBuilder.replace(getTypeTree(methodTree.getReturnType()), SuggestedFixes.qualifyType(state, fixBuilder, newReturnType.asElement()));
    SuggestedFix fix = fixBuilder.build();
    return describeMatch(methodTree.getReturnType(), fix);
}
Also used : ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) ClassType(com.sun.tools.javac.code.Type.ClassType)

Example 72 with MethodSymbol

use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.

the class MissingSuperCall method matchAnnotation.

/**
 * Prevents abstract methods from being annotated with {@code @CallSuper} et al. It doesn't make
 * sense to require overriders to call a method with no implementation.
 */
@Override
public Description matchAnnotation(AnnotationTree tree, VisitorState state) {
    if (!ANNOTATION_MATCHER.matches(tree, state)) {
        return Description.NO_MATCH;
    }
    MethodTree methodTree = ASTHelpers.findEnclosingNode(state.getPath(), MethodTree.class);
    if (methodTree == null) {
        return Description.NO_MATCH;
    }
    MethodSymbol methodSym = ASTHelpers.getSymbol(methodTree);
    if (methodSym == null) {
        return Description.NO_MATCH;
    }
    if (!methodSym.getModifiers().contains(Modifier.ABSTRACT)) {
        return Description.NO_MATCH;
    }
    // Match, find the matched annotation to use for the error message.
    Symbol annotationSym = ASTHelpers.getSymbol(tree);
    if (annotationSym == null) {
        return Description.NO_MATCH;
    }
    return buildDescription(tree).setMessage(String.format("@%s cannot be applied to an abstract method", annotationSym.getSimpleName())).build();
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Symbol(com.sun.tools.javac.code.Symbol)

Example 73 with MethodSymbol

use of com.sun.tools.javac.code.Symbol.MethodSymbol 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 74 with MethodSymbol

use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.

the class ParameterName method checkArguments.

private void checkArguments(Tree tree, List<? extends ExpressionTree> arguments, VisitorState state) {
    if (arguments.isEmpty()) {
        return;
    }
    MethodSymbol sym = (MethodSymbol) ASTHelpers.getSymbol(tree);
    if (NamedParameterComment.containsSyntheticParameterName(sym)) {
        return;
    }
    int start = ((JCTree) tree).getStartPosition();
    int end = state.getEndPosition(getLast(arguments));
    String source = state.getSourceCode().subSequence(start, end).toString();
    if (!source.contains("/*")) {
        // fast path if the arguments don't contain anything that looks like a comment
        return;
    }
    Deque<ErrorProneToken> tokens = new ArrayDeque<>(ErrorProneTokens.getTokens(source, state.context));
    forEachPair(sym.getParameters().stream(), arguments.stream(), (p, a) -> {
        while (!tokens.isEmpty() && ((start + tokens.peekFirst().pos()) < ((JCTree) a).getStartPosition())) {
            tokens.removeFirst();
        }
        if (tokens.isEmpty()) {
            return;
        }
        Range<Integer> argRange = Range.closedOpen(((JCTree) a).getStartPosition(), state.getEndPosition(a));
        if (!argRange.contains(start + tokens.peekFirst().pos())) {
            return;
        }
        checkArgument(p, a, start, tokens.removeFirst(), state);
    });
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ErrorProneToken(com.google.errorprone.util.ErrorProneToken) JCTree(com.sun.tools.javac.tree.JCTree) ArrayDeque(java.util.ArrayDeque)

Example 75 with MethodSymbol

use of com.sun.tools.javac.code.Symbol.MethodSymbol in project error-prone by google.

the class AbstractExpectedExceptionChecker method buildBaseFix.

protected BaseFix buildBaseFix(VisitorState state, List<Tree> expectations, @Nullable StatementTree failure) {
    String exceptionClass = "Throwable";
    // additional assertions to perform on the captured exception (if any)
    List<String> newAsserts = new ArrayList<>();
    Builder fix = SuggestedFix.builder();
    for (Tree expectation : expectations) {
        MethodInvocationTree invocation = (MethodInvocationTree) ((ExpressionStatementTree) expectation).getExpression();
        MethodSymbol symbol = ASTHelpers.getSymbol(invocation);
        Symtab symtab = state.getSymtab();
        List<? extends ExpressionTree> args = invocation.getArguments();
        switch(symbol.getSimpleName().toString()) {
            case "expect":
                Type type = ASTHelpers.getType(getOnlyElement(invocation.getArguments()));
                if (isSubtype(type, symtab.classType, state)) {
                    // expect(Class<?>)
                    exceptionClass = state.getSourceForNode(getReceiver(getOnlyElement(args)));
                } else if (isSubtype(type, state.getTypeFromString("org.hamcrest.Matcher"), state)) {
                    Type matcherType = state.getTypes().asSuper(type, state.getSymbolFromString("org.hamcrest.Matcher"));
                    if (!matcherType.getTypeArguments().isEmpty()) {
                        Type matchType = getOnlyElement(matcherType.getTypeArguments());
                        if (isSubtype(matchType, symtab.throwableType, state)) {
                            exceptionClass = SuggestedFixes.qualifyType(state, fix, matchType);
                        }
                    }
                    // expect(Matcher)
                    fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
                    newAsserts.add(String.format("assertThat(thrown, %s);", state.getSourceForNode(getOnlyElement(args))));
                }
                break;
            case "expectCause":
                ExpressionTree matcher = getOnlyElement(invocation.getArguments());
                if (IS_A.matches(matcher, state)) {
                    fix.addStaticImport("com.google.common.truth.Truth.assertThat");
                    newAsserts.add(String.format("assertThat(thrown).hasCauseThat().isInstanceOf(%s);", state.getSourceForNode(getOnlyElement(((MethodInvocationTree) matcher).getArguments()))));
                } else {
                    fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
                    newAsserts.add(String.format("assertThat(thrown.getCause(), %s);", state.getSourceForNode(getOnlyElement(args))));
                }
                break;
            case "expectMessage":
                if (isSubtype(getOnlyElement(symbol.getParameters()).asType(), symtab.stringType, state)) {
                    // expectedMessage(String)
                    fix.addStaticImport("com.google.common.truth.Truth.assertThat");
                    newAsserts.add(String.format("assertThat(thrown).hasMessageThat().contains(%s);", state.getSourceForNode(getOnlyElement(args))));
                } else {
                    // expectedMessage(Matcher)
                    fix.addStaticImport("org.hamcrest.MatcherAssert.assertThat");
                    newAsserts.add(String.format("assertThat(thrown.getMessage(), %s);", state.getSourceForNode(getOnlyElement(args))));
                }
                break;
            default:
                throw new AssertionError("unknown expect method: " + symbol.getSimpleName());
        }
    }
    // remove all interactions with the ExpectedException rule
    fix.replace(((JCTree) expectations.get(0)).getStartPosition(), state.getEndPosition(getLast(expectations)), "");
    if (failure != null) {
        fix.delete(failure);
    }
    return new BaseFix(fix.build(), exceptionClass, newAsserts);
}
Also used : Builder(com.google.errorprone.fixes.SuggestedFix.Builder) ArrayList(java.util.ArrayList) Symtab(com.sun.tools.javac.code.Symtab) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) MethodTree(com.sun.source.tree.MethodTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) JCTree(com.sun.tools.javac.tree.JCTree) ExpressionStatementTree(com.sun.source.tree.ExpressionStatementTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) ExpressionTree(com.sun.source.tree.ExpressionTree)

Aggregations

MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)98 Symbol (com.sun.tools.javac.code.Symbol)35 Type (com.sun.tools.javac.code.Type)32 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)27 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)22 MethodTree (com.sun.source.tree.MethodTree)22 Tree (com.sun.source.tree.Tree)21 ArrayList (java.util.ArrayList)18 ExpressionTree (com.sun.source.tree.ExpressionTree)17 TypeSymbol (com.sun.tools.javac.code.Symbol.TypeSymbol)13 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)13 Description (com.google.errorprone.matchers.Description)11 ClassTree (com.sun.source.tree.ClassTree)11 VisitorState (com.google.errorprone.VisitorState)10 JCTree (com.sun.tools.javac.tree.JCTree)9 Types (com.sun.tools.javac.code.Types)8 BugPattern (com.google.errorprone.BugPattern)7 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)7 MemberSelectTree (com.sun.source.tree.MemberSelectTree)7 MethodType (com.sun.tools.javac.code.Type.MethodType)7