mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-06 12:54:29 +08:00
Fix one-line error recovery for all things that are using a suite
Fixes https://github.com/davidhalter/jedi/issues/1138.
This commit is contained in:
@@ -40,8 +40,8 @@ class Stack(list):
|
||||
|
||||
def get_tos_first_tokens(self, grammar):
|
||||
tos = self[-1]
|
||||
inv_tokens = {v: k for k, v in grammar.tokens.items()}
|
||||
inv_keywords = {v: k for k, v in grammar.keywords.items()}
|
||||
inv_tokens = dict((v, k) for k, v in grammar.tokens.items())
|
||||
inv_keywords = dict((v, k) for k, v in grammar.keywords.items())
|
||||
dfa, state, nodes = tos
|
||||
|
||||
def check():
|
||||
@@ -51,7 +51,7 @@ class Stack(list):
|
||||
except KeyError:
|
||||
yield tokenize.tok_name[inv_tokens[first]]
|
||||
|
||||
return list(check())
|
||||
return sorted(check())
|
||||
|
||||
|
||||
def token_to_ilabel(grammar, type_, value):
|
||||
|
||||
@@ -160,7 +160,6 @@ class Parser(BaseParser):
|
||||
dfa, state, (type_, nodes) = stack[-1]
|
||||
states, first = dfa
|
||||
|
||||
|
||||
# In Python statements need to end with a newline. But since it's
|
||||
# possible (and valid in Python ) that there's no newline at the
|
||||
# end of a file, we have to recover even if the user doesn't want
|
||||
@@ -198,12 +197,22 @@ class Parser(BaseParser):
|
||||
def current_suite(stack):
|
||||
# For now just discard everything that is not a suite or
|
||||
# file_input, if we detect an error.
|
||||
suite_with_newline = False
|
||||
for index, (symbol, nodes) in reversed(list(enumerate(get_symbol_and_nodes(stack)))):
|
||||
# `suite` can sometimes be only simple_stmt, not stmt.
|
||||
if symbol == 'file_input':
|
||||
break
|
||||
elif symbol == 'suite' and len(nodes) > 1:
|
||||
# suites without an indent in them get discarded.
|
||||
elif symbol == 'suite':
|
||||
if len(nodes) > 1:
|
||||
break
|
||||
elif nodes:
|
||||
suite_with_newline = True
|
||||
# `suite` without an indent are error nodes.
|
||||
continue
|
||||
elif symbol in ('with_stmt', 'if_stmt', 'while_stmt',
|
||||
# 'funcdef', 'classdef',
|
||||
'try_stmt') \
|
||||
and nodes[-1] == ':' and not suite_with_newline:
|
||||
break
|
||||
return index, symbol, nodes
|
||||
|
||||
|
||||
21
test/test_error_recovery.py
Normal file
21
test/test_error_recovery.py
Normal file
@@ -0,0 +1,21 @@
|
||||
from parso import parse
|
||||
|
||||
|
||||
def test_with_stmt():
|
||||
module = parse('with x: f.\na')
|
||||
assert module.children[0].type == 'with_stmt'
|
||||
w, with_item, colon, f = module.children[0].children
|
||||
assert f.type == 'error_node'
|
||||
assert f.get_code(include_prefix=False) == 'f.'
|
||||
|
||||
assert module.children[2].type == 'name'
|
||||
|
||||
|
||||
def test_if_stmt():
|
||||
module = parse('if x: f.')# \nelse: g(
|
||||
if_stmt = module.children[0]
|
||||
assert if_stmt.type == 'if_stmt'
|
||||
if_, test, colon, f = if_stmt.children
|
||||
assert f.type == 'error_node'
|
||||
assert f.children[0].value == 'f'
|
||||
assert f.children[1].value == '.'
|
||||
Reference in New Issue
Block a user