use of com.sun.tools.javac.code.Type 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.tools.javac.code.Type 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.tools.javac.code.Type in project error-prone by google.
the class ArrayHashCode method rewriteArrayArgument.
/**
* Given an {@link ExpressionTree} that represents an argument of array type, rewrites it to wrap
* it in a call to either {@link java.util.Arrays#hashCode} if it is single dimensional, or
* {@link java.util.Arrays#deepHashCode} if it is multidimensional.
*/
private static String rewriteArrayArgument(ExpressionTree arg, Types types) {
Type argType = ASTHelpers.getType(arg);
Preconditions.checkState(types.isArray(argType), "arg must be of array type");
if (types.isArray(types.elemtype(argType))) {
return "Arrays.deepHashCode(" + arg + ")";
} else {
return "Arrays.hashCode(" + arg + ")";
}
}
use of com.sun.tools.javac.code.Type in project error-prone by google.
the class BadAnnotationImplementation method matchClass.
@Override
public Description matchClass(ClassTree classTree, final VisitorState state) {
if (!CLASS_TREE_MATCHER.matches(classTree, state)) {
return Description.NO_MATCH;
}
// If this is an enum that is trying to implement Annotation, give a special error message.
if (classTree.getKind() == Kind.ENUM) {
return buildDescription(classTree).setMessage("Enums cannot correctly implement Annotation because their equals and hashCode " + "methods are final. Consider using AutoAnnotation instead of implementing " + "Annotation by hand.").build();
}
// Otherwise walk up type hierarchy looking for equals and hashcode methods
MethodSymbol equals = null;
MethodSymbol hashCode = null;
final Types types = state.getTypes();
Name equalsName = state.getName("equals");
Predicate<MethodSymbol> equalsPredicate = new Predicate<MethodSymbol>() {
@Override
public boolean apply(MethodSymbol methodSymbol) {
return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().size() == 1 && types.isSameType(methodSymbol.getParameters().get(0).type, state.getSymtab().objectType);
}
};
Name hashCodeName = state.getName("hashCode");
Predicate<MethodSymbol> hashCodePredicate = new Predicate<MethodSymbol>() {
@Override
public boolean apply(MethodSymbol methodSymbol) {
return !methodSymbol.isStatic() && ((methodSymbol.flags() & Flags.SYNTHETIC) == 0) && ((methodSymbol.flags() & Flags.ABSTRACT) == 0) && methodSymbol.getParameters().isEmpty();
}
};
for (Type sup : types.closure(ASTHelpers.getSymbol(classTree).type)) {
if (equals == null) {
equals = getMatchingMethod(sup, equalsName, equalsPredicate);
}
if (hashCode == null) {
hashCode = getMatchingMethod(sup, hashCodeName, hashCodePredicate);
}
}
Verify.verifyNotNull(equals);
Verify.verifyNotNull(hashCode);
Symbol objectSymbol = state.getSymtab().objectType.tsym;
if (equals.owner.equals(objectSymbol) || hashCode.owner.equals(objectSymbol)) {
return describeMatch(classTree);
}
return Description.NO_MATCH;
}
use of com.sun.tools.javac.code.Type 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