diff --git a/jedi/parser/__init__.py b/jedi/parser/__init__.py index 1f116ee5..39fa740c 100644 --- a/jedi/parser/__init__.py +++ b/jedi/parser/__init__.py @@ -299,6 +299,7 @@ class ParserWithRecovery(Parser): self._omit_dedent_list = [] self._indent_counter = 0 + self._module_path = module_path # TODO do print absolute import detection here. # try: @@ -314,14 +315,14 @@ class ParserWithRecovery(Parser): tokenizer=tokenizer, start_parsing=start_parsing ) - if start_parsing: - self.module = self._parsed - self.module.used_names = self._used_names - self.module.path = module_path - self.module.global_names = self._global_names def parse(self, tokenizer): - return super(ParserWithRecovery, self).parse(self._tokenize(self._tokenize(tokenizer))) + root_node = super(ParserWithRecovery, self).parse(self._tokenize(self._tokenize(tokenizer))) + self.module = root_node + self.module.used_names = self._used_names + self.module.path = self._module_path + self.module.global_names = self._global_names + return root_node def error_recovery(self, grammar, stack, arcs, typ, value, start_pos, prefix, add_token_callback): diff --git a/jedi/parser/fast.py b/jedi/parser/fast.py index 4c67928a..7fa7b83c 100644 --- a/jedi/parser/fast.py +++ b/jedi/parser/fast.py @@ -82,6 +82,8 @@ class DiffParser(): self._old_children = self._module.children self._new_children = [] self._temp_module = Module(self._new_children) + self._temp_module.names_dict = {} + self._temp_module.used_names = {} self._prefix = '' lines_old = splitlines(self._parser.source, keepends=True) @@ -103,9 +105,14 @@ class DiffParser(): self._post_parse() self._module.used_names = self._temp_module.used_names + self._module.children = self._new_children + # TODO insert endmarker + + def _insert(self, until_line_new): + self._insert_count += 1 + self._parse(until_line_new) def _copy_from_old_parser(self, line_offset, until_line_old, until_line_new): - # TODO update namesdict!!! and module global_names, used_names while until_line_new > self._parsed_until_line: parsed_until_line_old = self._parsed_until_line - line_offset line_stmt = self._get_old_line_stmt(parsed_until_line_old + 1) @@ -128,7 +135,8 @@ class DiffParser(): nodes.append(node) if nodes: - self._insert_nodes(nodes) + parent = self._insert_nodes(nodes) + self._update_names_dict(parent, nodes) # TODO remove dedent at end self._update_positions(nodes, line_offset) # We have copied as much as possible (but definitely not too @@ -155,20 +163,28 @@ class DiffParser(): while True: return node - def _insert(self, until_line_new): - self._insert_count += 1 - self._parse(until_line_new) - def _insert_nodes(self, nodes): - endmarker = nodes[-1] - if endmarker.type == self.endmarker_type: + # Needs to be done before resetting the parsed + before_node = self._get_before_insertion_node() + + last_leaf = nodes[-1].last_leaf() + if last_leaf.value == '\n': + # Newlines end on the next line, which means that they would cover + # the next line. That line is not fully parsed at this point. + self._parsed_until_line = last_leaf.end_pos[0] - 1 + else: + self._parsed_until_line = last_leaf.end_pos[0] + + if last_leaf.type == self.endmarker_type: first_leaf = nodes[0].first_leaf() first_leaf.prefix = self._prefix + first_leaf.prefix - self._prefix = endmarker.prefix + self._prefix = last_leaf.prefix nodes = nodes[:-1] + if not nodes: + return self._module - before_node = self._get_before_insertion_node() + # Now the preparations are done. We are inserting the nodes. if before_node is None: # Everything is empty. self._new_children += nodes parent = self._temp_module @@ -196,13 +212,10 @@ class DiffParser(): p_children += nodes parent = before_node.parent break - last_leaf = self._temp_module.last_leaf() - if last_leaf.value == '\n': - # Newlines end on the next line, which means that they would cover - # the next line. That line is not fully parsed at this point. - self._parsed_until_line = last_leaf.end_pos[0] - 1 - else: - self._parsed_until_line = last_leaf.end_pos[0] + + # Reset the parents + for node in nodes: + node.parent = parent return parent def _update_names_dict(self, parent_node, nodes): @@ -260,6 +273,8 @@ class DiffParser(): return None line = self._parsed_until_line + 1 + leaf = self._module.last_leaf() + ''' print(line) leaf = self._module.get_leaf_for_position((line, 0), include_prefixes=False) while leaf.type != 'newline': @@ -269,6 +284,7 @@ class DiffParser(): # TODO raise NotImplementedError +''' node = leaf while True: parent = node.parent @@ -297,7 +313,6 @@ class DiffParser(): node = self._parse_scope_node(until_line) nodes = self._get_children_nodes(node) parent = self._insert_nodes(nodes) - self._merge_parsed_node(parent, node) def _get_children_nodes(self, node): diff --git a/jedi/parser/tree.py b/jedi/parser/tree.py index 71de570a..0e77e1d6 100644 --- a/jedi/parser/tree.py +++ b/jedi/parser/tree.py @@ -327,6 +327,9 @@ class Leaf(Base): def first_leaf(self): return self + def last_leaf(self): + return self + def get_code(self, normalized=False, include_prefix=True): if normalized: return self.value diff --git a/test/test_parser/test_fast_parser.py b/test/test_parser/test_fast_parser.py index d281caca..9d7e0605 100644 --- a/test/test_parser/test_fast_parser.py +++ b/test/test_parser/test_fast_parser.py @@ -22,12 +22,12 @@ def test_add_to_end(): self.x = 3 class Two(Abc): - def h(self): + def g(self): self """) # ^ here is the first completion - b = " def g(self):\n" \ + b = " def h(self):\n" \ " self." assert jedi.Script(a, 8, 12, 'example.py').completions() assert jedi.Script(a + b, path='example.py').completions()