1
0
forked from VimPlug/jedi

names_dict merging progress.

This commit is contained in:
Dave Halter
2016-08-20 14:21:37 +02:00
parent 37712ace9c
commit 70220171fa
2 changed files with 55 additions and 14 deletions

View File

@@ -10,7 +10,7 @@ from jedi._compatibility import use_metaclass
from jedi import settings from jedi import settings
from jedi.common import splitlines from jedi.common import splitlines
from jedi.parser import ParserWithRecovery from jedi.parser import ParserWithRecovery
from jedi.parser import tree from jedi.parser.tree import Module, search_ancestor
from jedi.parser.utils import parser_cache from jedi.parser.utils import parser_cache
from jedi.parser import tokenize from jedi.parser import tokenize
from jedi import debug from jedi import debug
@@ -35,8 +35,13 @@ class FastParser(use_metaclass(CachedFastParser)):
pass pass
def _merge_names_dicts(base_dict, other_dict):
for key, names in other_dict.items():
base_dict.setdefault(key, []).extend(names)
class DiffParser(): class DiffParser():
endmarker = ENDMARKER endmarker_type = 'endmarker'
def __init__(self, parser): def __init__(self, parser):
self._parser = parser self._parser = parser
@@ -76,7 +81,7 @@ class DiffParser():
self._old_children = self._module.children self._old_children = self._module.children
self._new_children = [] self._new_children = []
self._temp_module = tree.Module(self._new_children) self._temp_module = Module(self._new_children)
self._prefix = '' self._prefix = ''
lines_old = splitlines(self._parser.source, keepends=True) lines_old = splitlines(self._parser.source, keepends=True)
@@ -123,7 +128,6 @@ class DiffParser():
self._insert_nodes(nodes) self._insert_nodes(nodes)
# TODO remove dedent at end # TODO remove dedent at end
self._update_positions(nodes, line_offset) self._update_positions(nodes, line_offset)
self._post_parser_updates()
# We have copied as much as possible (but definitely not too # We have copied as much as possible (but definitely not too
# much). Therefore we escape, even if we're not at the end. The # much). Therefore we escape, even if we're not at the end. The
# rest will be parsed. # rest will be parsed.
@@ -154,17 +158,17 @@ class DiffParser():
def _insert_nodes(self, nodes): def _insert_nodes(self, nodes):
endmarker = nodes[-1] endmarker = nodes[-1]
if endmarker == self.endmarker: if endmarker.type == self.endmarker_type:
first_leaf = nodes[0].first_leaf() first_leaf = nodes[0].first_leaf()
first_leaf.prefix = self._prefix + first_leaf.prefix first_leaf.prefix = self._prefix + first_leaf.prefix
self._prefix = endmarker.prefix self._prefix = endmarker.prefix
nodes = nodes[:-1] nodes = nodes[:-1]
self.endmarker
before_node = self._get_before_insertion_node() before_node = self._get_before_insertion_node()
if before_node is None: # Everything is empty. if before_node is None: # Everything is empty.
self._new_children += nodes self._new_children += nodes
parent = self._temp_module
else: else:
line_indentation = nodes[0].start_pos[1] line_indentation = nodes[0].start_pos[1]
while True: while True:
@@ -177,13 +181,17 @@ class DiffParser():
# having the right indentation. # having the right indentation.
if before_node.parent is not None: if before_node.parent is not None:
# TODO add dedent # TODO add dedent
before_node = before_node.parent before_node = search_ancestor(
before_node.parent,
('suite', 'file_input')
)
continue continue
# TODO check if the indentation is lower than the last statement # TODO check if the indentation is lower than the last statement
# and add a dedent error leaf. # and add a dedent error leaf.
# TODO do the same for indent error leafs. # TODO do the same for indent error leafs.
p_children += nodes p_children += nodes
parent = before_node.parent
break break
last_leaf = self._temp_module.last_leaf() last_leaf = self._temp_module.last_leaf()
if last_leaf.value == '\n': if last_leaf.value == '\n':
@@ -192,6 +200,31 @@ class DiffParser():
self._parsed_until_line = last_leaf.end_pos[0] - 1 self._parsed_until_line = last_leaf.end_pos[0] - 1
else: else:
self._parsed_until_line = last_leaf.end_pos[0] self._parsed_until_line = last_leaf.end_pos[0]
return parent
def _update_names_dict(self, parent_node, nodes):
assert parent_node.type in ('suite', 'file_input')
if parent_node.type == 'suite':
parent_node = parent_node.parent
names_dict = parent_node.names_dict
def scan(nodes):
for node in nodes:
if node.type in ('classdef', 'funcdef'):
scan([node.children[1]])
continue
try:
scan(node.children)
except AttributeError:
if node.type == 'name':
names_dict.setdefault(node.value, []).append(node)
scan(nodes)
def _merge_parsed_node(self, parent_node, parsed_node):
_merge_names_dicts(parent_node.names_dict, parsed_node.names_dict)
_merge_names_dicts(self._temp_module, parsed_node.used_names)
def _divide_node(self, node, until_line): def _divide_node(self, node, until_line):
""" """
@@ -260,14 +293,9 @@ class DiffParser():
while until_line > self._parsed_until_line: while until_line > self._parsed_until_line:
node = self._parse_scope_node(until_line) node = self._parse_scope_node(until_line)
nodes = self._get_children_nodes(node) nodes = self._get_children_nodes(node)
self._insert_nodes(nodes) parent = self._insert_nodes(nodes)
before_node = self._get_before_insertion_node() self._merge_parsed_node(parent, node)
if before_node is None:
# The start of the file.
self._new_children += node.children
else:
before_node.parent.children += node.children
def _get_children_nodes(self, node): def _get_children_nodes(self, node):
nodes = node.children nodes = node.children

View File

@@ -54,6 +54,19 @@ def is_node(node, *symbol_names):
return type in symbol_names return type in symbol_names
def search_ancestor(node, node_type_or_types):
if not isinstance(node_type_or_types, (list, tuple)):
node_type_or_types = (node_type_or_types,)
node = node.parent
while node.type not in node_type_or_types:
try:
node = node.parent
except AttributeError:
return None
return node
class PositionModifier(object): class PositionModifier(object):
"""A start_pos modifier for the fast parser.""" """A start_pos modifier for the fast parser."""
def __init__(self): def __init__(self):