mirror of
https://github.com/davidhalter/parso.git
synced 2025-12-06 21:04:29 +08:00
Fix indentation issues with backslashes and def error recovery
This commit is contained in:
@@ -23,6 +23,7 @@ _INDENTATION_TOKENS = 'INDENT', 'ERROR_DEDENT', 'DEDENT'
|
|||||||
|
|
||||||
NEWLINE = PythonTokenTypes.NEWLINE
|
NEWLINE = PythonTokenTypes.NEWLINE
|
||||||
DEDENT = PythonTokenTypes.DEDENT
|
DEDENT = PythonTokenTypes.DEDENT
|
||||||
|
NAME = PythonTokenTypes.NAME
|
||||||
ERROR_DEDENT = PythonTokenTypes.ERROR_DEDENT
|
ERROR_DEDENT = PythonTokenTypes.ERROR_DEDENT
|
||||||
ENDMARKER = PythonTokenTypes.ENDMARKER
|
ENDMARKER = PythonTokenTypes.ENDMARKER
|
||||||
|
|
||||||
@@ -173,12 +174,6 @@ def _func_or_class_has_suite(node):
|
|||||||
return node.type in ('classdef', 'funcdef') and node.children[-1].type == 'suite'
|
return node.type in ('classdef', 'funcdef') and node.children[-1].type == 'suite'
|
||||||
|
|
||||||
|
|
||||||
def _get_suite_func_or_class_parent(node):
|
|
||||||
while node.parent.type in ('funcdef', 'classdef', 'async_stmt', 'async_funcdef', 'decorated'):
|
|
||||||
node = node.parent
|
|
||||||
return node
|
|
||||||
|
|
||||||
|
|
||||||
def _suite_or_file_input_is_valid(pgen_grammar, stack):
|
def _suite_or_file_input_is_valid(pgen_grammar, stack):
|
||||||
if not _flows_finished(pgen_grammar, stack):
|
if not _flows_finished(pgen_grammar, stack):
|
||||||
return False
|
return False
|
||||||
@@ -390,7 +385,7 @@ class DiffParser(object):
|
|||||||
node = self._try_parse_part(until_line)
|
node = self._try_parse_part(until_line)
|
||||||
nodes = node.children
|
nodes = node.children
|
||||||
|
|
||||||
self._nodes_tree.add_parsed_nodes(nodes)
|
self._nodes_tree.add_parsed_nodes(nodes, self._keyword_token_indents)
|
||||||
if self._replace_tos_indent is not None:
|
if self._replace_tos_indent is not None:
|
||||||
self._nodes_tree.indents[-1] = self._replace_tos_indent
|
self._nodes_tree.indents[-1] = self._replace_tos_indent
|
||||||
|
|
||||||
@@ -441,6 +436,7 @@ class DiffParser(object):
|
|||||||
)
|
)
|
||||||
stack = self._active_parser.stack
|
stack = self._active_parser.stack
|
||||||
self._replace_tos_indent = None
|
self._replace_tos_indent = None
|
||||||
|
self._keyword_token_indents = {}
|
||||||
# print('start', line_offset + 1, indents)
|
# print('start', line_offset + 1, indents)
|
||||||
for token in tokens:
|
for token in tokens:
|
||||||
# print(token, indents)
|
# print(token, indents)
|
||||||
@@ -483,6 +479,9 @@ class DiffParser(object):
|
|||||||
yield PythonToken(ENDMARKER, '', token.start_pos, '')
|
yield PythonToken(ENDMARKER, '', token.start_pos, '')
|
||||||
break
|
break
|
||||||
|
|
||||||
|
if typ == NAME and token.string in ('class', 'def'):
|
||||||
|
self._keyword_token_indents[token.start_pos] = list(indents)
|
||||||
|
|
||||||
yield token
|
yield token
|
||||||
|
|
||||||
|
|
||||||
@@ -491,17 +490,12 @@ class _NodesTreeNode(object):
|
|||||||
'_ChildrenGroup',
|
'_ChildrenGroup',
|
||||||
'prefix children line_offset last_line_offset_leaf')
|
'prefix children line_offset last_line_offset_leaf')
|
||||||
|
|
||||||
def __init__(self, tree_node, parent=None):
|
def __init__(self, tree_node, parent=None, indentation=0):
|
||||||
self.tree_node = tree_node
|
self.tree_node = tree_node
|
||||||
self._children_groups = []
|
self._children_groups = []
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
self._node_children = []
|
self._node_children = []
|
||||||
|
self.indentation = indentation
|
||||||
if self.tree_node.type == 'file_input':
|
|
||||||
self.indentation = 0
|
|
||||||
else:
|
|
||||||
n = _get_suite_func_or_class_parent(self.tree_node)
|
|
||||||
self.indentation = _get_indentation(n)
|
|
||||||
|
|
||||||
def finish(self):
|
def finish(self):
|
||||||
children = []
|
children = []
|
||||||
@@ -585,7 +579,7 @@ class _NodesTree(object):
|
|||||||
return node
|
return node
|
||||||
self._working_stack.pop()
|
self._working_stack.pop()
|
||||||
|
|
||||||
def add_parsed_nodes(self, tree_nodes):
|
def add_parsed_nodes(self, tree_nodes, keyword_token_indents):
|
||||||
old_prefix = self.prefix
|
old_prefix = self.prefix
|
||||||
tree_nodes = self._remove_endmarker(tree_nodes)
|
tree_nodes = self._remove_endmarker(tree_nodes)
|
||||||
if not tree_nodes:
|
if not tree_nodes:
|
||||||
@@ -598,19 +592,23 @@ class _NodesTree(object):
|
|||||||
assert node.tree_node.type in ('suite', 'file_input')
|
assert node.tree_node.type in ('suite', 'file_input')
|
||||||
node.add_tree_nodes(old_prefix, tree_nodes)
|
node.add_tree_nodes(old_prefix, tree_nodes)
|
||||||
# tos = Top of stack
|
# tos = Top of stack
|
||||||
self._update_parsed_node_tos(tree_nodes[-1])
|
self._update_parsed_node_tos(tree_nodes[-1], keyword_token_indents)
|
||||||
|
|
||||||
def _update_parsed_node_tos(self, tree_node):
|
def _update_parsed_node_tos(self, tree_node, keyword_token_indents):
|
||||||
if tree_node.type == 'suite':
|
if tree_node.type == 'suite':
|
||||||
new_tos = _NodesTreeNode(tree_node)
|
def_leaf = tree_node.parent.children[0]
|
||||||
|
new_tos = _NodesTreeNode(
|
||||||
|
tree_node,
|
||||||
|
indentation=keyword_token_indents[def_leaf.start_pos][-1],
|
||||||
|
)
|
||||||
new_tos.add_tree_nodes('', list(tree_node.children))
|
new_tos.add_tree_nodes('', list(tree_node.children))
|
||||||
|
|
||||||
self._working_stack[-1].add_child_node(new_tos)
|
self._working_stack[-1].add_child_node(new_tos)
|
||||||
self._working_stack.append(new_tos)
|
self._working_stack.append(new_tos)
|
||||||
|
|
||||||
self._update_parsed_node_tos(tree_node.children[-1])
|
self._update_parsed_node_tos(tree_node.children[-1], keyword_token_indents)
|
||||||
elif _func_or_class_has_suite(tree_node):
|
elif _func_or_class_has_suite(tree_node):
|
||||||
self._update_parsed_node_tos(tree_node.children[-1])
|
self._update_parsed_node_tos(tree_node.children[-1], keyword_token_indents)
|
||||||
|
|
||||||
def _remove_endmarker(self, tree_nodes):
|
def _remove_endmarker(self, tree_nodes):
|
||||||
"""
|
"""
|
||||||
@@ -766,7 +764,8 @@ class _NodesTree(object):
|
|||||||
|
|
||||||
indent = _get_suite_indentation(suite)
|
indent = _get_suite_indentation(suite)
|
||||||
added_indents.append(indent)
|
added_indents.append(indent)
|
||||||
suite_tos = _NodesTreeNode(suite)
|
|
||||||
|
suite_tos = _NodesTreeNode(suite, indentation=_get_indentation(last_node))
|
||||||
# Don't need to pass line_offset here, it's already done by the
|
# Don't need to pass line_offset here, it's already done by the
|
||||||
# parent.
|
# parent.
|
||||||
suite_nodes, new_working_stack, new_prefix, ai = self._copy_nodes(
|
suite_nodes, new_working_stack, new_prefix, ai = self._copy_nodes(
|
||||||
|
|||||||
@@ -1671,12 +1671,7 @@ def test_yet_another_backslash(differ):
|
|||||||
differ.parse(code1, parsers=ANY, copies=ANY)
|
differ.parse(code1, parsers=ANY, copies=ANY)
|
||||||
|
|
||||||
|
|
||||||
@pytest.mark.xfail
|
def test_backslash_before_def(differ):
|
||||||
def test_very_weird_indentation(differ):
|
|
||||||
"""
|
|
||||||
This test for now fails, because it's just hard to implement this, but it's
|
|
||||||
also not really important.
|
|
||||||
"""
|
|
||||||
code1 = dedent('''\
|
code1 = dedent('''\
|
||||||
def f():
|
def f():
|
||||||
x
|
x
|
||||||
@@ -1696,4 +1691,4 @@ def test_very_weird_indentation(differ):
|
|||||||
''')
|
''')
|
||||||
|
|
||||||
differ.initialize(code1)
|
differ.initialize(code1)
|
||||||
differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
|
differ.parse(code2, parsers=3, copies=1, expect_error_leaves=True)
|
||||||
|
|||||||
Reference in New Issue
Block a user