mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-05 01:50:56 +07:00
PY-49990 Parse a match statement without a subject as a type declaration
GitOrigin-RevId: 5c6dc8257973dd0f22a5ef8dd5883628205689a7
This commit is contained in:
committed by
intellij-monorepo-bot
parent
9664a32ba2
commit
0db66c81a5
@@ -147,8 +147,8 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
SyntaxTreeBuilder.Marker mark = myBuilder.mark();
|
||||
myBuilder.remapCurrentToken(PyTokenTypes.MATCH_KEYWORD);
|
||||
myBuilder.advanceLexer();
|
||||
myContext.getExpressionParser().parseExpression();
|
||||
if (!matchToken(PyTokenTypes.COLON)) {
|
||||
boolean followedBySubject = myContext.getExpressionParser().parseExpressionOptional();
|
||||
if (!followedBySubject || !matchToken(PyTokenTypes.COLON)) {
|
||||
mark.rollbackTo();
|
||||
myBuilder.remapCurrentToken(PyTokenTypes.IDENTIFIER);
|
||||
return false;
|
||||
|
||||
@@ -29,10 +29,6 @@ public final class PyMatchStatementFixer extends PyFixer<PyStatement> {
|
||||
if (matchStatement != null) {
|
||||
PsiElement colon = PyPsiUtils.getFirstChildOfType(element, PyTokenTypes.COLON);
|
||||
assert colon != null;
|
||||
if (matchStatement.getSubject() == null) {
|
||||
processor.registerUnresolvedError(colon.getTextOffset());
|
||||
return;
|
||||
}
|
||||
int colonEndOffset = colon.getTextRange().getEndOffset();
|
||||
// It's not enough to check matchStatement.getCaseClauses().isEmpty()
|
||||
boolean hasEmptyBody = colonEndOffset == matchStatement.getTextRange().getEndOffset();
|
||||
@@ -46,7 +42,17 @@ public final class PyMatchStatementFixer extends PyFixer<PyStatement> {
|
||||
return;
|
||||
}
|
||||
|
||||
Couple<PsiElement> pair = findMatchKeywordAndSubject(element);
|
||||
PyTypeDeclarationStatement typeDeclaration = as(element, PyTypeDeclarationStatement.class);
|
||||
// "match:" case
|
||||
if (typeDeclaration != null && isMatchIdentifier(typeDeclaration.getTarget())) {
|
||||
PyAnnotation annotation = typeDeclaration.getAnnotation();
|
||||
if (annotation != null && annotation.getValue() == null) {
|
||||
processor.registerUnresolvedError(annotation.getTextRange().getStartOffset());
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Couple<PsiElement> pair = findMatchKeywordAndSubjectInExpressionStatement(element);
|
||||
PsiElement matchKeyword = pair.getFirst();
|
||||
if (matchKeyword == null) {
|
||||
return;
|
||||
@@ -68,7 +74,7 @@ public final class PyMatchStatementFixer extends PyFixer<PyStatement> {
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private static Couple<PsiElement> findMatchKeywordAndSubject(@NotNull PyStatement statement) {
|
||||
private static Couple<PsiElement> findMatchKeywordAndSubjectInExpressionStatement(@NotNull PyStatement statement) {
|
||||
if (!(statement instanceof PyExpressionStatement)) return Couple.getEmpty();
|
||||
// "match <caret>expr" case
|
||||
PsiElement prevSibling = PyPsiUtils.getPrevNonWhitespaceSiblingOnSameLine(statement);
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
match: case = 42
|
||||
@@ -0,0 +1,14 @@
|
||||
PyFile:PatternMatchingAnnotatedAssignmentLooksLikeIncompleteMatchStatement.py
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: match
|
||||
PsiElement(Py:IDENTIFIER)('match')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: case
|
||||
PsiElement(Py:IDENTIFIER)('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('42')
|
||||
@@ -0,0 +1 @@
|
||||
match:
|
||||
@@ -0,0 +1,8 @@
|
||||
PyFile:PatternMatchingRecoveryMatchWithColonParsedAsVariableTypeDeclaration.py
|
||||
PyTypeDeclarationStatement
|
||||
PyTargetExpression: match
|
||||
PsiElement(Py:IDENTIFIER)('match')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
@@ -1,18 +1,29 @@
|
||||
PyFile:PatternMatchingRecoveryNoSubjectAfterMatch.py
|
||||
PyMatchStatement
|
||||
PsiElement(Py:MATCH_KEYWORD)('match')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyCaseClause
|
||||
PsiElement(Py:CASE_KEYWORD)('case')
|
||||
PsiWhiteSpace(' ')
|
||||
PyLiteralPattern
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('1')
|
||||
PyTypeDeclarationStatement
|
||||
PyTargetExpression: match
|
||||
PsiElement(Py:IDENTIFIER)('match')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiErrorElement:Unexpected indent
|
||||
<empty list>
|
||||
PyExpressionStatement
|
||||
PyReferenceExpression: case
|
||||
PsiElement(Py:IDENTIFIER)('case')
|
||||
PsiErrorElement:End of statement expected
|
||||
<empty list>
|
||||
PsiWhiteSpace(' ')
|
||||
PyTypeDeclarationStatement
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('1')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiErrorElement:Expression expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n ')
|
||||
PsiErrorElement:Unexpected indent
|
||||
<empty list>
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1 @@
|
||||
match: case
|
||||
@@ -0,0 +1,9 @@
|
||||
PyFile:PatternMatchingVariableTypeDeclarationLooksLikeIncompleteMatchStatement.py
|
||||
PyTypeDeclarationStatement
|
||||
PyTargetExpression: match
|
||||
PsiElement(Py:IDENTIFIER)('match')
|
||||
PyAnnotation
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace(' ')
|
||||
PyReferenceExpression: case
|
||||
PsiElement(Py:IDENTIFIER)('case')
|
||||
@@ -1171,6 +1171,21 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest(LanguageLevel.PYTHON310);
|
||||
}
|
||||
|
||||
// PY-49990
|
||||
public void testPatternMatchingVariableTypeDeclarationLooksLikeIncompleteMatchStatement() {
|
||||
doTest(LanguageLevel.PYTHON310);
|
||||
}
|
||||
|
||||
// PY-49990
|
||||
public void testPatternMatchingAnnotatedAssignmentLooksLikeIncompleteMatchStatement() {
|
||||
doTest(LanguageLevel.PYTHON310);
|
||||
}
|
||||
|
||||
// PY-49990
|
||||
public void testPatternMatchingRecoveryMatchWithColonParsedAsVariableTypeDeclaration() {
|
||||
doTest(LanguageLevel.PYTHON310);
|
||||
}
|
||||
|
||||
public void doTest() {
|
||||
doTest(LanguageLevel.PYTHON26);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user