Search in sources :

Example 51 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class DataFlow method findEnclosingMethodOrLambdaOrInitializer.

// TODO(user), remove once we merge jdk8 specific's with core
private static <T> TreePath findEnclosingMethodOrLambdaOrInitializer(TreePath path) {
    while (path != null) {
        if (path.getLeaf() instanceof MethodTree) {
            return path;
        }
        TreePath parent = path.getParentPath();
        if (parent != null) {
            if (parent.getLeaf() instanceof ClassTree) {
                if (path.getLeaf() instanceof BlockTree) {
                    // this is a class or instance initializer block
                    return path;
                }
                if (path.getLeaf() instanceof VariableTree && ((VariableTree) path.getLeaf()).getInitializer() != null) {
                    // this is a field with an inline initializer
                    return path;
                }
            }
            if (parent.getLeaf() instanceof LambdaExpressionTree) {
                return parent;
            }
        }
        path = parent;
    }
    return null;
}
Also used : LambdaExpressionTree(com.sun.source.tree.LambdaExpressionTree) TreePath(com.sun.source.util.TreePath) MethodTree(com.sun.source.tree.MethodTree) ClassTree(com.sun.source.tree.ClassTree) VariableTree(com.sun.source.tree.VariableTree) BlockTree(com.sun.source.tree.BlockTree)

Example 52 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class StrictFormatStringValidation method validateFormatStringVariable.

/**
 * Helps {@code validate()} validate a format string that is a variable, but not a parameter. This
 * method assumes that the format string variable has already been asserted to be final or
 * effectively final.
 */
private static ValidationResult validateFormatStringVariable(ExpressionTree formatStringTree, final Symbol formatStringSymbol, final List<? extends ExpressionTree> args, final VisitorState state) {
    if (formatStringSymbol.getKind() != ElementKind.LOCAL_VARIABLE) {
        return ValidationResult.create(null, String.format("Variables used as format strings that are not local variables must be compile time" + " consant.\n%s is not a local variable and is not compile time constant.", formatStringTree));
    }
    // Find the Tree for the block in which the variable is defined. If it is not defined in this
    // class (though it may have been in a super class). We require compile time constant values in
    // that case.
    Symbol owner = formatStringSymbol.owner;
    TreePath path = TreePath.getPath(state.getPath(), formatStringTree);
    while (path != null && ASTHelpers.getSymbol(path.getLeaf()) != owner) {
        path = path.getParentPath();
    }
    // impossible.
    if (path == null) {
        throw new IllegalStateException(String.format("Could not find the Tree where local variable %s is declared. " + "This should be impossible.", formatStringTree));
    }
    // Scan down from the scope where the variable was declared
    ValidationResult result = path.getLeaf().accept(new TreeScanner<ValidationResult, Void>() {

        @Override
        public ValidationResult visitVariable(VariableTree node, Void unused) {
            if (ASTHelpers.getSymbol(node) == formatStringSymbol) {
                if (node.getInitializer() == null) {
                    return ValidationResult.create(null, String.format("Variables used as format strings must be initialized when they are" + " declared.\nInvalid declaration: %s", node));
                }
                return validateStringFromAssignment(node, node.getInitializer(), args, state);
            }
            return super.visitVariable(node, unused);
        }

        @Override
        public ValidationResult reduce(ValidationResult r1, ValidationResult r2) {
            if (r1 == null && r2 == null) {
                return null;
            }
            return MoreObjects.firstNonNull(r1, r2);
        }
    }, null);
    return result;
}
Also used : TreePath(com.sun.source.util.TreePath) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) VarSymbol(com.sun.tools.javac.code.Symbol.VarSymbol) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) ValidationResult(com.google.errorprone.bugpatterns.formatstring.FormatStringValidation.ValidationResult)

Example 53 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class FieldMissingNullable method matchAssignment.

