Search in sources :

Example 81 with MethodSymbol

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

the class ASTHelpersFindSuperMethodsTest method findSuperMethods_findsAllMethodsInTheHierarchy.

@Test
public void findSuperMethods_findsAllMethodsInTheHierarchy() {
    MethodSymbol fooOfNorf = scanner.getMethod("Norf", "foo");
    MethodSymbol fooOfBaz = scanner.getMethod("Baz", "foo");
    MethodSymbol fooOfBar = scanner.getMethod("Bar", "foo");
    MethodSymbol fooOfQuux = scanner.getMethod("Foo", "foo");
    assertThat(findSuperMethods(fooOfNorf)).isEqualTo(ImmutableList.of(fooOfBaz, fooOfBar, fooOfQuux));
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Test(org.junit.Test) CompilerBasedAbstractTest(com.google.errorprone.matchers.CompilerBasedAbstractTest)

Example 82 with MethodSymbol

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

the class IncompatibleArgumentType method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree methodInvocationTree, VisitorState state) {
    // example:
    // class Foo<A> {
    // <B> void bar(@CompatibleWith("A") Object o, @CompatibleWith("B") Object o2) {}
    // }
    // new Foo<Integer>().<String>bar(1, "a');
    // A Type substitution capturing <Integer> on Foo and <String> on bar(Object,Object);
    Type calledMethodType = ASTHelpers.getType(methodInvocationTree.getMethodSelect());
    // A Type substitution capturing <Integer> on Foo
    Type calledClazzType = ASTHelpers.getReceiverType(methodInvocationTree);
    List<? extends ExpressionTree> arguments = methodInvocationTree.getArguments();
    // The unbound MethodSymbol for bar(), with type parameters <A> and <B>
    MethodSymbol declaredMethod = ASTHelpers.getSymbol(methodInvocationTree);
    if (arguments.isEmpty() || declaredMethod == null) {
        return null;
    }
    List<RequiredType> requiredTypesAtCallSite = new ArrayList<>(Collections.nCopies(arguments.size(), null));
    Types types = state.getTypes();
    if (!populateTypesToEnforce(declaredMethod, calledMethodType, calledClazzType, requiredTypesAtCallSite, state)) {
        // No annotations on this method, try the supers;
        for (MethodSymbol method : ASTHelpers.findSuperMethods(declaredMethod, types)) {
            if (populateTypesToEnforce(method, calledMethodType, calledClazzType, requiredTypesAtCallSite, state)) {
                break;
            }
        }
    }
    reportAnyViolations(arguments, requiredTypesAtCallSite, state);
    // We manually report ourselves, so we don't pass any errors up the chain.
    return Description.NO_MATCH;
}
Also used : Types(com.sun.tools.javac.code.Types) EqualsIncompatibleType(com.google.errorprone.bugpatterns.EqualsIncompatibleType) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ArrayList(java.util.ArrayList)

Example 83 with MethodSymbol

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

