use of com.sun.source.tree.CaseTree in project checker-framework by typetools.
the class TreeUtils method switchExpressionTreeGetCases.
/**
* Returns the cases of {@code switchExpressionTree}. For example
*
* <pre>
* switch ( <em>expression</em> ) {
* <em>cases</em>
* }
* </pre>
*
* @param switchExpressionTree the switch expression whose cases are returned
* @return the cases of {@code switchExpressionTree}
*/
public static List<? extends CaseTree> switchExpressionTreeGetCases(Tree switchExpressionTree) {
try {
Class<?> switchExpressionClass = Class.forName("com.sun.source.tree.SwitchExpressionTree");
Method getCasesMethod = switchExpressionClass.getMethod("getCases");
@SuppressWarnings("unchecked") List<? extends CaseTree> cases = (List<? extends CaseTree>) getCasesMethod.invoke(switchExpressionTree);
if (cases != null) {
return cases;
}
throw new BugInCF("TreeUtils.switchExpressionTreeGetCases: cases is null for tree: %s", switchExpressionTree);
} catch (ClassNotFoundException | NoSuchMethodException | InvocationTargetException | IllegalAccessException e) {
throw new BugInCF("TreeUtils.switchExpressionTreeGetCases: reflection failed for tree: %s", switchExpressionTree, e);
}
}
use of com.sun.source.tree.CaseTree in project checker-framework by typetools.
the class SwitchExpressionScanner method scanSwitchExpression.
/**
* Scans the given switch expression and calls {@link #visitSwitchResultExpression(ExpressionTree,
* Object)} on each result expression of the switch expression. {@link #combineResults(Object,
* Object)} is called to combine the results of visiting multiple switch result expressions.
*
* @param switchExpression a switch expression tree
* @param p the parameter to pass to {@link #visitSwitchResultExpression(ExpressionTree, Object)}
* @return the result of calling {@link #visitSwitchResultExpression(ExpressionTree, Object)} on
* each result expression of {@code switchExpression} and combining the results using {@link
* #combineResults(Object, Object)}
*/
public R scanSwitchExpression(Tree switchExpression, P p) {
assert switchExpression.getKind().name().equals("SWITCH_EXPRESSION");
List<? extends CaseTree> caseTrees = TreeUtils.switchExpressionTreeGetCases(switchExpression);
R result = null;
for (CaseTree caseTree : caseTrees) {
if (caseTree.getStatements() != null) {
// This case is a switch labeled statement group, so scan the statements for yield
// statements.
result = combineResults(result, yieldVisitor.scan(caseTree.getStatements(), p));
} else {
@SuppressWarnings(// caseTree.getStatements() == null, so the case has a body.
"nullness:assignment") @NonNull Tree body = TreeUtils.caseTreeGetBody(caseTree);
// See https://docs.oracle.com/javase/specs/jls/se17/html/jls-15.html#jls-15.28.2.
if (body.getKind() == Kind.BLOCK) {
// Scan for yield statements.
result = combineResults(result, yieldVisitor.scan(((BlockTree) body).getStatements(), p));
} else if (body.getKind() != Kind.THROW) {
// The expression is the result expression.
ExpressionTree expressionTree = (ExpressionTree) body;
result = combineResults(result, visitSwitchResultExpression(expressionTree, p));
}
}
}
@SuppressWarnings(// switch expressions must have at least one case that results in a
"nullness:assignment") @NonNull R nonNullResult = result;
return nonNullResult;
}
use of com.sun.source.tree.CaseTree in project j2objc by google.
the class TreeConverter method convertSwitch.
private TreeNode convertSwitch(SwitchTree node, TreePath parent) {
TreePath path = getTreePath(parent, node);
SwitchStatement newNode = new SwitchStatement().setExpression(convertWithoutParens(node.getExpression(), path));
for (CaseTree switchCase : node.getCases()) {
newNode.addStatement((SwitchCase) convert(switchCase, path));
TreePath switchCasePath = getTreePath(path, switchCase);
for (StatementTree s : switchCase.getStatements()) {
newNode.addStatement((Statement) convert(s, switchCasePath));
}
}
return newNode;
}
use of com.sun.source.tree.CaseTree in project error-prone by google.
the class UnnecessaryDefaultInEnumSwitch method matchSwitch.
@Override
public Description matchSwitch(SwitchTree switchTree, VisitorState state) {
// Only look at enum switches.
TypeSymbol switchType = ((JCSwitch) switchTree).getExpression().type.tsym;
if (switchType.getKind() != ElementKind.ENUM) {
return NO_MATCH;
}
// Extract default case and the one before it.
CaseTree caseBeforeDefault = null;
CaseTree defaultCase = null;
for (CaseTree caseTree : switchTree.getCases()) {
if (caseTree.getExpression() == null) {
defaultCase = caseTree;
break;
} else {
caseBeforeDefault = caseTree;
}
}
if (caseBeforeDefault == null || defaultCase == null) {
return NO_MATCH;
}
SetView<String> unhandledCases = unhandledCases(switchTree, switchType);
if (unhandledCases.equals(ImmutableSet.of("UNRECOGNIZED"))) {
// switch handles all values of an proto-generated enum except for 'UNRECOGNIZED'.
return fixUnrecognized(switchTree, defaultCase, state);
}
if (unhandledCases.isEmpty()) {
// switch is exhaustive, remove the default if we can.
return fixDefault(switchTree, caseBeforeDefault, defaultCase, state);
}
// switch is non-exhaustive, default can stay.
return NO_MATCH;
}
use of com.sun.source.tree.CaseTree in project error-prone by google.
the class DifferentNameButSame method matchCompilationUnit.
@Override
public Description matchCompilationUnit(CompilationUnitTree tree, VisitorState state) {
Table<Symbol, String, List<TreePath>> names = HashBasedTable.create();
new TreePathScanner<Void, Void>() {
@Override
public Void visitImport(ImportTree importTree, Void unused) {
return null;
}
@Override
public Void visitCase(CaseTree caseTree, Void unused) {
return null;
}
@Override
public Void visitMemberSelect(MemberSelectTree memberSelectTree, Void unused) {
if (getCurrentPath().getParentPath().getLeaf() instanceof MemberSelectTree) {
MemberSelectTree tree = (MemberSelectTree) getCurrentPath().getParentPath().getLeaf();
Symbol superSymbol = getSymbol(tree);
if (superSymbol instanceof ClassSymbol) {
return super.visitMemberSelect(memberSelectTree, null);
}
}
handle(memberSelectTree);
return super.visitMemberSelect(memberSelectTree, null);
}
@Override
public Void visitIdentifier(IdentifierTree identifierTree, Void unused) {
Tree parent = getCurrentPath().getParentPath().getLeaf();
if (parent instanceof NewClassTree) {
NewClassTree newClassTree = (NewClassTree) parent;
if (newClassTree.getIdentifier().equals(identifierTree) && newClassTree.getEnclosingExpression() != null) {
// don't try to fix instantiations with explicit enclosing instances, e.g. `a.new B();`
return null;
}
}
handle(identifierTree);
return super.visitIdentifier(identifierTree, null);
}
private void handle(Tree tree) {
if (state.getEndPosition(tree) == Position.NOPOS) {
return;
}
Symbol symbol = getSymbol(tree);
if (!(symbol instanceof ClassSymbol)) {
return;
}
String name = tree.toString();
List<TreePath> treePaths = names.get(symbol, name);
if (treePaths == null) {
treePaths = new ArrayList<>();
names.put(symbol, name, treePaths);
}
treePaths.add(getCurrentPath());
}
}.scan(tree, null);
for (Map.Entry<Symbol, Map<String, List<TreePath>>> entry : names.rowMap().entrySet()) {
Symbol symbol = entry.getKey();
// each level.
if (isGeneric(symbol)) {
continue;
}
if (isDefinedInThisFile(symbol, tree)) {
continue;
}
Map<String, List<TreePath>> references = entry.getValue();
if (references.size() == 1) {
continue;
}
// Skip if any look to be fully qualified: this will be mentioned by a different check.
if (references.keySet().stream().anyMatch(n -> Ascii.isLowerCase(n.charAt(0)))) {
continue;
}
ImmutableList<String> namesByPreference = references.entrySet().stream().sorted(REPLACEMENT_PREFERENCE).map(Map.Entry::getKey).collect(toImmutableList());
for (String name : namesByPreference) {
ImmutableList<TreePath> sites = references.entrySet().stream().filter(e -> !e.getKey().equals(name)).map(Map.Entry::getValue).flatMap(Collection::stream).collect(toImmutableList());
if (!(symbol instanceof MethodSymbol) && !visibleAndReferToSameThing(name, sites, state)) {
continue;
}
if (BadImport.BAD_NESTED_CLASSES.contains(name)) {
continue;
}
List<String> components = DOT_SPLITTER.splitToList(name);
SuggestedFix.Builder fixBuilder = SuggestedFix.builder();
for (TreePath site : sites) {
fixBuilder.merge(createFix(site, components, state));
}
SuggestedFix fix = fixBuilder.build();
for (TreePath path : sites) {
state.reportMatch(describeMatch(path.getLeaf(), fix));
}
break;
}
}
return NO_MATCH;
}
Aggregations