Skip to content

Commit cd9a2a3

Browse files
authored
JointJavacJavaParserVisitor now handles switch expressions (#4992)
JavaParsers crashes on some yields and also parses some to objects other than YieldStmts. ( javaparser/javaparser#3364)
1 parent 689b033 commit cd9a2a3

File tree

6 files changed

+132
-14
lines changed

6 files changed

+132
-14
lines changed

framework/src/main/java/org/checkerframework/common/basetype/BaseTypeVisitor.java

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,6 @@
7676
import javax.lang.model.type.TypeMirror;
7777
import javax.lang.model.util.ElementFilter;
7878
import javax.tools.Diagnostic.Kind;
79-
import javax.tools.JavaFileObject;
8079
import org.checkerframework.checker.compilermsgs.qual.CompilerMessageKey;
8180
import org.checkerframework.checker.interning.qual.FindDistinct;
8281
import org.checkerframework.checker.nullness.qual.NonNull;
@@ -366,11 +365,6 @@ protected void testJointJavacJavaParserVisitor() {
366365
}
367366

368367
Map<Tree, com.github.javaparser.ast.Node> treePairs = new HashMap<>();
369-
JavaFileObject f = root.getSourceFile();
370-
if (f.toUri().getPath().contains("java17")) {
371-
// Skip java17 files because they may contain switch expressions which aren't supported.
372-
return;
373-
}
374368
try (InputStream reader = root.getSourceFile().openInputStream()) {
375369
CompilationUnit javaParserRoot = JavaParserUtil.parseCompilationUnit(reader);
376370
JavaParserUtil.concatenateAddedStringLiterals(javaParserRoot);

framework/src/main/java/org/checkerframework/framework/ajava/DefaultJointVisitor.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.github.javaparser.ast.expr.SimpleName;
3838
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
3939
import com.github.javaparser.ast.expr.SuperExpr;
40+
import com.github.javaparser.ast.expr.SwitchExpr;
4041
import com.github.javaparser.ast.expr.ThisExpr;
4142
import com.github.javaparser.ast.expr.UnaryExpr;
4243
import com.github.javaparser.ast.modules.ModuleDeclaration;
@@ -65,6 +66,7 @@
6566
import com.github.javaparser.ast.stmt.ThrowStmt;
6667
import com.github.javaparser.ast.stmt.TryStmt;
6768
import com.github.javaparser.ast.stmt.WhileStmt;
69+
import com.github.javaparser.ast.stmt.YieldStmt;
6870
import com.github.javaparser.ast.type.ArrayType;
6971
import com.github.javaparser.ast.type.ClassOrInterfaceType;
7072
import com.github.javaparser.ast.type.IntersectionType;
@@ -347,6 +349,9 @@ public void processReturn(ReturnTree javacTree, ReturnStmt javaParserNode) {}
347349
@Override
348350
public void processSwitch(SwitchTree javacTree, SwitchStmt javaParserNode) {}
349351

352+
@Override
353+
public void processSwitchExpression(Tree javacTree, SwitchExpr javaParserNode) {}
354+
350355
@Override
351356
public void processSynchronized(SynchronizedTree javacTree, SynchronizedStmt javaParserNode) {}
352357

@@ -389,6 +394,9 @@ public void processWhileLoop(WhileLoopTree javacTree, WhileStmt javaParserNode)
389394
@Override
390395
public void processWildcard(WildcardTree javacTree, WildcardType javaParserNode) {}
391396

397+
@Override
398+
public void processYield(Tree javacTree, YieldStmt javaParserNode) {}
399+
392400
@Override
393401
public void processCompoundAssignment(
394402
CompoundAssignmentTree javacTree, AssignExpr javaParserNode) {}

framework/src/main/java/org/checkerframework/framework/ajava/ExpectedTreesVisitor.java

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,14 @@ public Void visitSwitch(SwitchTree tree, Void p) {
203203
return null;
204204
}
205205

206+
@Override
207+
public Void visitSwitchExpression17(Tree tree, Void p) {
208+
super.visitSwitchExpression17(tree, p);
209+
// javac surrounds switch expression in a ParenthesizedTree but JavaParser does not.
210+
trees.remove(TreeUtils.switchExpressionTreeGetExpression(tree));
211+
return null;
212+
}
213+
206214
@Override
207215
public Void visitSynchronized(SynchronizedTree tree, Void p) {
208216
super.visitSynchronized(tree, p);
@@ -374,6 +382,14 @@ public Void visitVariable(VariableTree tree, Void p) {
374382
return super.visitVariable(tree, p);
375383
}
376384

385+
@Override
386+
public Void visitYield17(Tree tree, Void p) {
387+
// JavaParser does not parse yields correctly:
388+
// https://github.com/javaparser/javaparser/issues/3364
389+
// So skip yields.
390+
return null;
391+
}
392+
377393
/**
378394
* Calls the correct visit method for {@code tree} if {@code tree} is non-null.
379395
*

framework/src/main/java/org/checkerframework/framework/ajava/JointJavacJavaParserVisitor.java

Lines changed: 58 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,7 @@
4141
import com.github.javaparser.ast.expr.SimpleName;
4242
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
4343
import com.github.javaparser.ast.expr.SuperExpr;
44+
import com.github.javaparser.ast.expr.SwitchExpr;
4445
import com.github.javaparser.ast.expr.ThisExpr;
4546
import com.github.javaparser.ast.expr.TypeExpr;
4647
import com.github.javaparser.ast.expr.UnaryExpr;
@@ -74,6 +75,7 @@
7475
import com.github.javaparser.ast.stmt.ThrowStmt;
7576
import com.github.javaparser.ast.stmt.TryStmt;
7677
import com.github.javaparser.ast.stmt.WhileStmt;
78+
import com.github.javaparser.ast.stmt.YieldStmt;
7779
import com.github.javaparser.ast.type.ArrayType;
7880
import com.github.javaparser.ast.type.ClassOrInterfaceType;
7981
import com.github.javaparser.ast.type.IntersectionType;
@@ -140,6 +142,7 @@
140142
import com.sun.source.tree.SynchronizedTree;
141143
import com.sun.source.tree.ThrowTree;
142144
import com.sun.source.tree.Tree;
145+
import com.sun.source.tree.Tree.Kind;
143146
import com.sun.source.tree.TryTree;
144147
import com.sun.source.tree.TypeCastTree;
145148
import com.sun.source.tree.TypeParameterTree;
@@ -317,6 +320,7 @@ && isDefaultSuperConstructorCall(javacIter.peek())
317320
// instances. In javaParser this is one VariableDeclarationExpr with two nested
318321
// VariableDeclarators. Match the declarators with the VariableTrees.
319322
if (javaParserIter.hasNext()
323+
&& javacIter.peek().getKind() == Tree.Kind.VARIABLE
320324
&& javaParserIter.peek().isExpressionStmt()
321325
&& javaParserIter.peek().asExpressionStmt().getExpression().isVariableDeclarationExpr()) {
322326
for (VariableDeclarator decl :
@@ -327,7 +331,6 @@ && isDefaultSuperConstructorCall(javacIter.peek())
327331
.asVariableDeclarationExpr()
328332
.getVariables()) {
329333
assert javacIter.hasNext();
330-
assert javacIter.peek().getKind() == Tree.Kind.VARIABLE;
331334
javacIter.next().accept(this, decl);
332335
}
333336

@@ -409,8 +412,20 @@ public Void visitCase(CaseTree javacTree, Node javaParserNode) {
409412
for (int i = 0; i < treeExpressions.size(); i++) {
410413
treeExpressions.get(i).accept(this, labels.get(i));
411414
}
415+
if (javacTree.getStatements() == null) {
416+
Tree javacBody = TreeUtils.caseTreeGetBody(javacTree);
417+
Statement nodeBody = node.getStatement(0);
418+
if (javacBody.getKind() == Kind.EXPRESSION_STATEMENT) {
419+
javacBody.accept(this, node.getStatement(0));
420+
} else if (nodeBody.isExpressionStmt()) {
421+
javacBody.accept(this, nodeBody.asExpressionStmt().getExpression());
422+
} else {
423+
javacBody.accept(this, nodeBody);
424+
}
425+
} else {
426+
processStatements(javacTree.getStatements(), node.getStatements());
427+
}
412428

413-
processStatements(javacTree.getStatements(), node.getStatements());
414429
return null;
415430
}
416431

@@ -1228,14 +1243,23 @@ public Void visitSwitch(SwitchTree javacTree, Node javaParserNode) {
12281243
}
12291244

12301245
/**
1231-
* Visit a SwitchExpressionTree
1246+
* Visit a switch expression.
12321247
*
1233-
* @param tree a SwitchExpressionTree, typed as Tree to be backward-compatible
1234-
* @param node a SwitchExpr, typed as Node to be backward-compatible
1235-
* @return nothing
1248+
* @param javacTree switch expression tree
1249+
* @param javaParserNode java parser node
1250+
* @return null
12361251
*/
1237-
public Void visitSwitchExpression17(Tree tree, Node node) {
1238-
// TODO
1252+
public Void visitSwitchExpression17(Tree javacTree, Node javaParserNode) {
1253+
SwitchExpr node = castNode(SwitchExpr.class, javaParserNode, javacTree);
1254+
processSwitchExpression(javacTree, node);
1255+
1256+
// Switch expressions are always parenthesized in javac but never in JavaParser.
1257+
ExpressionTree expression =
1258+
((ParenthesizedTree) TreeUtils.switchExpressionTreeGetExpression(javacTree))
1259+
.getExpression();
1260+
expression.accept(this, node.getSelector());
1261+
1262+
visitLists(TreeUtils.switchExpressionTreeGetCases(javacTree), node.getEntries());
12391263
return null;
12401264
}
12411265

@@ -1452,6 +1476,16 @@ public Void visitWildcard(WildcardTree javacTree, Node javaParserNode) {
14521476
* @return nothing
14531477
*/
14541478
public Void visitYield17(Tree tree, Node node) {
1479+
if (node instanceof YieldStmt) {
1480+
YieldStmt yieldStmt = castNode(YieldStmt.class, node, tree);
1481+
processYield(tree, yieldStmt);
1482+
1483+
TreeUtils.yieldTreeGetValue(tree).accept(this, yieldStmt.getExpression());
1484+
return null;
1485+
}
1486+
// JavaParser does not parse yields correctly:
1487+
// https://github.com/javaparser/javaparser/issues/3364
1488+
// So skip yields that aren't matched with a YieldStmt.
14551489
return null;
14561490
}
14571491

@@ -2036,6 +2070,14 @@ public abstract void processRequires(
20362070
*/
20372071
public abstract void processSwitch(SwitchTree javacTree, SwitchStmt javaParserNode);
20382072

2073+
/**
2074+
* Process a {@code SwitchExpressionTree}.
2075+
*
2076+
* @param javacTree tree to process
2077+
* @param javaParserNode corresponding JavaParser node
2078+
*/
2079+
public abstract void processSwitchExpression(Tree javacTree, SwitchExpr javaParserNode);
2080+
20392081
/**
20402082
* Process a {@code SynchronizedTree}.
20412083
*
@@ -2152,6 +2194,14 @@ public abstract void processVariable(
21522194
*/
21532195
public abstract void processWildcard(WildcardTree javacTree, WildcardType javaParserNode);
21542196

2197+
/**
2198+
* Process a {@code YieldTree}.
2199+
*
2200+
* @param javacTree tree to process
2201+
* @param javaParserNode corresponding Javaparser node
2202+
*/
2203+
public abstract void processYield(Tree javacTree, YieldStmt javaParserNode);
2204+
21552205
/**
21562206
* Process a {@code CompoundAssignmentTree}.
21572207
*

framework/src/main/java/org/checkerframework/framework/ajava/JointVisitorWithDefaultAction.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import com.github.javaparser.ast.expr.SimpleName;
3838
import com.github.javaparser.ast.expr.SingleMemberAnnotationExpr;
3939
import com.github.javaparser.ast.expr.SuperExpr;
40+
import com.github.javaparser.ast.expr.SwitchExpr;
4041
import com.github.javaparser.ast.expr.ThisExpr;
4142
import com.github.javaparser.ast.expr.UnaryExpr;
4243
import com.github.javaparser.ast.modules.ModuleDeclaration;
@@ -65,6 +66,7 @@
6566
import com.github.javaparser.ast.stmt.ThrowStmt;
6667
import com.github.javaparser.ast.stmt.TryStmt;
6768
import com.github.javaparser.ast.stmt.WhileStmt;
69+
import com.github.javaparser.ast.stmt.YieldStmt;
6870
import com.github.javaparser.ast.type.ArrayType;
6971
import com.github.javaparser.ast.type.ClassOrInterfaceType;
7072
import com.github.javaparser.ast.type.IntersectionType;
@@ -490,6 +492,11 @@ public void processSwitch(SwitchTree javacTree, SwitchStmt javaParserNode) {
490492
defaultJointAction(javacTree, javaParserNode);
491493
}
492494

495+
@Override
496+
public void processSwitchExpression(Tree javacTree, SwitchExpr javaParserNode) {
497+
defaultJointAction(javacTree, javaParserNode);
498+
}
499+
493500
@Override
494501
public void processSynchronized(SynchronizedTree javacTree, SynchronizedStmt javaParserNode) {
495502
defaultJointAction(javacTree, javaParserNode);
@@ -560,6 +567,11 @@ public void processWildcard(WildcardTree javacTree, WildcardType javaParserNode)
560567
defaultJointAction(javacTree, javaParserNode);
561568
}
562569

570+
@Override
571+
public void processYield(Tree javacTree, YieldStmt javaParserNode) {
572+
defaultJointAction(javacTree, javaParserNode);
573+
}
574+
563575
@Override
564576
public void processCompoundAssignment(
565577
CompoundAssignmentTree javacTree, AssignExpr javaParserNode) {

framework/src/main/java/org/checkerframework/framework/ajava/TreeScannerWithDefaults.java

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,20 @@ public abstract class TreeScannerWithDefaults extends TreeScanner<Void, Void> {
7575
*/
7676
public abstract void defaultAction(Tree tree);
7777

78+
@Override
79+
public Void scan(Tree tree, Void unused) {
80+
if (tree != null) {
81+
if (tree.getKind().name().equals("SWITCH_EXPRESSION")) {
82+
visitSwitchExpression17(tree, unused);
83+
return null;
84+
} else if (tree.getKind().name().equals("YIELD")) {
85+
visitYield17(tree, unused);
86+
return null;
87+
}
88+
}
89+
return super.scan(tree, unused);
90+
}
91+
7892
@Override
7993
public Void visitAnnotatedType(AnnotatedTypeTree tree, Void p) {
8094
defaultAction(tree);
@@ -369,6 +383,18 @@ public Void visitSwitch(SwitchTree tree, Void p) {
369383
return super.visitSwitch(tree, p);
370384
}
371385

386+
/**
387+
* Visit a switch expression tree.
388+
*
389+
* @param tree switch expression tree
390+
* @param p null
391+
* @return null
392+
*/
393+
public Void visitSwitchExpression17(Tree tree, Void p) {
394+
defaultAction(tree);
395+
return super.scan(tree, p);
396+
}
397+
372398
@Override
373399
public Void visitSynchronized(SynchronizedTree tree, Void p) {
374400
defaultAction(tree);
@@ -434,4 +460,16 @@ public Void visitWildcard(WildcardTree tree, Void p) {
434460
defaultAction(tree);
435461
return super.visitWildcard(tree, p);
436462
}
463+
464+
/**
465+
* Visit a yield tree.
466+
*
467+
* @param tree a yield tree
468+
* @param p null
469+
* @return null
470+
*/
471+
public Void visitYield17(Tree tree, Void p) {
472+
defaultAction(tree);
473+
return super.scan(tree, p);
474+
}
437475
}

0 commit comments

Comments
 (0)