[java] Add Java12 support

This commit is contained in:
Andreas Dangel
2019-03-15 15:29:16 +01:00
committed by Andreas Dangel
parent e1f067ab52
commit 8949019da6
12 changed files with 287 additions and 9 deletions

View File

@ -378,6 +378,21 @@ public class JavaParser {
throwParseException("With JDK 10, 'var' is a restricted local variable type and cannot be used for type declarations!");
}
}
private void checkForMultipleCaseLabels() {
if (jdkVersion < 12) {
throwParseException("Multiple case labels in switch statements are only supported with Java 12");
}
}
private void checkForSwitchRules() {
if (jdkVersion < 12) {
throwParseException("Switch rules in switch statements are only supported with Java 12");
}
}
private void checkForSwitchExpression() {
if (jdkVersion < 12) {
throwParseException("Switch expressions are only supported with Java 12");
}
}
// This is a semantic LOOKAHEAD to determine if we're dealing with an assert
// Note that this can't be replaced with a syntactic lookahead
@ -2006,10 +2021,14 @@ void Expression() :
// https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27
{}
{
LOOKAHEAD((<IDENTIFIER>|LambdaParameters()) "->" ) LambdaExpression()
|
(
ConditionalExpression()
[
LOOKAHEAD(2) AssignmentOperator() Expression()
]
)
}
void AssignmentOperator() :
@ -2140,13 +2159,14 @@ void UnaryExpressionNotPlusMinus() #UnaryExpressionNotPlusMinus((jjtn000.getImag
{
( "~" {jjtThis.setImage("~");} | "!" {jjtThis.setImage("!");} ) UnaryExpression()
/*
* This is really ugly... we are repeting the CastExpression lookahead and full expression...
* This is really ugly... we are repeating the CastExpression lookahead and full expression...
* If we don't the lookahead within CastExpression is ignored, and it simply looks for the expression,
* meaning we can't be explicit as to what can be casted depending on the cast type (primitive or otherwhise)
*/
| LOOKAHEAD("(" (Annotation())* PrimitiveType() ")") CastExpression()
| LOOKAHEAD("(" (Annotation())* Type() ( "&" ReferenceType() )* ")" UnaryExpressionNotPlusMinus()) CastExpression()
| PostfixExpression()
| SwitchExpression()
}
void PostfixExpression() #PostfixExpression((jjtn000.getImage() != null)):
@ -2164,6 +2184,13 @@ void CastExpression() :
| "(" (TypeAnnotation())* Type() ( "&" {checkForBadIntersectionTypesInCasts(); jjtThis.setIntersectionTypes(true);} ReferenceType() )* ")" UnaryExpressionNotPlusMinus()
}
void SwitchExpression() :
{}
{
{checkForSwitchExpression();}
"switch" "(" Expression() ")" "{" SwitchBlock() "}"
}
void PrimaryExpression() :
{}
{
@ -2191,9 +2218,9 @@ void PrimaryPrefix() :
Literal()
| LOOKAHEAD(2) "this" {jjtThis.setUsesThisModifier();}
| "super" {jjtThis.setUsesSuperModifier();}
| LOOKAHEAD( <IDENTIFIER> "->" ) LambdaExpression()
| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression()
| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression()
//| LOOKAHEAD( <IDENTIFIER> "->" ) LambdaExpression()
//| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression()
//| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression()
| LOOKAHEAD(3) "(" Expression() ")"
| AllocationExpression()
| LOOKAHEAD( ResultType() "." "class" ) ResultType() "." "class"
@ -2415,20 +2442,51 @@ void StatementExpression() :
PostfixExpression()
}
void SwitchStatement() :
void SwitchStatement():
{}
{
"switch" "(" Expression() ")" "{"
( SwitchLabel() ( BlockStatement() )* )*
SwitchBlock()
"}"
}
void SwitchBlock() #void :
{}
{
(
SwitchLabel()
(
"->" ( Expression() ";" | Block() | ThrowStatement() )
|
":" (SwitchLabel() ":")* ( BlockStatement() )*
)
)*
/*
LOOKAHEAD(SwitchLabel() "->") SwitchLabeledRule() ( SwitchLabeledRule() )*
|
( SwitchLabeledStatementGroup() )*
*/
}
void SwitchLabeledStatementGroup() #void:
{}
{
SwitchLabel() ":" (SwitchLabel() ":")* ( BlockStatement() )*
}
void SwitchLabel() :
{}
{
"case" Expression() ":"
"case" ConditionalExpression() ({checkForMultipleCaseLabels();} "," ConditionalExpression())*
|
"default" {jjtThis.setDefault();} ":"
"default" {jjtThis.setDefault();}
}
void SwitchLabeledRule():
{}
{
{checkForSwitchRules();}
SwitchLabel() "->" ( Expression() ";" | Block() | ThrowStatement() )
}
void IfStatement() :

View File

@ -25,7 +25,8 @@ public class JavaLanguageModule extends BaseLanguageModule {
addVersion("1.8", new JavaLanguageHandler(8), false);
addVersion("9", new JavaLanguageHandler(9), false);
addVersion("10", new JavaLanguageHandler(10), false);
addVersion("11", new JavaLanguageHandler(11), true);
addVersion("11", new JavaLanguageHandler(11), false);
addVersion("12", new JavaLanguageHandler(12), true);
}
}

View File