@Override
public Description matchAssignment(AssignmentTree tree, VisitorState state) {
    Symbol assigned = ASTHelpers.getSymbol(tree.getVariable());
    if (assigned == null || assigned.getKind() != ElementKind.FIELD || assigned.type.isPrimitive()) {
        // not a field of nullable type
        return Description.NO_MATCH;
    }
    // Best-effort try to avoid running the dataflow analysis
    // TODO(kmb): bail on more non-null expressions, such as "this", arithmethic, logical, and &&/||
    ExpressionTree expression = tree.getExpression();
    if (ASTHelpers.constValue(expression) != null) {
        // This should include literals such as "true" or a string
        return Description.NO_MATCH;
    }
    if (TrustingNullnessAnalysis.hasNullableAnnotation(assigned)) {
        // field already annotated
        return Description.NO_MATCH;
    }
    VariableTree fieldDecl = findDeclaration(state, assigned);
    if (fieldDecl == null) {
        // skip fields declared elsewhere for simplicity
        return Description.NO_MATCH;
    }
    // Don't need dataflow to tell us that null is nullable
    if (expression.getKind() == Tree.Kind.NULL_LITERAL) {
        return makeFix(state, fieldDecl, tree, "Assigning null literal to field");
    }
    // OK let's see what dataflow says
    Nullness nullness = TrustingNullnessAnalysis.instance(state.context).getNullness(new TreePath(state.getPath(), expression), state.context);
    if (nullness == null) {
        // TODO(b/69154806): Make dataflow work for that case.
        return Description.NO_MATCH;
    }
    switch(nullness) {
        case BOTTOM:
        case NONNULL:
            return Description.NO_MATCH;
        case NULL:
            return makeFix(state, fieldDecl, tree, "Assigning null to field");
        case NULLABLE:
            return makeFix(state, fieldDecl, tree, "May assign null to field");
        default:
            throw new AssertionError("Impossible: " + nullness);
    }
}
Also used : TreePath(com.sun.source.util.TreePath) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) ExpressionTree(com.sun.source.tree.ExpressionTree) Nullness(com.google.errorprone.dataflow.nullnesspropagation.Nullness)

Example 54 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class ForOverrideChecker method getOutermostClass.

/**
 * Get the outermost class/interface/enum of an element, or null if none.
 */
private Type getOutermostClass(VisitorState state) {
    TreePath path = state.getPath();
    Type type = null;
    while (path != null) {
        if (path.getLeaf().getKind() == Kind.CLASS || path.getLeaf().getKind() == Kind.INTERFACE || path.getLeaf().getKind() == Kind.ENUM) {
            type = ASTHelpers.getSymbol(path.getLeaf()).type;
        }
        path = path.getParentPath();
    }
    return type;
}
Also used : Type(com.sun.tools.javac.code.Type) TreePath(com.sun.source.util.TreePath)

Example 55 with TreePath

use of com.sun.source.util.TreePath in project error-prone by google.

the class InconsistentCapitalization method matchClass.

