use of com.sun.source.tree.ExpressionTree 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;
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractArgumentParameterChecker method findReplacements.
private Description findReplacements(List<? extends ExpressionTree> args, com.sun.tools.javac.util.List<VarSymbol> params, boolean isVarArgs, VisitorState state, Tree tree) {
if (args.isEmpty()) {
return Description.NO_MATCH;
}
ImmutableSet<PotentialReplacement> potentialReplacements = potentialReplacementsFunction.apply(state.withPath(new TreePath(state.getPath(), args.get(0))));
SuggestedFix.Builder fix = SuggestedFix.builder();
// Don't suggest for the varargs parameter.
// TODO(eaftan): Reconsider this, especially if the argument is of array type or is itself
// a varargs parameter.
int maxArg = isVarArgs ? params.size() - 1 : params.size();
for (int i = 0; i < maxArg; i++) {
ExpressionTree arg = args.get(i);
VarSymbol param = params.get(i);
if (!validKinds.contains(arg.getKind()) || !parameterPredicate.test(param)) {
continue;
}
String extractedArgumentName = extractArgumentName(arg);
if (extractedArgumentName == null) {
continue;
}
double currSimilarity = similarityMetric.applyAsDouble(extractedArgumentName, param.getSimpleName().toString());
if (1.0 - currSimilarity < beta) {
// No way for any replacement to be at least BETA better than the current argument
continue;
}
ReplacementWithSimilarity bestReplacement = potentialReplacements.stream().filter(replacement -> !replacement.sym().equals(ASTHelpers.getSymbol(arg))).filter(replacement -> isSubtypeHandleCompletionFailures(replacement.sym(), param, state)).map(replacement -> ReplacementWithSimilarity.create(replacement, similarityMetric.applyAsDouble(replacement.argumentName(), param.getSimpleName().toString()))).max(Comparator.comparingDouble(ReplacementWithSimilarity::similarity)).orElse(null);
if ((bestReplacement != null) && (bestReplacement.similarity() - currSimilarity >= beta)) {
fix.replace(arg, bestReplacement.replacement().replacementString());
}
}
if (fix.isEmpty()) {
return Description.NO_MATCH;
} else {
return describeMatch(tree, fix.build());
}
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class AbstractSuppressWarningsMatcher method getSuggestedFix.
protected final Fix getSuggestedFix(AnnotationTree annotationTree) {
List<String> values = new ArrayList<>();
for (ExpressionTree argumentTree : annotationTree.getArguments()) {
AssignmentTree assignmentTree = (AssignmentTree) argumentTree;
if (assignmentTree.getVariable().toString().equals("value")) {
ExpressionTree expressionTree = assignmentTree.getExpression();
switch(expressionTree.getKind()) {
case STRING_LITERAL:
values.add(((String) ((JCTree.JCLiteral) expressionTree).value));
break;
case NEW_ARRAY:
NewArrayTree newArrayTree = (NewArrayTree) expressionTree;
for (ExpressionTree elementTree : newArrayTree.getInitializers()) {
values.add((String) ((JCTree.JCLiteral) elementTree).value);
}
break;
default:
throw new AssertionError("Unknown kind: " + expressionTree.getKind());
}
processSuppressWarningsValues(values);
} else {
throw new AssertionError("SuppressWarnings has an element other than value=");
}
}
if (values.isEmpty()) {
return SuggestedFix.delete(annotationTree);
} else if (values.size() == 1) {
return SuggestedFix.replace(annotationTree, "@SuppressWarnings(\"" + values.get(0) + "\")");
} else {
StringBuilder sb = new StringBuilder("@SuppressWarnings({\"" + values.get(0) + "\"");
for (int i = 1; i < values.size(); i++) {
sb.append(", ");
sb.append("\"" + values.get(i) + "\"");
}
sb.append("})");
return SuggestedFix.replace(annotationTree, sb.toString());
}
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class ArrayHashCode method matchMethodInvocation.
/**
* Wraps identity hashcode computations in calls to {@link java.util.Arrays#hashCode} if the
* array is single dimensional or {@link java.util.Arrays#deepHashCode} if the array is
* multidimensional.
*
* <p>If there is only one argument to the hashcode method or the instance hashcode method is
* used, replaces the whole method invocation. If there are multiple arguments, wraps any that
* are of array type with the appropriate {@link java.util.Arrays} hashcode method.
*/
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
SuggestedFix.Builder fix = null;
Types types = state.getTypes();
if (jdk7HashCodeMethodMatcher.matches(tree, state)) {
// java.util.Objects#hashCode takes a single argument, so rewrite the whole method call
// to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(tree.getArguments().get(0), types));
} else if (instanceHashCodeMethodMatcher.matches(tree, state)) {
// Rewrite call to instance hashCode method to use Arrays.hashCode/deepHashCode instead.
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(((JCFieldAccess) tree.getMethodSelect()).getExpression(), types));
} else if (varargsHashCodeMethodMatcher.matches(tree, state)) {
// com.google.common.base.Objects#hashCode
if (tree.getArguments().size() == 1) {
// If only one argument, type must be either primitive array or multidimensional array.
// Types like Object[], String[], etc. are not an error because they don't get boxed
// in this single-argument varargs call.
ExpressionTree arg = tree.getArguments().get(0);
Type elemType = types.elemtype(ASTHelpers.getType(arg));
if (elemType.isPrimitive() || types.isArray(elemType)) {
fix = SuggestedFix.builder().replace(tree, rewriteArrayArgument(arg, types));
}
} else {
// If more than one argument, wrap each argument in a call to Arrays#hashCode/deepHashCode.
fix = SuggestedFix.builder();
for (ExpressionTree arg : tree.getArguments()) {
if (types.isArray(ASTHelpers.getType(arg))) {
fix.replace(arg, rewriteArrayArgument(arg, types));
}
}
}
}
if (fix != null) {
fix.addImport("java.util.Arrays");
return describeMatch(tree, fix.build());
}
return Description.NO_MATCH;
}
use of com.sun.source.tree.ExpressionTree in project error-prone by google.
the class BadComparable method matches.
/**
* Matches if this is a narrowing integral cast between signed types where the expression is a
* subtract.
*/
private boolean matches(TypeCastTree tree, VisitorState state) {
Type treeType = ASTHelpers.getType(tree.getType());
// If the cast isn't narrowing to an int then don't implicate it in the bug pattern.
if (treeType.getTag() != TypeTag.INT) {
return false;
}
// The expression should be a subtract but remove parentheses.
ExpressionTree expression = TreeInfo.skipParens((JCExpression) tree.getExpression());
if (expression.getKind() != Kind.MINUS) {
return false;
}
// Ensure the expression type is wider and signed (ie a long) than the cast type ignoring
// boxing.
Type expressionType = getTypeOfSubtract((BinaryTree) expression);
TypeTag expressionTypeTag = state.getTypes().unboxedTypeOrType(expressionType).getTag();
return (expressionTypeTag == TypeTag.LONG);
}
Aggregations