Search in sources :

Example 16 with LiteralTree

use of com.sun.source.tree.LiteralTree in project checker-framework by typetools.

the class SignednessVisitor method isMaskedShift.

/**
 * Determines if a right shift operation, {@code >>} or {@code >>>}, is masked with a masking
 * operation of the form {@code shiftExpr & maskLit} or {@code shiftExpr | maskLit} such that
 * the mask renders the shift signedness ({@code >>} vs {@code >>>}) irrelevent by destroying
 * the bits duplicated into the shift result. For example, the following pairs of right shifts
 * on {@code byte b} both produce the same results under any input, because of their masks:
 *
 * <p>{@code (b >> 4) & 0x0F == (b >>> 4) & 0x0F;}
 *
 * <p>{@code (b >> 4) | 0xF0 == (b >>> 4) | 0xF0;}
 *
 * @param shiftExpr a right shift expression: {@code expr1 >> expr2} or {@code expr1 >>> expr2}
 * @return true iff the right shift is masked such that a signed or unsigned right shift has the
 *     same effect
 */
private boolean isMaskedShift(BinaryTree shiftExpr) {
    // enclosing is the operation or statement that immediately contains shiftExpr
    Tree enclosing;
    // enclosingChild is the top node in the chain of nodes from shiftExpr to parent
    Tree enclosingChild;
    {
        TreePath parentPath = visitorState.getPath().getParentPath();
        enclosing = parentPath.getLeaf();
        enclosingChild = enclosing;
        // Strip away all parentheses from the shift operation
        while (enclosing.getKind() == Kind.PARENTHESIZED) {
            parentPath = parentPath.getParentPath();
            enclosingChild = enclosing;
            enclosing = parentPath.getLeaf();
        }
    }
    if (!isMask(enclosing)) {
        return false;
    }
    BinaryTree maskExpr = (BinaryTree) enclosing;
    ExpressionTree shiftAmountExpr = shiftExpr.getRightOperand();
    // Determine which child of maskExpr leads to shiftExpr. The other one is the mask.
    ExpressionTree mask = maskExpr.getRightOperand() == enclosingChild ? maskExpr.getLeftOperand() : maskExpr.getRightOperand();
    // Strip away the parentheses from the mask if any exist
    mask = TreeUtils.skipParens(mask);
    if (!isLiteral(shiftAmountExpr) || !isLiteral(mask)) {
        return false;
    }
    LiteralTree shiftLit = (LiteralTree) shiftAmountExpr;
    LiteralTree maskLit = (LiteralTree) mask;
    return maskIgnoresMSB(maskExpr.getKind(), shiftLit, maskLit);
}
Also used : TreePath(com.sun.source.util.TreePath) BinaryTree(com.sun.source.tree.BinaryTree) CompoundAssignmentTree(com.sun.source.tree.CompoundAssignmentTree) LiteralTree(com.sun.source.tree.LiteralTree) ExpressionTree(com.sun.source.tree.ExpressionTree) BinaryTree(com.sun.source.tree.BinaryTree) AnnotatedTypeTree(com.sun.source.tree.AnnotatedTypeTree) TypeCastTree(com.sun.source.tree.TypeCastTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) LiteralTree(com.sun.source.tree.LiteralTree)

Example 17 with LiteralTree

use of com.sun.source.tree.LiteralTree in project error-prone by google.

the class StringLiteralTest method matches.

@Test
public void matches() {
    // TODO(b/67738557): consolidate helpers for creating fake trees
    LiteralTree tree = new LiteralTree() {

        @Override
        public Kind getKind() {
            throw new UnsupportedOperationException();
        }

        @Override
        public <R, D> R accept(TreeVisitor<R, D> visitor, D data) {
            throw new UnsupportedOperationException();
        }

        @Override
        public Object getValue() {
            return "a string literal";
        }
    };
    assertTrue(new StringLiteral("a string literal").matches(tree, null));
}
Also used : TreeVisitor(com.sun.source.tree.TreeVisitor) LiteralTree(com.sun.source.tree.LiteralTree) Test(org.junit.Test)

Example 18 with LiteralTree

use of com.sun.source.tree.LiteralTree in project error-prone by google.

the class ConstantOverflow method longFix.

/**
 * If the left operand of an int binary expression is an int literal, suggest making it a long.
 */