@Override
public Description matchClass(ClassTree tree, VisitorState state) {
    ImmutableSet<Symbol> fields = FieldScanner.findFields(tree);
    if (fields.isEmpty()) {
        return Description.NO_MATCH;
    }
    ImmutableMap<String, Symbol> fieldNamesMap = fields.stream().collect(toImmutableMap(symbol -> symbol.toString().toLowerCase(), identity()));
    ImmutableMap<TreePath, Symbol> matchedParameters = MatchingParametersScanner.findMatchingParameters(fieldNamesMap, state.getPath());
    if (matchedParameters.isEmpty()) {
        return Description.NO_MATCH;
    }
    for (Entry<TreePath, Symbol> entry : matchedParameters.entrySet()) {
        TreePath parameterPath = entry.getKey();
        Symbol field = entry.getValue();
        String fieldName = field.getSimpleName().toString();
        VariableTree parameterTree = (VariableTree) parameterPath.getLeaf();
        SuggestedFix.Builder fix = SuggestedFix.builder().merge(SuggestedFixes.renameVariable(parameterTree, fieldName, state));
        if (parameterPath.getParentPath() != null) {
            String qualifiedName = getExplicitQualification(parameterPath, tree, state) + field.getSimpleName();
            // If the field was accessed in a non-qualified way, by renaming the parameter this may
            // cause clashes with it. Thus, it is required to qualify all uses of the field within the
            // parameter's scope just in case.
            parameterPath.getParentPath().getLeaf().accept(new TreeScanner<Void, Void>() {

                @Override
                public Void visitIdentifier(IdentifierTree tree, Void unused) {
                    if (field.equals(ASTHelpers.getSymbol(tree))) {
                        fix.replace(tree, qualifiedName);
                    }
                    return null;
                }
            }, null);
        }
        state.reportMatch(buildDescription(parameterPath.getLeaf()).setMessage(String.format("Found the field '%s' with the same name as the parameter '%s' but with " + "different capitalization.", fieldName, ((VariableTree) parameterPath.getLeaf()).getName())).addFix(fix.build()).build());
    }
    return Description.NO_MATCH;
}
Also used : SuggestedFixes(com.google.errorprone.fixes.SuggestedFixes) TreePath(com.sun.source.util.TreePath) ImmutableSet(com.google.common.collect.ImmutableSet) ElementKind(javax.lang.model.element.ElementKind) ImmutableMap(com.google.common.collect.ImmutableMap) ClassTreeMatcher(com.google.errorprone.bugpatterns.BugChecker.ClassTreeMatcher) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) TreeScanner(com.sun.source.util.TreeScanner) VisitorState(com.google.errorprone.VisitorState) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) Description(com.google.errorprone.matchers.Description) IdentifierTree(com.sun.source.tree.IdentifierTree) Function.identity(java.util.function.Function.identity) Entry(java.util.Map.Entry) BugPattern(com.google.errorprone.BugPattern) WARNING(com.google.errorprone.BugPattern.SeverityLevel.WARNING) ProvidesFix(com.google.errorprone.BugPattern.ProvidesFix) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) JDK(com.google.errorprone.BugPattern.Category.JDK) TreePathScanner(com.sun.source.util.TreePathScanner) Tree(com.sun.source.tree.Tree) ASTHelpers(com.google.errorprone.util.ASTHelpers) ClassTree(com.sun.source.tree.ClassTree) Symbol(com.sun.tools.javac.code.Symbol) VariableTree(com.sun.source.tree.VariableTree) IdentifierTree(com.sun.source.tree.IdentifierTree) TreePath(com.sun.source.util.TreePath) SuggestedFix(com.google.errorprone.fixes.SuggestedFix)

Aggregations

TreePath (com.sun.source.util.TreePath)151 ExpressionTree (com.sun.source.tree.ExpressionTree)60 Tree (com.sun.source.tree.Tree)60 VariableTree (com.sun.source.tree.VariableTree)50 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)46 MethodTree (com.sun.source.tree.MethodTree)46 ClassTree (com.sun.source.tree.ClassTree)45 MemberSelectTree (com.sun.source.tree.MemberSelectTree)39 IdentifierTree (com.sun.source.tree.IdentifierTree)37 BlockTree (com.sun.source.tree.BlockTree)36 NewClassTree (com.sun.source.tree.NewClassTree)32 StatementTree (com.sun.source.tree.StatementTree)32 JCTree (com.sun.tools.javac.tree.JCTree)31 AssignmentTree (com.sun.source.tree.AssignmentTree)27 BinaryTree (com.sun.source.tree.BinaryTree)27 TypeCastTree (com.sun.source.tree.TypeCastTree)26 ExpressionStatementTree (com.sun.source.tree.ExpressionStatementTree)25 LambdaExpressionTree (com.sun.source.tree.LambdaExpressionTree)25 LiteralTree (com.sun.source.tree.LiteralTree)25 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)23