[java] Add Java12 support

This commit is contained in:
Andreas Dangel
2019-03-15 20:51:53 +01:00
parent 8949019da6
commit 65cac51445
6 changed files with 114 additions and 56 deletions

View File

@ -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() )
|
":" (SwitchLabel() ":")* ( BlockStatement() )*
)
)*
/*
LOOKAHEAD(SwitchLabel() "->") SwitchLabeledRule() ( SwitchLabeledRule() )*
|
( SwitchLabeledStatementGroup() )*
*/
"{"
(
LOOKAHEAD( { switchLabeledRuleLookahead(10) } ) ( SwitchLabeledRule() )+
|
(LOOKAHEAD(3) SwitchLabeledStatementGroup() )* (SwitchLabel() ":")*
)
"}"
}
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():

View File

@ -1,21 +1,24 @@
/**
* 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 {
ASTSwitchExpression(int id) {
super(id);
}
public class ASTSwitchExpression extends AbstractJavaNode {
ASTSwitchExpression(int id) {
super(id);
}
ASTSwitchExpression(JavaParser p, int id) {
super(p, id);
}
ASTSwitchExpression(JavaParser p, int id) {
super(p, id);
}
/** Accept the visitor. **/
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
}
/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */

View File

@ -1,21 +1,24 @@
/**
* 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 {
ASTSwitchLabeledRule(int id) {
super(id);
}
public class ASTSwitchLabeledRule extends AbstractJavaNode {
ASTSwitchLabeledRule(int id) {
super(id);
}
ASTSwitchLabeledRule(JavaParser p, int id) {
super(p, id);
}
ASTSwitchLabeledRule(JavaParser p, int id) {
super(p, id);
}
/** Accept the visitor. **/
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
@Override
public Object jjtAccept(JavaParserVisitor visitor, Object data) {
return visitor.visit(this, data);
}
}
/* JavaCC - OriginalChecksum=8b1747ca53f66203ee212a3699a9a2f3 (do not edit this line) */

View File

@ -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

View File

@ -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());
}
}

View File

@ -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();
}
}
}