PY-48008 Improve test coverage of match statements parsing

GitOrigin-RevId: 347185106d7fec7117c31b10fa24b709a3b0da42
This commit is contained in:
Mikhail Golubev
2021-05-31 16:37:41 +03:00
committed by intellij-monorepo-bot
parent 70efe3108f
commit e1b52ae759
12 changed files with 184 additions and 4 deletions

View File

@@ -114,10 +114,7 @@ public class PatternParsing extends Parsing {
private boolean parseClassPattern() {
if (atToken(PyTokenTypes.IDENTIFIER)) {
SyntaxTreeBuilder.Marker mark = myBuilder.mark();
if (!parseReferenceExpression()) {
mark.drop();
return false;
}
parseReferenceExpression();
if (!atToken(PyTokenTypes.LPAR)) {
mark.rollbackTo();
return false;
@@ -316,6 +313,7 @@ public class PatternParsing extends Parsing {
return false;
}
/** @noinspection UnusedReturnValue*/
private boolean parseReferenceExpression() {
if (atToken(PyTokenTypes.IDENTIFIER)) {
SyntaxTreeBuilder.Marker refExpr = myBuilder.mark();

View File

@@ -0,0 +1,7 @@
match x:
case [{'foo': (42]:
pass
case Class([{'foo': True):
pass
case {'foo': [Class(1}:
pass

View File

@@ -0,0 +1,98 @@
PyFile:PatternMatchingRecoveryDanglingBracketsInNestedPatterns.py
PyMatchStatement
PsiElement(Py:MATCH_KEYWORD)('match')
PsiWhiteSpace(' ')
PyReferenceExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyCaseClause
PsiElement(Py:CASE_KEYWORD)('case')
PsiWhiteSpace(' ')
PySequencePattern
PsiElement(Py:LBRACKET)('[')
PyMappingPattern
PsiElement(Py:LBRACE)('{')
PyKeyValuePattern
PyLiteralPattern
PyStringLiteralExpression: foo
PsiElement(Py:SINGLE_QUOTED_STRING)(''foo'')
PsiElement(Py:COLON)(':')
PsiWhiteSpace(' ')
PyGroupPattern
PsiElement(Py:LPAR)('(')
PyLiteralPattern
PyNumericLiteralExpression
PsiElement(Py:INTEGER_LITERAL)('42')
PsiErrorElement:')' expected
<empty list>
PsiElement(Py:RBRACKET)(']')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyStatementList
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')
PsiErrorElement:End of statement expected
<empty list>
PsiWhiteSpace('\n ')
PyCaseClause
PsiElement(Py:CASE_KEYWORD)('case')
PsiWhiteSpace(' ')
PyClassPattern
PyReferenceExpression: Class
PsiElement(Py:IDENTIFIER)('Class')
PyPatternArgumentList
PsiElement(Py:LPAR)('(')
PySequencePattern
PsiElement(Py:LBRACKET)('[')
PyMappingPattern
PsiElement(Py:LBRACE)('{')
PyKeyValuePattern
PyLiteralPattern
PyStringLiteralExpression: foo
PsiElement(Py:SINGLE_QUOTED_STRING)(''foo'')
PsiElement(Py:COLON)(':')
PsiWhiteSpace(' ')
PyLiteralPattern
PyBoolLiteralExpression
PsiElement(Py:TRUE_KEYWORD)('True')
PsiErrorElement:'}' expected
<empty list>
PsiElement(Py:RPAR)(')')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyStatementList
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')
PsiErrorElement:End of statement expected
<empty list>
PsiWhiteSpace('\n ')
PyCaseClause
PsiElement(Py:CASE_KEYWORD)('case')
PsiWhiteSpace(' ')
PyMappingPattern
PsiElement(Py:LBRACE)('{')
PyKeyValuePattern
PyLiteralPattern
PyStringLiteralExpression: foo
PsiElement(Py:SINGLE_QUOTED_STRING)(''foo'')
PsiElement(Py:COLON)(':')
PsiWhiteSpace(' ')
PySequencePattern
PsiElement(Py:LBRACKET)('[')
PyClassPattern
PyReferenceExpression: Class
PsiElement(Py:IDENTIFIER)('Class')
PyPatternArgumentList
PsiElement(Py:LPAR)('(')
PyLiteralPattern
PyNumericLiteralExpression
PsiElement(Py:INTEGER_LITERAL)('1')
PsiErrorElement:')' expected
<empty list>
PsiElement(Py:RBRACE)('}')
PsiElement(Py:COLON)(':')
PsiWhiteSpace('\n ')
PyStatementList
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')

View File

@@ -0,0 +1,3 @@
match x:
pass

View File

@@ -0,0 +1,12 @@
PyFile:PatternMatchingRecoveryMatchStatementWithoutClauses.py
PyMatchStatement
PsiElement(Py:MATCH_KEYWORD)('match')
PsiWhiteSpace(' ')
PyReferenceExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiElement(Py:COLON)(':')
PsiErrorElement:Indent expected
<empty list>
PsiWhiteSpace('\n\n')
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')

View File

@@ -0,0 +1,9 @@
PyFile:PatternMatchingRecoveryMatchStatementWithoutClausesAtEndOfFile.py
PyMatchStatement
PsiElement(Py:MATCH_KEYWORD)('match')
PsiWhiteSpace(' ')
PyReferenceExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiElement(Py:COLON)(':')
PsiErrorElement:Indent expected
<empty list>

View File

@@ -0,0 +1,3 @@
match x:
# comment
pass

View File

@@ -0,0 +1,14 @@
PyFile:PatternMatchingRecoveryMatchStatementWithoutClausesWithComment.py
PyMatchStatement
PsiElement(Py:MATCH_KEYWORD)('match')
PsiWhiteSpace(' ')
PyReferenceExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiElement(Py:COLON)(':')
PsiErrorElement:Indent expected
<empty list>
PsiWhiteSpace('\n ')
PsiComment(Py:END_OF_LINE_COMMENT)('# comment')
PsiWhiteSpace('\n')
PyPassStatement
PsiElement(Py:PASS_KEYWORD)('pass')

View File

@@ -0,0 +1,11 @@
PyFile:PatternMatchingRecoveryMatchStatementWithoutClausesWithCommentAtEndOfFile.py
PyMatchStatement
PsiElement(Py:MATCH_KEYWORD)('match')
PsiWhiteSpace(' ')
PyReferenceExpression: x
PsiElement(Py:IDENTIFIER)('x')
PsiElement(Py:COLON)(':')
PsiErrorElement:Indent expected
<empty list>
PsiWhiteSpace('\n ')
PsiComment(Py:END_OF_LINE_COMMENT)('# comment')

View File

@@ -998,6 +998,26 @@ public class PythonParsingTest extends ParsingTestCase {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingRecoveryDanglingBracketsInNestedPatterns() {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingRecoveryMatchStatementWithoutClauses() {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingRecoveryMatchStatementWithoutClausesWithComment() {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingRecoveryMatchStatementWithoutClausesAtEndOfFile() {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingRecoveryMatchStatementWithoutClausesWithCommentAtEndOfFile() {
doTest(LanguageLevel.PYTHON310);
}
public void testPatternMatchingSingleCapturePattern() {
doTest(LanguageLevel.PYTHON310);
}
@@ -1178,4 +1198,6 @@ public class PythonParsingTest extends ParsingTestCase {
functionToCheck.getStatementList(); //To make sure each function has statement list (does not throw exception)
}
}
}