[java] Add Java12 support
This commit is contained in:
@ -383,6 +383,15 @@ public class JavaParser {
|
||||
throwParseException("Multiple case labels in switch statements are only supported with Java 12");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Keeps track during tree construction, whether we are currently building a switch label.
|
||||
* A switch label must not contain a LambdaExpression.
|
||||
* Unfortunately, we have added LambdaExpression as part of PrimaryPrefix, which is wrong.
|
||||
* To keep compatibility, this flag is used, whether a LambdaExpression should be parsed
|
||||
* in PrimaryPrefix.
|
||||
* See also comment at #Expression().
|
||||
*/
|
||||
private boolean inSwitchLabel = false;
|
||||
private void checkForSwitchRules() {
|
||||
if (jdkVersion < 12) {
|
||||
throwParseException("Switch rules in switch statements are only supported with Java 12");
|
||||
@ -424,6 +433,26 @@ public class JavaParser {
|
||||
return getToken(1).kind == IDENTIFIER && getToken(1).image.equals(keyword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Semantic lookahead needed to distinguish between switch rules
|
||||
* and switch statement. Using the syntactic lookahead for SwitchLabel()
|
||||
* does not work, during lookahead the javacode is not executed, so
|
||||
* that "->" is already consumed as a LambdaExpression, when it is actually
|
||||
* part of the switch rule. See also #inSwitchLabel.
|
||||
*/
|
||||
private boolean switchLabeledRuleLookahead(int maxTokens) {
|
||||
int pos = 0;
|
||||
|
||||
while (pos < maxTokens) {
|
||||
Token token = getToken(pos);
|
||||
pos++;
|
||||
|
||||
if (token.kind == COLON) return false;
|
||||
if (token.kind == LAMBDA) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public Map<Integer, String> getSuppressMap() {
|
||||
return token_source.getSuppressMap();
|
||||
}
|
||||
@ -2019,16 +2048,15 @@ void Expression() :
|
||||
// separated from the AssignmentExpression production. Their use is restricted
|
||||
// to method and constructor argument, cast operand, and the RHS of assignments.
|
||||
// https://docs.oracle.com/javase/specs/jls/se9/html/jls-15.html#jls-15.27
|
||||
//
|
||||
// To prevent LambdaExpressions in switch labels, the field #inSwitchLabel is used
|
||||
// as a workaround.
|
||||
{}
|
||||
{
|
||||
LOOKAHEAD((<IDENTIFIER>|LambdaParameters()) "->" ) LambdaExpression()
|
||||
|
|
||||
(
|
||||
ConditionalExpression()
|
||||
[
|
||||
LOOKAHEAD(2) AssignmentOperator() Expression()
|
||||
]
|
||||
)
|
||||
}
|
||||
|
||||
void AssignmentOperator() :
|
||||
@ -2188,7 +2216,7 @@ void SwitchExpression() :
|
||||
{}
|
||||
{
|
||||
{checkForSwitchExpression();}
|
||||
"switch" "(" Expression() ")" "{" SwitchBlock() "}"
|
||||
"switch" "(" Expression() ")" SwitchBlock()
|
||||
}
|
||||
|
||||
void PrimaryExpression() :
|
||||
@ -2218,9 +2246,9 @@ void PrimaryPrefix() :
|
||||
Literal()
|
||||
| LOOKAHEAD(2) "this" {jjtThis.setUsesThisModifier();}
|
||||
| "super" {jjtThis.setUsesSuperModifier();}
|
||||
//| LOOKAHEAD( <IDENTIFIER> "->" ) LambdaExpression()
|
||||
//| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->" ) LambdaExpression()
|
||||
//| LOOKAHEAD( FormalParameters() "->" ) LambdaExpression()
|
||||
| LOOKAHEAD( <IDENTIFIER> "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| LOOKAHEAD( "(" VariableDeclaratorId() ( "," VariableDeclaratorId() )* ")" "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| LOOKAHEAD( FormalParameters() "->", {!inSwitchLabel} ) LambdaExpression()
|
||||
| LOOKAHEAD(3) "(" Expression() ")"
|
||||
| AllocationExpression()
|
||||
| LOOKAHEAD( ResultType() "." "class" ) ResultType() "." "class"
|
||||
@ -2445,41 +2473,37 @@ void StatementExpression() :
|
||||
void SwitchStatement():
|
||||
{}
|
||||
{
|
||||
"switch" "(" Expression() ")" "{"
|
||||
SwitchBlock()
|
||||
"}"
|
||||
"switch" "(" Expression() ")" SwitchBlock()
|
||||
}
|
||||
|
||||
void SwitchBlock() #void :
|
||||
{}
|
||||
{
|
||||
"{"
|
||||
(
|
||||
SwitchLabel()
|
||||
(
|
||||
"->" ( Expression() ";" | Block() | ThrowStatement() )
|
||||
LOOKAHEAD( { switchLabeledRuleLookahead(10) } ) ( SwitchLabeledRule() )+
|
||||
|
|
||||
":" (SwitchLabel() ":")* ( BlockStatement() )*
|
||||
(LOOKAHEAD(3) SwitchLabeledStatementGroup() )* (SwitchLabel() ":")*
|
||||
)
|
||||
)*
|
||||
/*
|
||||
LOOKAHEAD(SwitchLabel() "->") SwitchLabeledRule() ( SwitchLabeledRule() )*
|
||||
|
|
||||
( SwitchLabeledStatementGroup() )*
|
||||
*/
|
||||
"}"
|
||||
}
|
||||
|
||||
void SwitchLabeledStatementGroup() #void:
|
||||
{}
|
||||
{
|
||||
SwitchLabel() ":" (SwitchLabel() ":")* ( BlockStatement() )*
|
||||
(SwitchLabel() ":")+ ( BlockStatement() )+
|
||||
}
|
||||
|
||||
void SwitchLabel() :
|
||||
{}
|
||||
{
|
||||
"case" ConditionalExpression() ({checkForMultipleCaseLabels();} "," ConditionalExpression())*
|
||||
{ inSwitchLabel = true; }
|
||||
(
|
||||
"case" ( ConditionalExpression() #Expression ) ({checkForMultipleCaseLabels();} "," ( ConditionalExpression() #Expression ) )*
|
||||
|
|
||||
"default" {jjtThis.setDefault();}
|
||||
)
|
||||
{ inSwitchLabel = false; }
|
||||
}
|
||||
|
||||
void SwitchLabeledRule():
|
||||
|
@ -1,9 +1,13 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/* 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 {
|
||||
public class ASTSwitchExpression extends AbstractJavaNode {
|
||||
ASTSwitchExpression(int id) {
|
||||
super(id);
|
||||
}
|
||||
@ -12,8 +16,7 @@ class ASTSwitchExpression extends AbstractJavaNode {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
@ -1,9 +1,13 @@
|
||||
/**
|
||||
* BSD-style license; for more info see http://pmd.sourceforge.net/license.html
|
||||
*/
|
||||
|
||||
/* 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 {
|
||||
public class ASTSwitchLabeledRule extends AbstractJavaNode {
|
||||
ASTSwitchLabeledRule(int id) {
|
||||
super(id);
|
||||
}
|
||||
@ -12,8 +16,7 @@ class ASTSwitchLabeledRule extends AbstractJavaNode {
|
||||
super(p, id);
|
||||
}
|
||||
|
||||
|
||||
/** Accept the visitor. **/
|
||||
@Override
|
||||
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
|
||||
return visitor.visit(this, data);
|
||||
}
|
||||
|
@ -26,8 +26,8 @@ public class LanguageVersionDiscovererTest {
|
||||
File javaFile = new File("/path/to/MyClass.java");
|
||||
|
||||
LanguageVersion languageVersion = discoverer.getDefaultLanguageVersionForFile(javaFile);
|
||||
assertEquals("LanguageVersion must be Java 11 !",
|
||||
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"), languageVersion);
|
||||
assertEquals("LanguageVersion must be Java 12 !",
|
||||
LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("12"), languageVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -48,7 +48,7 @@ public class LanguageVersionDiscovererTest {
|
||||
public void testLanguageVersionDiscoverer() {
|
||||
PMDConfiguration configuration = new PMDConfiguration();
|
||||
LanguageVersionDiscoverer languageVersionDiscoverer = configuration.getLanguageVersionDiscoverer();
|
||||
assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("11"),
|
||||
assertEquals("Default Java version", LanguageRegistry.getLanguage(JavaLanguageModule.NAME).getVersion("12"),
|
||||
languageVersionDiscoverer
|
||||
.getDefaultLanguageVersion(LanguageRegistry.getLanguage(JavaLanguageModule.NAME)));
|
||||
configuration
|
||||
|
@ -34,6 +34,11 @@ public class Java12Test {
|
||||
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
|
||||
loadSource("MultipleCaseLabels.java"));
|
||||
Assert.assertNotNull(compilationUnit);
|
||||
ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class);
|
||||
Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression);
|
||||
Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabel);
|
||||
ASTSwitchLabel switchLabel = switchStatement.getFirstChildOfType(ASTSwitchLabel.class);
|
||||
Assert.assertEquals(3, switchLabel.findChildrenOfType(ASTExpression.class).size());
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
@ -46,6 +51,23 @@ public class Java12Test {
|
||||
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
|
||||
loadSource("SwitchRules.java"));
|
||||
Assert.assertNotNull(compilationUnit);
|
||||
ASTSwitchStatement switchStatement = compilationUnit.getFirstDescendantOfType(ASTSwitchStatement.class);
|
||||
Assert.assertTrue(switchStatement.jjtGetChild(0) instanceof ASTExpression);
|
||||
Assert.assertTrue(switchStatement.jjtGetChild(1) instanceof ASTSwitchLabeledRule);
|
||||
ASTSwitchLabeledRule switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(1);
|
||||
Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren());
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel);
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTExpression);
|
||||
|
||||
switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(4);
|
||||
Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren());
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel);
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTBlock);
|
||||
|
||||
switchLabeledRule = (ASTSwitchLabeledRule) switchStatement.jjtGetChild(5);
|
||||
Assert.assertEquals(2, switchLabeledRule.jjtGetNumChildren());
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(0) instanceof ASTSwitchLabel);
|
||||
Assert.assertTrue(switchLabeledRule.jjtGetChild(1) instanceof ASTThrowStatement);
|
||||
}
|
||||
|
||||
@Test(expected = ParseException.class)
|
||||
@ -58,6 +80,11 @@ public class Java12Test {
|
||||
ASTCompilationUnit compilationUnit = ParserTstUtil.parseAndTypeResolveJava("12",
|
||||
loadSource("SwitchExpressions.java"));
|
||||
Assert.assertNotNull(compilationUnit);
|
||||
|
||||
ASTSwitchExpression switchExpression = compilationUnit.getFirstDescendantOfType(ASTSwitchExpression.class);
|
||||
Assert.assertEquals(6, switchExpression.jjtGetNumChildren());
|
||||
Assert.assertTrue(switchExpression.jjtGetChild(0) instanceof ASTExpression);
|
||||
Assert.assertEquals(5, switchExpression.findChildrenOfType(ASTSwitchLabeledRule.class).size());
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -14,7 +14,8 @@ public class SwitchRules {
|
||||
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");
|
||||
case WEDNESDAY -> { System.out.println(" 9"); }
|
||||
default -> throw new IllegalArgumentException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user