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);
}
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));
}
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();
}
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;
}
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));
}
Aggregations