From f99fe6ad21ed58de6acf5f055bac8a83982c8624 Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Sun, 30 Dec 2018 15:25:17 +0100 Subject: [PATCH] Fix diff-parser: Copying parts of if else should not lead to the whole thing being copied --- parso/python/diff.py | 11 +++++++++-- test/test_diff_parser.py | 33 ++++++++++++++++++++++++++++++++- 2 files changed, 41 insertions(+), 3 deletions(-) diff --git a/parso/python/diff.py b/parso/python/diff.py index a0bc3e4..2255b5c 100644 --- a/parso/python/diff.py +++ b/parso/python/diff.py @@ -171,6 +171,7 @@ class DiffParser(object): % (last_pos, line_length, parso.__version__, ''.join(diff)) ) + #assert self._module.get_code() == ''.join(new_lines) LOG.debug('diff parser end') return self._module @@ -212,7 +213,9 @@ class DiffParser(object): to = self._nodes_tree.parsed_until_line - LOG.debug('actually copy %s to %s', from_, to) + LOG.debug('copy old[%s:%s] new[%s:%s]', + copied_nodes[0].start_pos[0], + copied_nodes[-1].end_pos[0] - 1, from_, to) # Since there are potential bugs that might loop here endlessly, we # just stop here. assert last_until_line != self._nodes_tree.parsed_until_line \ @@ -228,7 +231,11 @@ class DiffParser(object): node = leaf while node.parent.type not in ('file_input', 'suite'): node = node.parent - return node + + # Make sure that if only the `else:` line of an if statement is + # copied that not the whole thing is going to be copied. + if node.start_pos[0] >= old_line: + return node # Must be on the same line. Otherwise we need to parse that bit. return None diff --git a/test/test_diff_parser.py b/test/test_diff_parser.py index d90f40b..eaf748c 100644 --- a/test/test_diff_parser.py +++ b/test/test_diff_parser.py @@ -142,7 +142,7 @@ def test_if_simple(differ): differ.initialize(src + 'a') differ.parse(src + else_ + "a", copies=0, parsers=1) - differ.parse(else_, parsers=1, expect_error_leaves=True) + differ.parse(else_, parsers=1, copies=1, expect_error_leaves=True) differ.parse(src + else_, parsers=1) @@ -560,3 +560,34 @@ def test_invalid_to_valid_nodes(differ): differ.initialize(code1) differ.parse(code2, parsers=1, copies=3) + + +def test_if_removal_and_reappearence(differ): + code1 = dedent('''\ + la = 3 + if foo: + latte = 3 + else: + la + pass + ''') + + code2 = dedent('''\ + la = 3 + latte = 3 + else: + la + pass + ''') + + code3 = dedent('''\ + la = 3 + if foo: + latte = 3 + else: + la + ''') + differ.initialize(code1) + differ.parse(code2, parsers=1, copies=4, expect_error_leaves=True) + differ.parse(code1, parsers=1, copies=1) + differ.parse(code3, parsers=1, copies=1)