Diff parser: Check indentation for copies correctly

This commit is contained in:
Dave Halter
2020-04-04 20:36:19 +02:00
parent 1927ba7254
commit 6c7b397cc7
2 changed files with 37 additions and 9 deletions

View File

@@ -110,7 +110,7 @@ def _assert_nodes_are_equal(node1, node2):
assert False, (node1, node2)
for n1, n2 in zip(children1, children2):
_assert_nodes_are_equal(n1, n2)
assert len(children1) == len(children2), repr(children1) + '\n' + repr(children2)
assert len(children1) == len(children2), '\n' + repr(children1) + '\n' + repr(children2)
def _get_debug_error_message(module, old_lines, new_lines):
@@ -615,6 +615,19 @@ class _NodesTree(object):
tree_nodes = tree_nodes[:-1]
return tree_nodes
def _get_matching_indent_nodes(self, tree_nodes):
# There might be a random dedent where we have to stop copying.
# Invalid indents are ok, because the parser handled that
# properly before. An invalid dedent can happen, because a few
# lines above there was an invalid indent.
indent = _get_indentation(tree_nodes[0])
if indent not in self.indents:
return
for n in tree_nodes:
if _get_indentation(n) != indent:
return
yield n
def copy_nodes(self, tree_nodes, until_line, line_offset):
"""
Copies tree nodes from the old parser tree.
@@ -632,14 +645,7 @@ class _NodesTree(object):
old_indents = self.indents
self.indents = [i for i in self.indents if i <= indentation]
# There might be a random dedent where we have to stop copying.
# Invalid indents are ok, because the parser handled that
# properly before. An invalid dedent can happen, because a few
# lines above there was an invalid indent.
for i, c in enumerate(tree_nodes):
if _get_indentation(c) not in self.indents:
tree_nodes = tree_nodes[:i]
break
tree_nodes = list(self._get_matching_indent_nodes(tree_nodes))
self._update_insertion_node(indentation)

View File

@@ -1448,3 +1448,25 @@ def test_repeating_invalid_indent(differ):
''')
differ.initialize(code1)
differ.parse(code2, parsers=1, copies=1, expect_error_leaves=True)
def test_another_random_indent(differ):
code1 = dedent('''\
def foo():
a
b
c
return
def foo():
d
''')
code2 = dedent('''\
def foo():
a
c
return
def foo():
d
''')
differ.initialize(code1)
differ.parse(code2, parsers=1, copies=3)