From f51943380f9fe117dcbb92c24568335a909a59bb Mon Sep 17 00:00:00 2001 From: Dmitry Jemerov Date: Thu, 13 Dec 2012 20:56:31 +0100 Subject: [PATCH] parse ellipsis only in the context where it can actually be used (PY-7763) --- .../python/parsing/ExpressionParsing.java | 30 ++++++++++------- python/testData/psi/EllipsisAsStatement.py | 5 +++ python/testData/psi/EllipsisAsStatement.txt | 33 +++++++++++++++++++ .../jetbrains/python/PythonParsingTest.java | 4 +++ 4 files changed, 61 insertions(+), 11 deletions(-) create mode 100644 python/testData/psi/EllipsisAsStatement.py create mode 100644 python/testData/psi/EllipsisAsStatement.txt diff --git a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java index 47971220e18e..31681c8375e9 100644 --- a/python/src/com/jetbrains/python/parsing/ExpressionParsing.java +++ b/python/src/com/jetbrains/python/parsing/ExpressionParsing.java @@ -72,15 +72,6 @@ public class ExpressionParsing extends Parsing { parseReprExpression(myBuilder); return true; } - else if (firstToken == PyTokenTypes.DOT) { - final PsiBuilder.Marker maybeEllipsis = myBuilder.mark(); - myBuilder.advanceLexer(); - if (matchToken(PyTokenTypes.DOT) && matchToken(PyTokenTypes.DOT)) { - maybeEllipsis.done(PyElementTypes.NONE_LITERAL_EXPRESSION); - return true; - } - maybeEllipsis.rollbackTo(); - } return false; } @@ -334,7 +325,9 @@ public class ExpressionParsing extends Parsing { parseSliceEnd(expr, sliceItemStart); } else { - parseSingleExpression(false); + if (!parseEllipsis()) { + parseSingleExpression(false); + } if (atToken(PyTokenTypes.COLON)) { sliceOrTupleStart.drop(); parseSliceEnd(expr, sliceItemStart); @@ -378,6 +371,19 @@ public class ExpressionParsing extends Parsing { return true; } + private boolean parseEllipsis() { + if (atToken(PyTokenTypes.DOT)) { + final PsiBuilder.Marker maybeEllipsis = myBuilder.mark(); + myBuilder.advanceLexer(); + if (matchToken(PyTokenTypes.DOT) && matchToken(PyTokenTypes.DOT)) { + maybeEllipsis.done(PyElementTypes.NONE_LITERAL_EXPRESSION); + return true; + } + maybeEllipsis.rollbackTo(); + } + return false; + } + private static TokenSet BRACKET_OR_COMMA = TokenSet.create(PyTokenTypes.RBRACKET, PyTokenTypes.COMMA); private static TokenSet BRACKET_COLON_COMMA = TokenSet.create(PyTokenTypes.RBRACKET, PyTokenTypes.COLON, PyTokenTypes.COMMA); @@ -420,7 +426,9 @@ public class ExpressionParsing extends Parsing { while (atToken(PyTokenTypes.COMMA)) { nextToken(); PsiBuilder.Marker sliceItemStart = myBuilder.mark(); - parseTestExpression(false, false); + if (!parseEllipsis()) { + parseTestExpression(false, false); + } if (matchToken(PyTokenTypes.COLON)) { inSlice = true; parseTestExpression(false, false); diff --git a/python/testData/psi/EllipsisAsStatement.py b/python/testData/psi/EllipsisAsStatement.py new file mode 100644 index 000000000000..e1efdfe13f1e --- /dev/null +++ b/python/testData/psi/EllipsisAsStatement.py @@ -0,0 +1,5 @@ +def a(): + ... # <- highlighted as "Statement seems to have no effect" + pass + +a() \ No newline at end of file diff --git a/python/testData/psi/EllipsisAsStatement.txt b/python/testData/psi/EllipsisAsStatement.txt new file mode 100644 index 000000000000..dbe4c271bd31 --- /dev/null +++ b/python/testData/psi/EllipsisAsStatement.txt @@ -0,0 +1,33 @@ +PyFile:EllipsisAsStatement.py + PyFunction('a') + PsiElement(Py:DEF_KEYWORD)('def') + PsiWhiteSpace(' ') + PsiElement(Py:IDENTIFIER)('a') + PyParameterList + PsiElement(Py:LPAR)('(') + PsiElement(Py:RPAR)(')') + PsiElement(Py:COLON)(':') + PsiWhiteSpace('\n ') + PyStatementList + PsiElement(Py:DOT)('.') + PsiErrorElement:Statement expected, found Py:DOT + + PsiElement(Py:DOT)('.') + PsiErrorElement:Statement expected, found Py:DOT + + PsiElement(Py:DOT)('.') + PsiErrorElement:Statement expected, found Py:DOT + + PsiWhiteSpace(' ') + PsiComment(Py:END_OF_LINE_COMMENT)('# <- highlighted as "Statement seems to have no effect"') + PsiWhiteSpace('\n ') + PyPassStatement + PsiElement(Py:PASS_KEYWORD)('pass') + PsiWhiteSpace('\n\n') + PyExpressionStatement + PyCallExpression: a + PyReferenceExpression: a + PsiElement(Py:IDENTIFIER)('a') + PyArgumentList + PsiElement(Py:LPAR)('(') + PsiElement(Py:RPAR)(')') \ No newline at end of file diff --git a/python/testSrc/com/jetbrains/python/PythonParsingTest.java b/python/testSrc/com/jetbrains/python/PythonParsingTest.java index 17513fd7c48f..283ea51cc1e4 100644 --- a/python/testSrc/com/jetbrains/python/PythonParsingTest.java +++ b/python/testSrc/com/jetbrains/python/PythonParsingTest.java @@ -356,6 +356,10 @@ public class PythonParsingTest extends ParsingTestCase { doTest(); } + public void testEllipsisAsStatement() { // PY-7763 + doTest(); + } + public void doTest(LanguageLevel languageLevel) { LanguageLevel prev = myLanguageLevel; myLanguageLevel = languageLevel;