use of com.sun.source.tree.IdentifierTree in project error-prone by google.
the class MissingCasesInEnumSwitch method matchSwitch.
@Override
public Description matchSwitch(SwitchTree tree, VisitorState state) {
Type switchType = ASTHelpers.getType(tree.getExpression());
if (switchType.asElement().getKind() != ElementKind.ENUM) {
return Description.NO_MATCH;
}
// default case is present
if (tree.getCases().stream().anyMatch(c -> c.getExpression() == null)) {
return Description.NO_MATCH;
}
ImmutableSet<String> handled = tree.getCases().stream().map(CaseTree::getExpression).filter(IdentifierTree.class::isInstance).map(e -> ((IdentifierTree) e).getName().toString()).collect(toImmutableSet());
Set<String> unhandled = Sets.difference(ASTHelpers.enumValues(switchType.asElement()), handled);
if (unhandled.isEmpty()) {
return Description.NO_MATCH;
}
return buildDescription(tree).setMessage(buildMessage(unhandled)).build();
}
use of com.sun.source.tree.IdentifierTree in project error-prone by google.
the class NestedInstanceOfConditions method matchIf.
@Override
public Description matchIf(IfTree ifTree, VisitorState visitorState) {
ExpressionTree expressionTree = stripParentheses(ifTree.getCondition());
if (expressionTree instanceof InstanceOfTree) {
InstanceOfTree instanceOfTree = (InstanceOfTree) expressionTree;
if (!(instanceOfTree.getExpression() instanceof IdentifierTree)) {
return Description.NO_MATCH;
}
Matcher<Tree> assignmentTreeMatcher = new AssignmentTreeMatcher(instanceOfTree.getExpression());
Matcher<Tree> containsAssignmentTreeMatcher = contains(assignmentTreeMatcher);
if (containsAssignmentTreeMatcher.matches(ifTree, visitorState)) {
return Description.NO_MATCH;
}
// set expression and type to look for in matcher
Matcher<Tree> nestedInstanceOfMatcher = new NestedInstanceOfMatcher(instanceOfTree.getExpression(), instanceOfTree.getType());
Matcher<Tree> containsNestedInstanceOfMatcher = contains(nestedInstanceOfMatcher);
if (containsNestedInstanceOfMatcher.matches(ifTree.getThenStatement(), visitorState)) {
return describeMatch(ifTree);
}
}
return Description.NO_MATCH;
}
use of com.sun.source.tree.IdentifierTree in project error-prone by google.
the class MyCustomCheck method matchMethodInvocation.
@Override
public Description matchMethodInvocation(MethodInvocationTree tree, VisitorState state) {
if (!PRINT_METHOD.matches(tree, state)) {
return NO_MATCH;
}
Symbol base = tree.getMethodSelect().accept(new TreeScanner<Symbol, Void>() {
@Override
public Symbol visitIdentifier(IdentifierTree node, Void unused) {
return ASTHelpers.getSymbol(node);
}
@Override
public Symbol visitMemberSelect(MemberSelectTree node, Void unused) {
return super.visitMemberSelect(node, null);
}
}, null);
if (!Objects.equals(base, state.getSymtab().systemType.tsym)) {
return NO_MATCH;
}
ExpressionTree arg = Iterables.getOnlyElement(tree.getArguments());
if (!STRING_FORMAT.matches(arg, state)) {
return NO_MATCH;
}
List<? extends ExpressionTree> formatArgs = ((MethodInvocationTree) arg).getArguments();
return describeMatch(tree, SuggestedFix.builder().replace(((JCTree) tree).getStartPosition(), ((JCTree) formatArgs.get(0)).getStartPosition(), "System.err.printf(").replace(state.getEndPosition((JCTree) getLast(formatArgs)), state.getEndPosition((JCTree) tree), ")").build());
}
use of com.sun.source.tree.IdentifierTree 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;
}
CaseTree caseBeforeDefault = null;
CaseTree defaultCase = null;
for (CaseTree caseTree : tree.getCases()) {
if (caseTree.getExpression() == null) {
defaultCase = caseTree;
break;
} else {
caseBeforeDefault = caseTree;
}
}
if (defaultCase == null) {
return NO_MATCH;
}
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 {
String defaultSource = state.getSourceCode().subSequence(((JCTree) defaultStatements.get(0)).getStartPosition(), state.getEndPosition(getLast(defaultStatements))).toString();
String initialComments = comments(state, defaultCase, defaultStatements);
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
fix = SuggestedFix.builder().delete(defaultCase).postfixWith(tree, initialComments + defaultSource).build();
} else {
// and the code is unreachable -- so use (2) as the strategy. Otherwise, use (1).
if (!SuggestedFixes.compilesWithFix(SuggestedFix.delete(defaultCase), state)) {
// case (3)
return NO_MATCH;
}
if (!canCompleteNormally(caseBeforeDefault)) {
// case (2) -- If the case before the default can't complete normally,
// it's OK to to delete the default.
fix = SuggestedFix.delete(defaultCase);
} else {
// case (1) -- If it can complete, we need to merge the default into it.
fix = SuggestedFix.builder().delete(defaultCase).postfixWith(caseBeforeDefault, initialComments + defaultSource).build();
}
}
}
return describeMatch(defaultCase, fix);
}
use of com.sun.source.tree.IdentifierTree in project error-prone by google.
the class ConstructorLeaksThis method traverse.
@Override
protected void traverse(Tree tree, VisitorState state) {
ClassSymbol thisClass = ASTHelpers.getSymbol(state.findEnclosing(ClassTree.class));
tree.accept(new TreeScanner<Void, Void>() {
@Override
public Void visitIdentifier(IdentifierTree node, Void unused) {
checkForThis(node, node.getName(), thisClass, state);
return super.visitIdentifier(node, null);
}
@Override
public Void visitMemberSelect(MemberSelectTree node, Void unused) {
checkForThis(node, node.getIdentifier(), thisClass, state);
// Don't examine this.foo or MyClass.this.foo
ExpressionTree left = node.getExpression();
if ((left instanceof IdentifierTree && ((IdentifierTree) left).getName().contentEquals("this")) || (left instanceof MemberSelectTree && ((MemberSelectTree) left).getIdentifier().contentEquals("this"))) {
return null;
}
return super.visitMemberSelect(node, unused);
}
@Override
public Void visitAssignment(AssignmentTree node, Void unused) {
scan(node.getExpression(), null);
// ignore references to 'this' in the LHS of assignments
return null;
}
}, null);
}
Aggregations