the class UnsafeFinalization method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    MethodSymbol sym = ASTHelpers.getSymbol(tree);
    // Match invocations of static native methods.
    if (sym == null || !sym.isStatic() || !Flags.asFlagSet(sym.flags()).contains(Flag.NATIVE)) {
        return NO_MATCH;
    }
    // Find the enclosing method declaration where the invocation occurs.
    MethodTree method = enclosingMethod(state);
    if (method == null) {
        return NO_MATCH;
    }
    // Don't check native methods called from static methods and constructors:
    // static methods don't have an instance to finalize, and we shouldn't need to worry about
    // finalization during construction.
    MethodSymbol enclosing = ASTHelpers.getSymbol(method);
    if (enclosing == null || enclosing.isStatic() || enclosing.isConstructor()) {
        return NO_MATCH;
    }
    // Check if any arguments of the static native method are members (e.g. fields) of the enclosing
    // class. We're only looking for cases where the static native uses state of the enclosing class
    // that may become invalid after finalization.
    ImmutableList<Symbol> arguments = tree.getArguments().stream().map(ASTHelpers::getSymbol).filter(x -> x != null).collect(toImmutableList());
    if (arguments.stream().filter(x -> EnumSet.of(TypeKind.INT, TypeKind.LONG).contains(state.getTypes().unboxedTypeOrType(x.asType()).getKind())).noneMatch(arg -> arg.isMemberOf(enclosing.enclClass(), state.getTypes()))) {
        // no instance state is passed to the native method
        return NO_MATCH;
    }
    if (arguments.stream().anyMatch(arg -> arg.getSimpleName().contentEquals("this") && arg.isMemberOf(enclosing.enclClass(), state.getTypes()))) {
        // the instance is passed to the native method
        return NO_MATCH;
    }
    Symbol finalizeSym = getFinalizer(state, enclosing.enclClass());
    if (finalizeSym.equals(enclosing)) {
        // Don't check native methods called from within the implementation of finalize.
        return NO_MATCH;
    }
    if (finalizeSym.enclClass().equals(state.getSymtab().objectType.asElement())) {
        // Inheriting finalize from Object doesn't count.
        return NO_MATCH;
    }
    boolean[] sawFence = { false };
    new TreeScanner<Void, Void>() {

        @Override
        public Void visitMethodInvocation(MethodInvocationTree tree, Void unused) {
            if (FENCE_MATCHER.matches(tree, state)) {
                sawFence[0] = true;
            }
            return null;
        }
    }.scan(state.getPath().getCompilationUnit(), null);
    if (sawFence[0]) {
        // Ignore methods that contain a use of reachabilityFence.
        return NO_MATCH;
    }
    return describeMatch(tree);
}
Also used : MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VisitorState(com.google.errorprone.VisitorState) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ImmutableList(com.google.common.collect.ImmutableList) BugPattern(com.google.errorprone.BugPattern) Matcher(com.google.errorprone.matchers.Matcher) Tree(com.sun.source.tree.Tree) EnumSet(java.util.EnumSet) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) MethodInvocationTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.MethodInvocationTreeMatcher) ElementKind(javax.lang.model.element.ElementKind) ExpressionTree(com.sun.source.tree.ExpressionTree) ImmutableList.toImmutableList(com.google.common.collect.ImmutableList.toImmutableList) Flag(com.sun.tools.javac.code.Flags.Flag) Symbol(com.sun.tools.javac.code.Symbol) NO_MATCH(com.google.errorprone.matchers.Description.NO_MATCH) Streams(com.google.common.collect.Streams) TypeKind(javax.lang.model.type.TypeKind) TreeScanner(com.sun.source.util.TreeScanner) MethodMatchers.staticMethod(com.google.errorprone.matchers.method.MethodMatchers.staticMethod) Stream(java.util.stream.Stream) Description(com.google.errorprone.matchers.Description) Optional(java.util.Optional) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) Flags(com.sun.tools.javac.code.Flags) ASTHelpers(com.google.errorprone.util.ASTHelpers) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodTree(com.sun.source.tree.MethodTree) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) ASTHelpers(com.google.errorprone.util.ASTHelpers)

Example 84 with MethodSymbol

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

the class ProvidesNull method matchReturn.

/**
 * Matches explicit "return null" statements in methods annotated with {@code @Provides} but not
 * {@code @Nullable}. Suggests either annotating the method with {@code @Nullable} or throwing a
 * {@link RuntimeException} instead.
 */