@ -0,0 +1,21 @@
/* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package net.sourceforge.pmd.lang.java.ast;
public
class ASTSwitchExpression extends AbstractJavaNode {
ASTSwitchExpression(int id) {
super(id);
}
ASTSwitchExpression(JavaParser p, int id) {
super(p, id);
}
/** Accept the visitor. **/
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
}
/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */

View File

@ -0,0 +1,21 @@
/* Generated By:JJTree: Do not edit this line. ASTSwitchLabeledRule.java Version 4.3 */
/* JavaCCOptions:MULTI=true,NODE_USES_PARSER=true,VISITOR=true,TRACK_TOKENS=true,NODE_PREFIX=AST,NODE_EXTENDS=,NODE_FACTORY=,SUPPORT_CLASS_VISIBILITY_PUBLIC=true */
package net.sourceforge.pmd.lang.java.ast;
public
class ASTSwitchLabeledRule extends AbstractJavaNode {
ASTSwitchLabeledRule(int id) {
super(id);
}
ASTSwitchLabeledRule(JavaParser p, int id) {
super(p, id);
}
/** Accept the visitor. **/
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
}
/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */

View File

@ -868,4 +868,16 @@ public class JavaParserDecoratedVisitor implements JavaParserVisitor {
visitor.visit(node, data);
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchLabeledRule node, Object data) {
visitor.visit(node, data);
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchExpression node, Object data) {
visitor.visit(node, data);
return visit((JavaNode) node, data);
}
}

View File

@ -600,4 +600,14 @@ public class JavaParserVisitorAdapter implements JavaParserVisitor {
public Object visit(ASTModuleName node, Object data) {
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchLabeledRule node, Object data) {
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchExpression node, Object data) {
return visit((JavaNode) node, data);
}
}

View File

@ -730,4 +730,14 @@ public class JavaParserVisitorDecorator implements JavaParserControllessVisitor
public Object visit(ASTModuleName node, Object data) {
return visitor.visit(node, data);
}
@Override
public Object visit(ASTSwitchLabeledRule node, Object data) {
return visitor.visit(node, data);
}
@Override
public Object visit(ASTSwitchExpression node, Object data) {
return visitor.visit(node, data);
}
}

View File

@ -674,4 +674,14 @@ public abstract class AbstractJavaRule extends AbstractRule implements JavaParse
public Object visit(ASTModuleName node, Object data) {
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchLabeledRule node, Object data) {
return visit((JavaNode) node, data);
}
@Override
public Object visit(ASTSwitchExpression node, Object data) {
return visit((JavaNode) node, data);
}
}

View File

@ -0,0 +1,63 @@
/**
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
*/
package net.sourceforge.pmd.lang.java.ast;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import org.apache.commons.io.IOUtils;
import org.junit.Assert;
import org.junit.Test;
import net.sourceforge.pmd.lang.ast.ParseException;
import net.sourceforge.pmd.lang.java.ParserTstUtil;
public class Java12Test {
private static String loadSource(String name) {
try {
return IOUtils.toString(Java10Test.class.getResourceAsStream("jdkversiontests/java12/" + name),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}
}
@Test(expected = ParseException.class)
public void testMultipleCaseLabelsJava11() {
ParserTstUtil.parseAndTypeResolveJava("11", loadSource("MultipleCaseLabels.java"));
}
@Test
public void testMultipleCaseLabels() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
loadSource("MultipleCaseLabels.java"));
Assert.assertNotNull(compilationUnit);
}
@Test(expected = ParseException.class)
public void testSwitchRulesJava11() {
ParserTstUtil.parseAndTypeResolveJava("11", loadSource("SwitchRules.java"));
}
@Test
public void testSwitchRules() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
loadSource("SwitchRules.java"));
Assert.assertNotNull(compilationUnit);
}
@Test(expected = ParseException.class)
public void testSwitchExpressionsJava11() {
ParserTstUtil.parseAndTypeResolveJava("11", loadSource("SwitchExpressions.java"));
}
@Test
public void testSwitchExpressions() {
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
loadSource("SwitchExpressions.java"));
Assert.assertNotNull(compilationUnit);
}
}

View File

@ -0,0 +1,21 @@
public class MultipleCaseLabels {
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;
public static void main(String[] args) {
int day = THURSDAY;
switch (day) {
case MONDAY, FRIDAY, SUNDAY: System.out.println(" 6"); break;
case TUESDAY : System.out.println(" 7"); break;
case THURSDAY, SATURDAY : System.out.println(" 8"); break;
case WEDNESDAY : System.out.println(" 9"); break;
}
}
}

View File

@ -0,0 +1,31 @@
public class SwitchExpressions {
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;
public static void main(String[] args) {
int day = FRIDAY;
int numLetters = switch (day) {
case MONDAY, FRIDAY, SUNDAY -> 6;
case TUESDAY -> 7;
case THURSDAY, SATURDAY -> 8;
case WEDNESDAY -> 9;
default -> {
int k = day * 2;
int result = f(k);
break result;
}
};
System.out.printf("NumLetters: %d%n", numLetters);
}
private static int f(int k) {
return k*3;
}
}

View File

@ -0,0 +1,20 @@
public class SwitchRules {
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;
public static void main(String[] args) {
int day = WEDNESDAY;
switch (day) {
case MONDAY, FRIDAY, SUNDAY -> System.out.println(" 6");
case TUESDAY -> System.out.println(" 7");
case THURSDAY, SATURDAY -> System.out.println(" 8");
case WEDNESDAY -> System.out.println(" 9");
}
}
}