use of com.google.errorprone.VisitorState in project error-prone by google.
the class Matchers method receiverSameAsArgument.
/**
* Matches when the receiver of an instance method is the same reference as a particular argument to the method.
* For example, receiverSameAsArgument(1) would match {@code obj.method("", obj)}
*
* @param argNum The number of the argument to compare against (zero-based.
*/
public static Matcher<? super MethodInvocationTree> receiverSameAsArgument(final int argNum) {
return new Matcher<MethodInvocationTree>() {
@Override
public boolean matches(MethodInvocationTree t, VisitorState state) {
List<? extends ExpressionTree> args = t.getArguments();
if (args.size() <= argNum) {
return false;
}
ExpressionTree arg = args.get(argNum);
JCExpression methodSelect = (JCExpression) t.getMethodSelect();
if (methodSelect instanceof JCFieldAccess) {
JCFieldAccess fieldAccess = (JCFieldAccess) methodSelect;
return ASTHelpers.sameVariable(fieldAccess.getExpression(), arg);
} else if (methodSelect instanceof JCIdent) {
// A bare method call: "equals(foo)". Receiver is implicitly "this".
return "this".equals(arg.toString());
}
return false;
}
};
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class Matchers method enclosingNode.
/**
* Matches an AST node that is enclosed by some node that matches the given matcher.
*
* TODO(eaftan): This could be used instead of enclosingBlock and enclosingClass.
*/
public static <T extends Tree> Matcher<Tree> enclosingNode(final Matcher<T> matcher) {
return new Matcher<Tree>() {
// TODO(cushon): this should take a Class<T>
@SuppressWarnings("unchecked")
@Override
public boolean matches(Tree t, VisitorState state) {
TreePath path = state.getPath().getParentPath();
while (path != null) {
Tree node = path.getLeaf();
state = state.withPath(path);
if (matcher.matches((T) node, state)) {
return true;
}
path = path.getParentPath();
}
return false;
}
};
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class RestrictedApiChecker method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
RestrictedApi annotation = ASTHelpers.getAnnotation(tree, RestrictedApi.class);
if (annotation != null) {
return checkRestriction(annotation, tree, state);
}
MethodSymbol methSymbol = ASTHelpers.getSymbol(tree);
if (methSymbol == null) {
// This shouldn't happen, but has. (See b/33758055)
return Description.NO_MATCH;
}
// Try each super method for @RestrictedApi
Optional<MethodSymbol> superWithRestrictedApi = ASTHelpers.findSuperMethods(methSymbol, state.getTypes()).stream().filter((t) -> ASTHelpers.hasAnnotation(t, RestrictedApi.class, state)).findFirst();
if (!superWithRestrictedApi.isPresent()) {
return Description.NO_MATCH;
}
return checkRestriction(ASTHelpers.getAnnotation(superWithRestrictedApi.get(), RestrictedApi.class), tree, state);
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class TypeParameterShadowing method findDuplicatesOf.
private Description findDuplicatesOf(Tree tree, List<? extends TypeParameterTree> typeParameters, VisitorState state) {
Symbol symbol = ASTHelpers.getSymbol(tree);
if (symbol == null) {
return Description.NO_MATCH;
}
List<TypeVariableSymbol> enclosingTypeSymbols = typeVariablesEnclosing(symbol);
if (enclosingTypeSymbols.isEmpty()) {
return Description.NO_MATCH;
}
List<TypeVariableSymbol> conflictingTypeSymbols = new ArrayList<>();
typeParameters.forEach(param -> enclosingTypeSymbols.stream().filter(tvs -> tvs.name.contentEquals(param.getName())).findFirst().ifPresent(conflictingTypeSymbols::add));
if (conflictingTypeSymbols.isEmpty()) {
return Description.NO_MATCH;
}
Description.Builder descriptionBuilder = buildDescription(tree);
String message = "Found aliased type parameters: " + conflictingTypeSymbols.stream().map(tvs -> tvs.name + " declared in " + tvs.owner.getSimpleName()).collect(Collectors.joining("\n"));
descriptionBuilder.setMessage(message);
Set<String> typeVarsInScope = Streams.concat(enclosingTypeSymbols.stream(), symbol.getTypeParameters().stream()).map(v -> v.name.toString()).collect(toImmutableSet());
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
conflictingTypeSymbols.stream().map(v -> renameTypeVariable(tree, typeParameters, v.name, replacementTypeVarName(v.name, typeVarsInScope), state)).forEach(fixBuilder::merge);
descriptionBuilder.addFix(fixBuilder.build());
return descriptionBuilder.build();
}
use of com.google.errorprone.VisitorState in project error-prone by google.
the class UnnecessaryDefaultInEnumSwitch method matchSwitch.
@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
TypeSymbol switchType = ((JCSwitch) tree).getExpression().type.tsym;
if (switchType.getKind() != ElementKind.ENUM) {
return NO_MATCH;
}
Optional<? extends CaseTree> maybeDefaultCase = tree.getCases().stream().filter(c -> c.getExpression() == null).findFirst();
if (!maybeDefaultCase.isPresent()) {
return NO_MATCH;
}
CaseTree defaultCase = maybeDefaultCase.get();
Set<String> handledCases = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(p -> ((IdentifierTree) p).getName().toString()).collect(toImmutableSet());
if (!ASTHelpers.enumValues(switchType).equals(handledCases)) {
return NO_MATCH;
}
Fix fix;
List<? extends StatementTree> defaultStatements = defaultCase.getStatements();
if (trivialDefault(defaultStatements)) {
// deleting `default:` or `default: break;` is a no-op
fix = SuggestedFix.delete(defaultCase);
} else if (!canCompleteNormally(tree)) {
// if the switch statement cannot complete normally, then deleting the default
// and moving its statements to after the switch statement is a no-op
String defaultSource = state.getSourceCode().subSequence(((JCTree) defaultStatements.get(0)).getStartPosition(), state.getEndPosition(getLast(defaultStatements))).toString();
fix = SuggestedFix.builder().delete(defaultCase).postfixWith(tree, defaultSource).build();
} else {
return NO_MATCH;
}
return describeMatch(defaultCase, fix);
}
Aggregations