use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.
the class BadShiftAmount method matchBinary.
@Override
public Description matchBinary(BinaryTree tree, VisitorState state) {
if (!BINARY_TREE_MATCHER.matches(tree, state)) {
return Description.NO_MATCH;
}
/*
* For shift amounts in [32, 63], cast the left operand to long. Otherwise change the shift
* amount to whatever would actually be used.
*/
int intValue = ((Number) ((LiteralTree) tree.getRightOperand()).getValue()).intValue();
Fix fix;
if (intValue >= 32 && intValue <= 63) {
if (tree.getLeftOperand().getKind() == Kind.INT_LITERAL) {
fix = SuggestedFix.postfixWith(tree.getLeftOperand(), "L");
} else {
fix = SuggestedFix.prefixWith(tree, "(long) ");
}
} else {
JCLiteral jcLiteral = (JCLiteral) tree.getRightOperand();
// This is the equivalent shift distance according to JLS 15.19.
String actualShiftDistance = Integer.toString(intValue & 0x1f);
int actualStart = ASTHelpers.getActualStartPosition(jcLiteral, state.getSourceCode());
if (actualStart != jcLiteral.getStartPosition()) {
fix = SuggestedFix.replace(tree.getRightOperand(), actualShiftDistance, actualStart - jcLiteral.getStartPosition(), 0);
} else {
fix = SuggestedFix.replace(tree.getRightOperand(), actualShiftDistance);
}
}
return describeMatch(tree, fix);
}
use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.
the class LongLiteralLowerCaseSuffix method getLongLiteral.
/**
* Extracts the long literal corresponding to a given {@link LiteralTree} node from the source
* code as a string. Returns null if the source code is not available.
*/
private static String getLongLiteral(LiteralTree literalTree, VisitorState state) {
JCLiteral longLiteral = (JCLiteral) literalTree;
CharSequence sourceFile = state.getSourceCode();
if (sourceFile == null) {
return null;
}
int start = longLiteral.getStartPosition();
java.util.regex.Matcher matcher = LONG_LITERAL_PATTERN.matcher(sourceFile.subSequence(start, sourceFile.length()));
if (matcher.lookingAt()) {
return matcher.group();
}
return null;
}
use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.
the class ComparisonOutOfRange method describe.
/**
* Suggested fixes are as follows. For the byte case, convert the literal to its byte
* representation. For example, "255" becomes "-1. For the character case, replace the
* comparison with "true"/"false" since it's not clear what was intended and that is
* semantically equivalent.
*
* TODO(eaftan): Suggested fixes don't handle side-effecting expressions, such as
* (d = reader.read()) == -1. Maybe add special case handling for assignments.
*/
public Description describe(BinaryTree tree, VisitorState state) {
List<ExpressionTree> binaryTreeMatches = ASTHelpers.matchBinaryTree(tree, Arrays.asList(Matchers.<ExpressionTree>isInstance(JCLiteral.class), Matchers.<ExpressionTree>anything()), state);
if (binaryTreeMatches == null) {
throw new IllegalStateException("Expected one of the operands to be a literal");
}
JCLiteral literal = (JCLiteral) binaryTreeMatches.get(0);
JCTree nonLiteralOperand = (JCTree) binaryTreeMatches.get(1);
boolean byteMatch = state.getTypes().isSameType(nonLiteralOperand.type, state.getSymtab().byteType);
boolean willEvaluateTo = (tree.getKind() != Kind.EQUAL_TO);
Fix fix;
String customDiagnosticMessage;
if (byteMatch) {
String replacement = Byte.toString(((Number) literal.getValue()).byteValue());
// Correct for poor javac 6 literal parsing.
int actualStart = ASTHelpers.getActualStartPosition(literal, state.getSourceCode());
if (actualStart != literal.getStartPosition()) {
fix = SuggestedFix.replace(literal, replacement, actualStart - literal.getStartPosition(), 0);
} else {
fix = SuggestedFix.replace(literal, replacement);
}
customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "byte", (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
} else {
fix = SuggestedFix.replace(tree, Boolean.toString(willEvaluateTo));
customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "char", (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
}
return buildDescription(tree).addFix(fix).setMessage(customDiagnosticMessage).build();
}
use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.
the class ASTHelpers method constValue.
/** Returns the compile-time constant value of a tree if it has one, or {@code null}. */
@Nullable
public static Object constValue(Tree tree) {
if (tree == null) {
return null;
}
tree = TreeInfo.skipParens((JCTree) tree);
Type type = ASTHelpers.getType(tree);
Object value;
if (tree instanceof JCLiteral) {
value = ((JCLiteral) tree).value;
} else if (type != null) {
value = type.constValue();
} else {
return null;
}
if (type.hasTag(TypeTag.BOOLEAN) && value instanceof Integer) {
return ((Integer) value) == 1;
}
return value;
}
use of com.sun.tools.javac.tree.JCTree.JCLiteral in project lombok by rzwitserloot.
the class HandleVal method visitLocal.
@Override
public void visitLocal(JavacNode localNode, JCVariableDecl local) {
JCTree typeTree = local.vartype;
if (typeTree == null)
return;
String typeTreeToString = typeTree.toString();
if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var")))
return;
boolean isVal = typeMatches(val.class, localNode, typeTree);
boolean isVar = typeMatches(var.class, localNode, typeTree);
if (!(isVal || isVar))
return;
if (isVal)
handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
if (isVar)
handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var");
JCTree parentRaw = localNode.directUp().get();
if (isVal && parentRaw instanceof JCForLoop) {
localNode.addError("'val' is not allowed in old-style for loops");
return;
}
JCExpression rhsOfEnhancedForLoop = null;
if (local.init == null) {
if (parentRaw instanceof JCEnhancedForLoop) {
JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw;
if (efl.var == local)
rhsOfEnhancedForLoop = efl.expr;
}
}
final String annotation = typeTreeToString;
if (rhsOfEnhancedForLoop == null && local.init == null) {
localNode.addError("'" + annotation + "' on a local variable requires an initializer expression");
return;
}
if (local.init instanceof JCNewArray && ((JCNewArray) local.init).elemtype == null) {
localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
return;
}
if (localNode.shouldDeleteLombokAnnotations()) {
JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName());
JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName());
}
if (isVal)
local.mods.flags |= Flags.FINAL;
if (!localNode.shouldDeleteLombokAnnotations()) {
JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext());
local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
}
if (JavacResolution.platformHasTargetTyping()) {
local.vartype = localNode.getAst().getTreeMaker().Ident(localNode.getAst().toName("___Lombok_VAL_Attrib__"));
} else {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
Type type;
try {
if (rhsOfEnhancedForLoop == null) {
if (local.init.type == null) {
if (isVar && local.init instanceof JCLiteral && ((JCLiteral) local.init).value == null) {
localNode.addError("variable initializer is 'null'");
}
JavacResolution resolver = new JavacResolution(localNode.getContext());
try {
type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
} catch (RuntimeException e) {
System.err.println("Exception while resolving: " + localNode);
throw e;
}
} else {
type = local.init.type;
if (type.isErroneous()) {
try {
JavacResolution resolver = new JavacResolution(localNode.getContext());
local.type = Symtab.instance(localNode.getContext()).unknownType;
type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
} catch (RuntimeException e) {
System.err.println("Exception while resolving: " + localNode);
throw e;
}
}
}
} else {
if (rhsOfEnhancedForLoop.type == null) {
JavacResolution resolver = new JavacResolution(localNode.getContext());
type = ((JCExpression) resolver.resolveMethodMember(localNode.directUp()).get(rhsOfEnhancedForLoop)).type;
} else {
type = rhsOfEnhancedForLoop.type;
}
}
try {
JCExpression replacement;
if (rhsOfEnhancedForLoop != null) {
Type componentType = JavacResolution.ifTypeIsIterableToComponent(type, localNode.getAst());
if (componentType == null)
replacement = JavacResolution.createJavaLangObject(localNode.getAst());
else
replacement = JavacResolution.typeToJCTree(componentType, localNode.getAst(), false);
} else {
replacement = JavacResolution.typeToJCTree(type, localNode.getAst(), false);
}
if (replacement != null) {
local.vartype = replacement;
} else {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
localNode.getAst().setChanged();
} catch (JavacResolution.TypeNotConvertibleException e) {
localNode.addError("Cannot use '" + annotation + "' here because initializer expression does not have a representable type: " + e.getMessage());
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
} catch (RuntimeException e) {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
throw e;
} finally {
recursiveSetGeneratedBy(local.vartype, typeTree, localNode.getContext());
}
}
Aggregations