[parser] parse yield++, yield = 1 and similar as expression: IDEA-247679

GitOrigin-RevId: a35a7381bf83d3f4f72c1fb2e66763a31a1025c3
This commit is contained in:
Roman Ivanov
2021-10-07 14:55:50 +02:00
committed by intellij-monorepo-bot
parent 4d2cb67ff7
commit fe201e95bc
3 changed files with 53 additions and 3 deletions

View File

@@ -21,6 +21,24 @@ import static com.intellij.lang.PsiBuilderUtil.*;
import static com.intellij.lang.java.parser.JavaParserUtil.*;
public class StatementParser {
private static final TokenSet YIELD_STMT_INDICATOR_TOKENS = TokenSet.create(
JavaTokenType.PLUS, JavaTokenType.MINUS, JavaTokenType.EXCL,
JavaTokenType.SUPER_KEYWORD, JavaTokenType.THIS_KEYWORD,
JavaTokenType.TRUE_KEYWORD, JavaTokenType.FALSE_KEYWORD, JavaTokenType.NULL_KEYWORD,
JavaTokenType.STRING_LITERAL, JavaTokenType.INTEGER_LITERAL, JavaTokenType.DOUBLE_LITERAL,
JavaTokenType.FLOAT_LITERAL, JavaTokenType.LONG_LITERAL, JavaTokenType.CHARACTER_LITERAL,
JavaTokenType.IDENTIFIER, JavaTokenType.SWITCH_KEYWORD, JavaTokenType.NEW_KEYWORD,
JavaTokenType.LPARENTH,
// recovery
JavaTokenType.RBRACE, JavaTokenType.SEMICOLON, JavaTokenType.CASE_KEYWORD
);
private enum BraceMode {
TILL_FIRST, TILL_LAST
}
@@ -245,9 +263,27 @@ public class StatementParser {
}
private static boolean isStmtYieldToken(@NotNull PsiBuilder builder, IElementType tokenType) {
return tokenType == JavaTokenType.IDENTIFIER &&
PsiKeyword.YIELD.equals(builder.getTokenText()) &&
getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_14);
if (!(tokenType == JavaTokenType.IDENTIFIER &&
PsiKeyword.YIELD.equals(builder.getTokenText()) &&
getLanguageLevel(builder).isAtLeast(LanguageLevel.JDK_14))) {
return false;
}
// we prefer to parse it as yield stmt wherever possible (even in incomplete syntax)
PsiBuilder.Marker maybeYieldStmt = builder.mark();
builder.advanceLexer();
IElementType tokenAfterYield = builder.getTokenType();
if (tokenAfterYield == null || YIELD_STMT_INDICATOR_TOKENS.contains(tokenAfterYield)) {
maybeYieldStmt.rollbackTo();
return true;
}
if (JavaTokenType.PLUSPLUS.equals(tokenAfterYield) || JavaTokenType.MINUSMINUS.equals(tokenAfterYield)) {
builder.advanceLexer();
boolean isYieldStmt = !builder.getTokenType().equals(JavaTokenType.SEMICOLON);
maybeYieldStmt.rollbackTo();
return isYieldStmt;
}
maybeYieldStmt.rollbackTo();
return false;
}
private static void skipQualifiedName(PsiBuilder builder) {

View File

@@ -0,0 +1,13 @@
PsiJavaFile:YieldAssignment.java
PsiExpressionStatement
PsiAssignmentExpression:yield = 10
PsiReferenceExpression:yield
PsiReferenceParameterList
<empty list>
PsiIdentifier:yield('yield')
PsiWhiteSpace(' ')
PsiJavaToken:EQ('=')
PsiWhiteSpace(' ')
PsiLiteralExpression:10
PsiJavaToken:INTEGER_LITERAL('10')
PsiJavaToken:SEMICOLON(';')

View File

@@ -37,6 +37,7 @@ public class StatementParserTest extends JavaParsingTestCase {
public void testYieldCallNonQualified() { doParserTest("yield();"); }
public void testYieldCallNonQualifiedWithLambda() { doParserTest("yield(() -> {});"); }
public void testYieldLambda() { doParserTest("yield () -> {};"); }
public void testYieldAssignment() { doParserTest("yield = 10;"); }
public void testYieldCompatibility() { setLanguageLevel(LanguageLevel.JDK_12); doParserTest("yield(2);"); }
public void testContinueNormal0() { doParserTest("continue;"); }