diff --git a/pmd-java/etc/grammar/Java.jjt b/pmd-java/etc/grammar/Java.jjt index 80186c015e..9b881d591f 100644 --- a/pmd-java/etc/grammar/Java.jjt +++ b/pmd-java/etc/grammar/Java.jjt @@ -502,6 +502,52 @@ public class JavaParser { return getToken(1).kind == IDENTIFIER && getToken(1).image.equals(keyword); } + /** + * True if we're in a switch block, one precondition for parsing a yield + * statement. + */ + private boolean inSwitchBlock = false; + + private boolean isYieldStart() { + return inSwitchBlock && isJava13PreviewOr14() + && isKeyword("yield") + && mayStartExprAfterYield(2); + } + + private boolean mayStartExprAfterYield(final int offset) { + // based off of https://hg.openjdk.java.net/jdk/jdk/file/bc3da0226ffa/src/jdk.compiler/share/classes/com/sun/tools/javac/parser/JavacParser.java#l2580 + // please don't sue me + Token token = getToken(offset); + if (token == null) return false; // eof + switch (token.kind) { + case PLUS: case MINUS: case STRING_LITERAL: case CHARACTER_LITERAL: + case INTEGER_LITERAL: case FLOATING_POINT_LITERAL: case HEX_FLOATING_POINT_LITERAL: + case NULL: case IDENTIFIER: case TRUE: case FALSE: + case NEW: case SWITCH: case THIS: case SUPER: + return true; + case INCR: case DECR: + return getToken(offset + 1).kind != SEMICOLON; // eg yield++; + case LPAREN: + int lookahead = offset + 1; + int balance = 1; + Token t; + while ((t = getToken(lookahead)) != null && balance > 0) { + switch (t.kind) { + case LPAREN: balance++; break; + case RPAREN: balance--; break; + case COMMA: if (balance == 1) return false; // a method call, eg yield(1, 2); + } + lookahead++; + } + // lambda: yield () -> {}; + // method call: yield (); + return lookahead != offset + 2 // ie () + || t.kind == ARROW; + default: + return false; + } + } + private boolean shouldStartStatementInSwitch() { switch (getToken(1).kind) { case _DEFAULT: @@ -1900,8 +1946,9 @@ void SwitchStatement(): } void SwitchBlock() #void : -{} +{boolean prevInSwitchBlock = inSwitchBlock;} { + {inSwitchBlock = true;} "{" ( SwitchLabel() @@ -1916,6 +1963,7 @@ void SwitchBlock() #void : ) )? "}" + {inSwitchBlock = prevInSwitchBlock;} } void SwitchLabeledRule() #void :