Search in sources :

Example 36 with Symbol

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

the class ASTHelpers method getRootAssignable.

/**
   * Find the root assignable expression of a chain of field accesses.  If there is no root
   * (i.e, a bare method call or a static method call), return null.
   *
   * <p>Examples:
   * <pre>
   * {@code
   *    a.trim().intern() ==> a
   *    a.b.trim().intern() ==> a.b
   *    this.intValue.foo() ==> this.intValue
   *    this.foo() ==> this
   *    intern() ==> null
   *    String.format() ==> null
   *    java.lang.String.format() ==> null
   * }
   * </pre>
   */
public static ExpressionTree getRootAssignable(MethodInvocationTree methodInvocationTree) {
    if (!(methodInvocationTree instanceof JCMethodInvocation)) {
        throw new IllegalArgumentException("Expected type to be JCMethodInvocation, but was " + methodInvocationTree.getClass());
    }
    // Check for bare method call, e.g. intern().
    if (((JCMethodInvocation) methodInvocationTree).getMethodSelect() instanceof JCIdent) {
        return null;
    }
    // Unwrap the field accesses until you get to an identifier.
    ExpressionTree expr = methodInvocationTree;
    while (expr instanceof JCMethodInvocation) {
        expr = ((JCMethodInvocation) expr).getMethodSelect();
        if (expr instanceof JCFieldAccess) {
            expr = ((JCFieldAccess) expr).getExpression();
        }
    }
    // We only want assignable identifiers.
    Symbol sym = getSymbol(expr);
    if (sym instanceof VarSymbol) {
        return expr;
    }
    return null;
}
Also used : JCMethodInvocation(com.sun.tools.javac.tree.JCTree.JCMethodInvocation) JCIdent(com.sun.tools.javac.tree.JCTree.JCIdent) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) ExpressionTree(com.sun.source.tree.ExpressionTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol)

Example 37 with Symbol

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

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

the class BadAnnotationImplementation method matchClass.

@Override
public Description matchClass(ClassTree classTree, final VisitorState state) {
    if (!CLASS_TREE_MATCHER.matches(classTree, state)) {
        return Description.NO_MATCH;
    }
    // If this is an enum that is trying to implement Annotation, give a special error message.
    if (classTree.getKind() == Kind.ENUM) {
        return buildDescription(classTree).setMessage("Enums cannot correctly implement Annotation because their equals and hashCode " + "methods are final. Consider using AutoAnnotation instead of implementing " + "Annotation by hand.").build();
    }
    // Otherwise walk up type hierarchy looking for equals and hashcode methods
    MethodSymbol equals = null;
    MethodSymbol hashCode = null;
    final Types types = state.getTypes();
    Name equalsName = state.getName("equals");
    Predicate<MethodSymbol> equalsPredicate = new Predicate<MethodSymbol>() {

        @Override
        public boolean apply(MethodSymbol methodSymbol) {
            return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().size() == 1 && types.isSameType(methodSymbol.getParameters().get(0).type, state.getSymtab().objectType);
        }
    };
    Name hashCodeName = state.getName("hashCode");
    Predicate<MethodSymbol> hashCodePredicate = new Predicate<MethodSymbol>() {

        @Override
        public boolean apply(MethodSymbol methodSymbol) {
            return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().isEmpty();
        }
    };
    for (Type sup : types.closure(ASTHelpers.getSymbol(classTree).type)) {
        if (equals == null) {
            equals = getMatchingMethod(sup, equalsName, equalsPredicate);
        }
        if (hashCode == null) {
            hashCode = getMatchingMethod(sup, hashCodeName, hashCodePredicate);
        }
    }
    Verify.verifyNotNull(equals);
    Verify.verifyNotNull(hashCode);
    Symbol objectSymbol = state.getSymtab().objectType.tsym;
    if (equals.owner.equals(objectSymbol) || hashCode.owner.equals(objectSymbol)) {
        return describeMatch(classTree);
    }
    return Description.NO_MATCH;
}
Also used : Types(com.sun.tools.javac.code.Types) Type(com.sun.tools.javac.code.Type) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) Symbol(com.sun.tools.javac.code.Symbol) Name(com.sun.tools.javac.util.Name) Predicate(com.google.common.base.Predicate)

Example 39 with Symbol

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

the class FindIdentifiers method createFindIdentifiersScanner.

/**
   * Finds all identifiers in a tree. Takes an optional stop point as its argument: the depth-first
   * walk will stop if this node is encountered.
   */
private static final TreeScanner<Void, Void> createFindIdentifiersScanner(ImmutableSet.Builder<Symbol> builder, @Nullable Tree stoppingPoint) {
    return new TreeScanner<Void, Void>() {

        @Override
        public Void scan(Tree tree, Void unused) {
            return Objects.equals(stoppingPoint, tree) ? null : super.scan(tree, unused);
        }

        @Override
        public Void scan(Iterable<? extends Tree> iterable, Void unused) {
            if (stoppingPoint != null && iterable != null) {
                ImmutableList.Builder<Tree> builder = ImmutableList.builder();
                for (Tree t : iterable) {
                    if (stoppingPoint.equals(t)) {
                        break;
                    }
                    builder.add(t);
                }
                iterable = builder.build();
            }
            return super.scan(iterable, unused);
        }

        @Override
        public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
            Symbol symbol = ASTHelpers.getSymbol(identifierTree);
            if (symbol != null) {
                builder.add(symbol);
            }
            return null;
        }
    };
}
Also used : TreeScanner(com.sun.source.util.TreeScanner) ImmutableList(com.google.common.collect.ImmutableList) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) ForLoopTree(com.sun.source.tree.ForLoopTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) TryTree(com.sun.source.tree.TryTree) IdentifierTree(com.sun.source.tree.IdentifierTree)

