diff --git a/jedi/parser/fast.py b/jedi/parser/fast.py index 5d9ad2a4..7a33913d 100644 --- a/jedi/parser/fast.py +++ b/jedi/parser/fast.py @@ -133,7 +133,9 @@ class DiffParser(object): sm = difflib.SequenceMatcher(None, lines_old, lines_new) print(len(lines_old), line_length, lines_old, lines_new) for operation, i1, i2, j1, j2 in sm.get_opcodes(): - debug.dbg('diff %s old[%s:%s] new[%s:%s]', operation, i1, i2, j1, j2) + debug.dbg('diff %s old[%s:%s] new[%s:%s]', + operation, i1 + 1, i2, j1 + 1, j2) + if j2 == line_length + int(self._added_newline): # The empty part after the last newline is not relevant. j2 -= 1 @@ -209,14 +211,19 @@ class DiffParser(object): if nodes: print('COPY', until_line_new, nodes) self._copy_count += 1 + debug.dbg( + 'diff actuall copy %s to %s', + nodes[0].start_pos[0], + nodes[-1].end_pos[0] + ) parent = self._insert_nodes(nodes) self._update_names_dict(parent, nodes) - self._update_positions(nodes, line_offset) + self._update_positions(nodes, line_offset) # We have copied as much as possible (but definitely not too - # much). Therefore we escape, even if we're not at the end. The - # rest will be parsed. - # Might not reach until the end, because there's a statement + # much). Therefore we just parse the rest. + # We might not reach the end, because there's a statement # that is not finished. + self._parse(until_line_new) break def _get_old_line_stmt(self, old_line): diff --git a/test/test_parser/test_diff_parser.py b/test/test_parser/test_diff_parser.py index 6d364d50..a811befd 100644 --- a/test/test_parser/test_diff_parser.py +++ b/test/test_parser/test_diff_parser.py @@ -3,6 +3,7 @@ from textwrap import dedent import pytest import jedi +from jedi import debug from jedi._compatibility import u from jedi.common import splitlines from jedi import cache @@ -56,11 +57,13 @@ class Differ(object): self._first_use = True def initialize(self, source): + debug.dbg('differ: initialize', color='YELLOW') grammar = load_grammar() self.parser = ParserWithRecovery(grammar, source) return self.parser.module def parse(self, source, copies=0, parsers=0, allow_error_leafs=False): + debug.dbg('differ: parse copies=%s parsers=%s', copies, parsers, color='YELLOW') lines = splitlines(source, keepends=True) diff_parser = DiffParser(self.parser) new_module = diff_parser.update(lines) @@ -182,11 +185,14 @@ def test_for_on_one_line(differ): src = dedent("""\ def hi(): for x in foo: pass + pass def nested(): pass """) - differ.parse(src, parsers=1, copies=1) + # The second parser is for parsing the `def nested()` which is an `equal` + # operation in the SequenceMatcher. + differ.parse(src, parsers=2, copies=1) def test_open_parentheses(differ):