private Fix longFix(ExpressionTree expr, VisitorState state) {
    BinaryTree binExpr = null;
    while (expr instanceof BinaryTree) {
        binExpr = (BinaryTree) expr;
        expr = binExpr.getLeftOperand();
    }
    if (!(expr instanceof LiteralTree) || expr.getKind() != Kind.INT_LITERAL) {
        return null;
    }
    Type intType = state.getSymtab().intType;
    if (!isSameType(getType(binExpr), intType, state)) {
        return null;
    }
    SuggestedFix.Builder fix = SuggestedFix.builder().postfixWith(expr, "L");
    Tree parent = state.getPath().getParentPath().getLeaf();
    if (parent instanceof VariableTree && isSameType(getType(parent), intType, state)) {
        fix.replace(((VariableTree) parent).getType(), "long");
    }
    return fix.build();
}
Also used : ASTHelpers.getType(com.google.errorprone.util.ASTHelpers.getType) ASTHelpers.isSameType(com.google.errorprone.util.ASTHelpers.isSameType) Type(com.sun.tools.javac.code.Type) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) BinaryTree(com.sun.source.tree.BinaryTree) VariableTree(com.sun.source.tree.VariableTree) LiteralTree(com.sun.source.tree.LiteralTree) BinaryTree(com.sun.source.tree.BinaryTree) UnaryTree(com.sun.source.tree.UnaryTree) VariableTree(com.sun.source.tree.VariableTree) TypeCastTree(com.sun.source.tree.TypeCastTree) IdentifierTree(com.sun.source.tree.IdentifierTree) Tree(com.sun.source.tree.Tree) ParenthesizedTree(com.sun.source.tree.ParenthesizedTree) ConditionalExpressionTree(com.sun.source.tree.ConditionalExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) MemberSelectTree(com.sun.source.tree.MemberSelectTree) PrimitiveTypeTree(com.sun.source.tree.PrimitiveTypeTree) LiteralTree(com.sun.source.tree.LiteralTree)

Example 19 with LiteralTree

use of com.sun.source.tree.LiteralTree in project error-prone by google.

the class CanonicalDuration method matchMethodInvocation.

@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
    Api api;
    if (JAVA_TIME_MATCHER.matches(tree, state)) {
        api = Api.JAVA;
    } else if (JODA_MATCHER.matches(tree, state)) {
        api = Api.JODA;
    } else {
        return NO_MATCH;
    }
    if (tree.getArguments().size() != 1) {
        // TODO(cushon): ofSeconds w/ nano adjustment?
        return NO_MATCH;
    }
    Tree arg = getOnlyElement(tree.getArguments());
    if (!(arg instanceof LiteralTree)) {
        // don't inline constants
        return NO_MATCH;
    }
    Number value = constValue(arg, Number.class);
    if (value == null) {
        return NO_MATCH;
    }
    if (value.intValue() == 0) {
        switch(api) {
            case JODA:
                ExpressionTree receiver = getReceiver(tree);
                SuggestedFix fix;
                if (receiver == null) {
                    // static import of the method
                    fix = SuggestedFix.builder().addImport(api.getDurationFullyQualifiedName()).replace(tree, "Duration.ZERO").build();
                } else {
                    fix = SuggestedFix.replace(state.getEndPosition(getReceiver(tree)), state.getEndPosition(tree), ".ZERO");
                }
                return buildDescription(tree).setMessage("Duration can be expressed more clearly without units, as Duration.ZERO").addFix(fix).build();
            case JAVA:
                // don't rewrite e.g. `ofMillis(0)` to `ofDays(0)`
                return NO_MATCH;
        }
        throw new AssertionError(api);
    }
    MethodSymbol sym = getSymbol(tree);
    if (!METHOD_NAME_TO_UNIT.containsKey(sym.getSimpleName().toString())) {
        return NO_MATCH;
    }
    TemporalUnit unit = METHOD_NAME_TO_UNIT.get(sym.getSimpleName().toString());
    if (Objects.equals(BLACKLIST.get(unit), value.longValue())) {
        return NO_MATCH;
    }
    Duration duration = Duration.of(value.longValue(), unit);
    // largest unit that can be used to exactly express the duration.
    for (Map.Entry<ChronoUnit, Converter<Duration, Long>> entry : CONVERTERS.entrySet()) {
        ChronoUnit nextUnit = entry.getKey();
        if (unit.equals(nextUnit)) {
            // We reached the original unit, no simplification is possible.
            break;
        }
        Converter<Duration, Long> converter = entry.getValue();
        long nextValue = converter.convert(duration);
        if (converter.reverse().convert(nextValue).equals(duration)) {
            // We reached a larger than original unit that precisely expresses the duration, rewrite to
            // use it instead.
            String name = FACTORIES.get(api, nextUnit);
            String replacement = String.format("%s(%d%s)", name, nextValue, nextValue == ((int) nextValue) ? "" : "L");
            ExpressionTree receiver = getReceiver(tree);
            if (receiver == null) {
                // static import of the method
                SuggestedFix fix = SuggestedFix.builder().addStaticImport(api.getDurationFullyQualifiedName() + "." + name).replace(tree, replacement).build();
                return describeMatch(tree, fix);
            } else {
                return describeMatch(tree, SuggestedFix.replace(state.getEndPosition(receiver), state.getEndPosition(tree), "." + replacement));
            }
        }
    }
    return NO_MATCH;
}
Also used : TemporalUnit(java.time.temporal.TemporalUnit) Duration(java.time.Duration) LiteralTree(com.sun.source.tree.LiteralTree) SuggestedFix(com.google.errorprone.fixes.SuggestedFix) MethodSymbol(com.sun.tools.javac.code.Symbol.MethodSymbol) LiteralTree(com.sun.source.tree.LiteralTree) MethodInvocationTree(com.sun.source.tree.MethodInvocationTree) Tree(com.sun.source.tree.Tree) ExpressionTree(com.sun.source.tree.ExpressionTree) ExpressionTree(com.sun.source.tree.ExpressionTree) Converter(com.google.common.base.Converter) Map(java.util.Map) ImmutableMap(com.google.common.collect.ImmutableMap) ImmutableMap.toImmutableMap(com.google.common.collect.ImmutableMap.toImmutableMap) ChronoUnit(java.time.temporal.ChronoUnit)