Example 40 with Symbol

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

the class FindIdentifiers method findUnusedIdentifiers.

/**
   * Finds all variable declarations which are unused at this point in the AST (i.e. they might be
   * used further on).
   */
public static ImmutableSet<VarSymbol> findUnusedIdentifiers(VisitorState state) {
    ImmutableSet.Builder<VarSymbol> definedVariables = ImmutableSet.builder();
    ImmutableSet.Builder<Symbol> usedSymbols = ImmutableSet.builder();
    Tree prev = state.getPath().getLeaf();
    for (Tree curr : state.getPath().getParentPath()) {
        createFindIdentifiersScanner(usedSymbols, prev).scan(curr, null);
        switch(curr.getKind()) {
            case BLOCK:
                // If we see a block then walk over each statement to see if it defines a variable
                for (StatementTree statement : ((BlockTree) curr).getStatements()) {
                    if (statement.equals(prev)) {
                        // declared/used before us in the tree
                        break;
                    }
                    addIfVariable(statement, definedVariables);
                }
                break;
            case FOR_LOOP:
                ForLoopTree forLoop = (ForLoopTree) curr;
                forLoop.getInitializer().stream().forEach(t -> addIfVariable(t, definedVariables));
                break;
            case ENHANCED_FOR_LOOP:
                EnhancedForLoopTree enhancedFor = (EnhancedForLoopTree) curr;
                addIfVariable(enhancedFor.getVariable(), definedVariables);
                break;
            default:
                break;
        }
        prev = curr;
    }
    return ImmutableSet.copyOf(Sets.difference(definedVariables.build(), usedSymbols.build()));
}
Also used : StatementTree(com.sun.source.tree.StatementTree) ImmutableSet(com.google.common.collect.ImmutableSet) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) ClassSymbol(com.sun.tools.javac.code.Symbol.ClassSymbol) TypeSymbol(com.sun.tools.javac.code.Symbol.TypeSymbol) Symbol(com.sun.tools.javac.code.Symbol) PackageSymbol(com.sun.tools.javac.code.Symbol.PackageSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) ForLoopTree(com.sun.source.tree.ForLoopTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) IdentifierTree(com.sun.source.tree.IdentifierTree) CatchTree(com.sun.source.tree.CatchTree) ForLoopTree(com.sun.source.tree.ForLoopTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) CompilationUnitTree(com.sun.source.tree.CompilationUnitTree) BlockTree(com.sun.source.tree.BlockTree) StatementTree(com.sun.source.tree.StatementTree) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree) MethodTree(com.sun.source.tree.MethodTree) VariableTree(com.sun.source.tree.VariableTree) NewClassTree(com.sun.source.tree.NewClassTree) ImportTree(com.sun.source.tree.ImportTree) Tree(com.sun.source.tree.Tree) ClassTree(com.sun.source.tree.ClassTree) TryTree(com.sun.source.tree.TryTree) BlockTree(com.sun.source.tree.BlockTree) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) EnhancedForLoopTree(com.sun.source.tree.EnhancedForLoopTree)

Aggregations

Symbol (com.sun.tools.javac.code.Symbol)195 MethodSymbol (com.sun.tools.javac.code.Symbol.MethodSymbol)56 Type (com.sun.tools.javac.code.Type)54 ClassSymbol (com.sun.tools.javac.code.Symbol.ClassSymbol)53 VarSymbol (com.sun.tools.javac.code.Symbol.VarSymbol)45 TypeSymbol (com.sun.tools.javac.code.Symbol.TypeSymbol)36 PackageSymbol (com.sun.tools.javac.code.Symbol.PackageSymbol)29 JCTree (com.sun.tools.javac.tree.JCTree)28 ClassType (com.sun.tools.javac.code.Type.ClassType)18 Tree (com.sun.source.tree.Tree)17 ExpressionTree (com.sun.source.tree.ExpressionTree)15 DynamicMethodSymbol (com.sun.tools.javac.code.Symbol.DynamicMethodSymbol)15 OperatorSymbol (com.sun.tools.javac.code.Symbol.OperatorSymbol)15 ClassTree (com.sun.source.tree.ClassTree)14 MethodTree (com.sun.source.tree.MethodTree)14 Name (com.sun.tools.javac.util.Name)14 IdentifierTree (com.sun.source.tree.IdentifierTree)13 ArrayType (com.sun.tools.javac.code.Type.ArrayType)12 MethodType (com.sun.tools.javac.code.Type.MethodType)12 UnionClassType (com.sun.tools.javac.code.Type.UnionClassType)12