[java] Add Java 13 support

Fix type resolution of switch with yields
This commit is contained in:
Andreas Dangel committed 2019-08-13 20:48:01 +02:00
1 parent b110186ed7
commit ac4a0daff9
4 files changed
+86 -3

No files matched your search

@@ -18,4 +18,13 @@ public class ASTYieldStatement extends AbstractJavaTypeNode {
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
@Override
public String getImage() {
String result = super.getImage();
if (result == null && hasDescendantOfType(ASTName.class)) {
result = getFirstDescendantOfType(ASTName.class).getImage();
}
return result;
}
}
@@ -34,7 +34,6 @@ import net.sourceforge.pmd.lang.java.ast.ASTArrayDimsAndInits;
import net.sourceforge.pmd.lang.java.ast.ASTBlock;
import net.sourceforge.pmd.lang.java.ast.ASTBlockStatement;
import net.sourceforge.pmd.lang.java.ast.ASTBooleanLiteral;
import net.sourceforge.pmd.lang.java.ast.ASTBreakStatement;
import net.sourceforge.pmd.lang.java.ast.ASTCastExpression;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceDeclaration;
import net.sourceforge.pmd.lang.java.ast.ASTClassOrInterfaceType;
@@ -1187,7 +1186,7 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
super.visit(node, data);
JavaTypeDefinition type = null;
// first try to determine the type based on the first expression/break of a switch rule
// first try to determine the type based on the first expression/break/yield of a switch rule
List<ASTSwitchLabeledRule> rules = node.findChildrenOfType(ASTSwitchLabeledRule.class);
for (ASTSwitchLabeledRule rule : rules) {
Node body = rule.jjtGetChild(1); // second child is either Expression, Block, ThrowStatement
@@ -1203,10 +1202,18 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
break;
}
}
List<ASTYieldStatement> yields = body.findDescendantsOfType(ASTYieldStatement.class);
if (!yields.isEmpty()) {
ASTExpression expression = yields.get(0).getFirstChildOfType(ASTExpression.class);
if (expression != null) {
type = expression.getTypeDefinition();
break;
}
}
}
}
if (type == null) {
// now check the labels and their expressions of break statements
// now check the labels and their expressions of break/yield statements
for (int i = 0; i < node.jjtGetNumChildren(); i++) {
Node child = node.jjtGetChild(i);
if (child instanceof ASTBlockStatement) {
@@ -1218,6 +1225,14 @@ public class ClassTypeResolver extends JavaParserVisitorAdapter {
break;
}
}
List<ASTYieldStatement> yields = child.findDescendantsOfType(ASTYieldStatement.class);
if (!yields.isEmpty()) {
ASTExpression expression = yields.get(0).getFirstChildOfType(ASTExpression.class);
if (expression != null && expression.getTypeDefinition() != null) {
type = expression.getTypeDefinition();
break;
}
}
}
}
}
@@ -41,6 +41,29 @@ public class Java13Test {
Assert.assertEquals(Integer.TYPE, yieldStatement.getType());
}
@Test
public void testSwitchExpressionsYield() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("13",
loadSource("SwitchExpressionsYield.java"));
Assert.assertNotNull(compilationUnit);
ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class);
Assert.assertEquals(11, switchExpression.jjtGetNumChildren());
Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression);
Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabel.class).size());
ASTYieldStatement yieldStatement = switchExpression.getFirstDescendantOfType(ASTYieldStatement.class);
Assert.assertEquals("SwitchExpressionsBreak.SIX", yieldStatement.getImage());
Assert.assertTrue(yieldStatement.jjtGetChild(0) instanceof ASTExpression);
ASTLocalVariableDeclaration localVar = compilationUnit.findDescendantsOfType(ASTLocalVariableDeclaration.class)
.get(1);
ASTVariableDeclarator localVarDecl = localVar.getFirstChildOfType(ASTVariableDeclarator.class);
Assert.assertEquals(Integer.TYPE, localVarDecl.getType());
Assert.assertEquals(Integer.TYPE, switchExpression.getType());
}
@Test(expected = ParseException.class)
public void testSwitchExpressionsBeforeJava13() {
ParserTstUtil.parseAndTypeResolveJava("12", loadSource("SwitchExpressions.java"));
@@ -0,0 +1,36 @@
/**
*
* @see <a href="https://openjdk.java.net/jeps/325">JEP 325: Switch Expressions (Preview)</a>
*/
public class SwitchExpressionsYield {
private static final int MONDAY = 1;
private static final int TUESDAY = 2;
private static final int WEDNESDAY = 3;
private static final int THURSDAY = 4;
private static final int FRIDAY = 5;
private static final int SATURDAY = 6;
private static final int SUNDAY = 7;
private static final int SIX = 6;
public static void main(String[] args) {
int day = FRIDAY;
var numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY: yield SwitchExpressionsBreak.SIX;
case TUESDAY : yield 7;
case THURSDAY, SATURDAY : yield 8;
case WEDNESDAY : yield 9;
default : {
int k = day * 2;
int result = f(k);
yield result;
}
};
System.out.printf("NumLetters: %d%n", numLetters);
}
private static int f(int k) {
return k*3;
}
}