// TODO(eaftan): Use nullness dataflow analysis when it's ready
@Override
public Description matchReturn(ReturnTree returnTree, VisitorState state) {
    ExpressionTree returnExpression = returnTree.getExpression();
    if (returnExpression == null || returnExpression.getKind() != Kind.NULL_LITERAL) {
        return Description.NO_MATCH;
    }
    TreePath path = state.getPath();
    MethodTree enclosingMethod = null;
    while (true) {
        if (path == null || path.getLeaf() instanceof LambdaExpressionTree) {
            return Description.NO_MATCH;
        } else if (path.getLeaf() instanceof MethodTree) {
            enclosingMethod = (MethodTree) path.getLeaf();
            break;
        } else {
            path = path.getParentPath();
        }
    }
    MethodSymbol enclosingMethodSym = ASTHelpers.getSymbol(enclosingMethod);
    if (enclosingMethodSym == null) {
        return Description.NO_MATCH;
    }
    if (!ASTHelpers.hasAnnotation(enclosingMethodSym, "dagger.Provides", state) || ASTHelpers.hasDirectAnnotationWithSimpleName(enclosingMethodSym, "Nullable")) {
        return Description.NO_MATCH;
    }
    Fix addNullableFix = SuggestedFix.builder().prefixWith(enclosingMethod, "@Nullable\n").addImport("javax.annotation.Nullable").build();
    CatchTree enclosingCatch = ASTHelpers.findEnclosingNode(state.getPath(), CatchTree.class);
    if (enclosingCatch == null) {
        // If not in a catch block, suggest adding @Nullable first, then throwing an exception.
        Fix throwRuntimeExceptionFix = SuggestedFix.replace(returnTree, "throw new RuntimeException();");
        return buildDescription(returnTree).addFix(addNullableFix).addFix(throwRuntimeExceptionFix).build();
    } else {
        // If in a catch block, suggest throwing an exception first, then adding @Nullable.
        String replacement = String.format("throw new RuntimeException(%s);", enclosingCatch.getParameter().getName());
        Fix throwRuntimeExceptionFix = SuggestedFix.replace(returnTree, replacement);
        return buildDescription(returnTree).addFix(throwRuntimeExceptionFix).addFix(addNullableFix).build();
    }
}
Also used : LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) TreePath(com.sun.source.util.TreePath) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) MethodTree(com.sun.source.tree.MethodTree) CatchTree(com.sun.source.tree.CatchTree) ExpressionTree(com.sun.source.tree.ExpressionTree) LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree)

Example 85 with MethodSymbol

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

the class RefasterRuleBuilderScanner method visitMethod.

@Override
public Void visitMethod(MethodTree tree, Void v) {
    try {
        VisitorState state = new VisitorState(context);
        logger.log(FINE, "Discovered method with name {0}", tree.getName());
        if (ASTHelpers.hasAnnotation(tree, Placeholder.class, state)) {
            checkArgument(tree.getModifiers().getFlags().contains(Modifier.ABSTRACT), "@Placeholder methods are expected to be abstract");
            UTemplater templater = new UTemplater(context);
            ImmutableMap.Builder<UVariableDecl, ImmutableClassToInstanceMap<Annotation>> params = ImmutableMap.builder();
            for (VariableTree param : tree.getParameters()) {
                params.put(templater.visitVariable(param, null), UTemplater.annotationMap(ASTHelpers.getSymbol(param)));
            }
            MethodSymbol sym = ASTHelpers.getSymbol(tree);
            placeholderMethods.put(sym, PlaceholderMethod.create(tree.getName(), templater.template(sym.getReturnType()), params.build(), UTemplater.annotationMap(sym)));
        } else if (ASTHelpers.hasAnnotation(tree, BeforeTemplate.class, state)) {
            checkState(afterTemplates.isEmpty(), "BeforeTemplate must come before AfterTemplate");
            Template<?> template = UTemplater.createTemplate(context, tree);
            beforeTemplates.add(template);
            if (template instanceof BlockTemplate) {
                context.put(UTemplater.REQUIRE_BLOCK_KEY, /* data= */
                true);
            }
        } else if (ASTHelpers.hasAnnotation(tree, AfterTemplate.class, state)) {
            afterTemplates.add(UTemplater.createTemplate(context, tree));
        } else if (tree.getModifiers().getFlags().contains(Modifier.ABSTRACT)) {
            throw new IllegalArgumentException("Placeholder methods must have @Placeholder, but abstract method does not: " + tree);
        }
        return null;
    } catch (Throwable t) {
        throw new RuntimeException("Error analysing: " + tree.getName(), t);
    }
}
Also used : BeforeTemplate(com.google.errorprone.refaster.annotation.BeforeTemplate) ImmutableClassToInstanceMap(com.google.common.collect.ImmutableClassToInstanceMap) VariableTree(com.sun.source.tree.VariableTree) ImmutableMap(com.google.common.collect.ImmutableMap) BeforeTemplate(com.google.errorprone.refaster.annotation.BeforeTemplate) AfterTemplate(com.google.errorprone.refaster.annotation.AfterTemplate) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) VisitorState(com.google.errorprone.VisitorState)

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