mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
Better error recovery for lines with single 'class' or 'def' keywords and normal functions defined below
This commit is contained in:
@@ -654,7 +654,7 @@ PARSE.expected.colon.or.rbracket=':' or ']' expected
|
||||
PARSE.expected.comma.or.rpar=',' or ')' expected
|
||||
PARSE.expected.else='else' expected
|
||||
|
||||
PARSE.expected.func.name=function name expected
|
||||
PARSE.expected.identifier=Identifier expected
|
||||
PARSE.expected.comma.lpar.rpar=',' or '(' or ')' expected
|
||||
PARSE.expected.statement.break=Statement break expected
|
||||
PARSE.expected.@.or.def='@' or 'def' expected
|
||||
|
||||
@@ -45,7 +45,7 @@ public class FunctionParsing extends Parsing {
|
||||
|
||||
protected void parseFunctionInnards(PsiBuilder.Marker functionMarker) {
|
||||
myBuilder.advanceLexer();
|
||||
checkMatchesOrSkip(PyTokenTypes.IDENTIFIER, message("PARSE.expected.func.name"));
|
||||
parseIdentifierOrSkip();
|
||||
parseParameterList();
|
||||
parseReturnTypeAnnotation();
|
||||
checkMatches(PyTokenTypes.COLON, message("PARSE.expected.colon"));
|
||||
|
||||
@@ -18,7 +18,9 @@ package com.jetbrains.python.parsing;
|
||||
import com.intellij.lang.PsiBuilder;
|
||||
import com.intellij.openapi.diagnostic.Logger;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import com.jetbrains.python.PyBundle;
|
||||
import com.jetbrains.python.PyElementTypes;
|
||||
import com.jetbrains.python.PyTokenTypes;
|
||||
import com.jetbrains.python.psi.PyElementType;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
@@ -61,15 +63,19 @@ public class Parsing {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean checkMatchesOrSkip(final IElementType token, final String message) {
|
||||
if (myBuilder.getTokenType() == token) {
|
||||
protected boolean parseIdentifierOrSkip() {
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.IDENTIFIER) {
|
||||
myBuilder.advanceLexer();
|
||||
return true;
|
||||
}
|
||||
PsiBuilder.Marker mark = myBuilder.mark();
|
||||
myBuilder.advanceLexer();
|
||||
mark.error(message);
|
||||
return false;
|
||||
else {
|
||||
final PsiBuilder.Marker nameExpected = myBuilder.mark();
|
||||
if (myBuilder.getTokenType() != PyTokenTypes.STATEMENT_BREAK) {
|
||||
myBuilder.advanceLexer();
|
||||
}
|
||||
nameExpected.error(PyBundle.message("PARSE.expected.identifier"));
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected void assertCurrentToken(final PyElementType tokenType) {
|
||||
@@ -95,7 +101,7 @@ public class Parsing {
|
||||
protected boolean matchToken(final IElementType tokenType) {
|
||||
if (myBuilder.getTokenType() == tokenType) {
|
||||
myBuilder.advanceLexer();
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -792,7 +792,7 @@ public class StatementParsing extends Parsing implements ITokenTypeRemapper {
|
||||
public void parseClassDeclaration(PsiBuilder.Marker classMarker, ParsingScope scope) {
|
||||
assertCurrentToken(PyTokenTypes.CLASS_KEYWORD);
|
||||
myBuilder.advanceLexer();
|
||||
checkMatchesOrSkip(PyTokenTypes.IDENTIFIER, IDENTIFIER_EXPECTED);
|
||||
parseIdentifierOrSkip();
|
||||
if (myBuilder.getTokenType() == PyTokenTypes.LPAR) {
|
||||
getExpressionParser().parseArgumentList();
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@ PyFile:KeywordAsFunctionName.py
|
||||
PyFunction('null')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiErrorElement:function name expected
|
||||
PsiErrorElement:Identifier expected
|
||||
PsiElement(Py:FROM_KEYWORD)('from')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
class
|
||||
|
||||
|
||||
def foo():
|
||||
pass
|
||||
@@ -0,0 +1,25 @@
|
||||
PyFile:SingleClassBeforeFunction.py
|
||||
PyClass: null
|
||||
PsiElement(Py:CLASS_KEYWORD)('class')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PyArgumentList
|
||||
<empty list>
|
||||
PsiErrorElement:Colon expected
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n\n\n')
|
||||
PyStatementList
|
||||
PsiErrorElement:Indent expected
|
||||
<empty list>
|
||||
PyFunction('foo')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('foo')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyPassStatement
|
||||
PsiElement(Py:PASS_KEYWORD)('pass')
|
||||
@@ -0,0 +1,5 @@
|
||||
def
|
||||
|
||||
|
||||
def bar():
|
||||
x = 1
|
||||
@@ -0,0 +1,31 @@
|
||||
PyFile:SingleDefBeforeFunction.py
|
||||
PyFunction('null')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiErrorElement:Identifier expected
|
||||
<empty list>
|
||||
PsiErrorElement:'(' expected
|
||||
<empty list>
|
||||
PyParameterList
|
||||
<empty list>
|
||||
PsiWhiteSpace('\n\n\n')
|
||||
PyStatementList
|
||||
PsiErrorElement:Indent expected
|
||||
<empty list>
|
||||
PyFunction('bar')
|
||||
PsiElement(Py:DEF_KEYWORD)('def')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:IDENTIFIER)('bar')
|
||||
PyParameterList
|
||||
PsiElement(Py:LPAR)('(')
|
||||
PsiElement(Py:RPAR)(')')
|
||||
PsiElement(Py:COLON)(':')
|
||||
PsiWhiteSpace('\n ')
|
||||
PyStatementList
|
||||
PyAssignmentStatement
|
||||
PyTargetExpression: x
|
||||
PsiElement(Py:IDENTIFIER)('x')
|
||||
PsiWhiteSpace(' ')
|
||||
PsiElement(Py:EQ)('=')
|
||||
PsiWhiteSpace(' ')
|
||||
PyNumericLiteralExpression
|
||||
PsiElement(Py:INTEGER_LITERAL)('1')
|
||||
@@ -455,6 +455,14 @@ public class PythonParsingTest extends ParsingTestCase {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSingleDefBeforeFunction() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void testSingleClassBeforeFunction() {
|
||||
doTest();
|
||||
}
|
||||
|
||||
public void doTest(LanguageLevel languageLevel) {
|
||||
LanguageLevel prev = myLanguageLevel;
|
||||
myLanguageLevel = languageLevel;
|
||||
|
||||
Reference in New Issue
Block a user