Example 20 with LiteralTree

use of com.sun.source.tree.LiteralTree in project error-prone by google.

the class InstanceOfAndCastMatchWrongType method expressionsEqual.

/**
 * Determines whether two {@link ExpressionTree} instances are equal. Only handles the cases
 * relevant to this checker: array accesses, identifiers, and literals. Returns false for all
 * other cases.
 */
private static boolean expressionsEqual(ExpressionTree expr1, ExpressionTree expr2) {
    if (!expr1.getKind().equals(expr2.getKind())) {
        return false;
    }
    if (!expr1.getKind().equals(Kind.ARRAY_ACCESS) && !expr1.getKind().equals(Kind.IDENTIFIER) && !(expr1 instanceof LiteralTree)) {
        return false;
    }
    if (expr1.getKind() == Kind.ARRAY_ACCESS) {
        ArrayAccessTree arrayAccessTree1 = (ArrayAccessTree) expr1;
        ArrayAccessTree arrayAccessTree2 = (ArrayAccessTree) expr2;
        return expressionsEqual(arrayAccessTree1.getExpression(), arrayAccessTree2.getExpression()) && expressionsEqual(arrayAccessTree1.getIndex(), arrayAccessTree2.getIndex());
    }
    if (expr1 instanceof LiteralTree) {
        LiteralTree literalTree1 = (LiteralTree) expr1;
        LiteralTree literalTree2 = (LiteralTree) expr2;
        return literalTree1.getValue().equals(literalTree2.getValue());
    }
    return Objects.equal(ASTHelpers.getSymbol(expr1), ASTHelpers.getSymbol(expr2));
}
Also used : ArrayAccessTree(com.sun.source.tree.ArrayAccessTree) LiteralTree(com.sun.source.tree.LiteralTree)

Aggregations

LiteralTree (com.sun.source.tree.LiteralTree)20 ExpressionTree (com.sun.source.tree.ExpressionTree)13 Tree (com.sun.source.tree.Tree)8 BinaryTree (com.sun.source.tree.BinaryTree)7 MemberSelectTree (com.sun.source.tree.MemberSelectTree)7 IdentifierTree (com.sun.source.tree.IdentifierTree)6 MethodInvocationTree (com.sun.source.tree.MethodInvocationTree)6 ConditionalExpressionTree (com.sun.source.tree.ConditionalExpressionTree)5 PrimitiveTypeTree (com.sun.source.tree.PrimitiveTypeTree)4 TypeCastTree (com.sun.source.tree.TypeCastTree)4 ArrayAccessTree (com.sun.source.tree.ArrayAccessTree)3 BlockTree (com.sun.source.tree.BlockTree)3 ClassTree (com.sun.source.tree.ClassTree)3 CompoundAssignmentTree (com.sun.source.tree.CompoundAssignmentTree)3 Element (javax.lang.model.element.Element)3 ExecutableElement (javax.lang.model.element.ExecutableElement)3 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)2 AnnotatedTypeTree (com.sun.source.tree.AnnotatedTypeTree)2 IfTree (com.sun.source.tree.IfTree)2 MethodTree (com.sun.source.tree.MethodTree)2