forked from VimPlug/jedi
Get a few diff tests passing.
This commit is contained in:
@@ -8,6 +8,7 @@ fragments.
|
|||||||
import copy
|
import copy
|
||||||
import re
|
import re
|
||||||
import difflib
|
import difflib
|
||||||
|
from collections import namedtuple
|
||||||
|
|
||||||
from jedi._compatibility import use_metaclass
|
from jedi._compatibility import use_metaclass
|
||||||
from jedi import settings
|
from jedi import settings
|
||||||
@@ -117,19 +118,15 @@ class DiffParser(object):
|
|||||||
def __init__(self, parser):
|
def __init__(self, parser):
|
||||||
self._parser = parser
|
self._parser = parser
|
||||||
self._grammar = self._parser._grammar
|
self._grammar = self._parser._grammar
|
||||||
self._old_module = parser.get_root_node()
|
self._module = parser.get_root_node()
|
||||||
|
|
||||||
def _reset(self):
|
def _reset(self):
|
||||||
self._copy_count = 0
|
self._copy_count = 0
|
||||||
self._parser_count = 0
|
self._parser_count = 0
|
||||||
|
|
||||||
self._copied_ranges = []
|
self._copied_ranges = []
|
||||||
|
|
||||||
self._old_children = self._old_module.children
|
|
||||||
self._new_used_names = {}
|
self._new_used_names = {}
|
||||||
self._last_prefix = ''
|
self._nodes_stack = _NodesStack(self._module)
|
||||||
|
|
||||||
self._nodes_stack = _NodesStack(self._old_module)
|
|
||||||
|
|
||||||
def update(self, lines_new):
|
def update(self, lines_new):
|
||||||
'''
|
'''
|
||||||
@@ -144,8 +141,6 @@ class DiffParser(object):
|
|||||||
Insert:
|
Insert:
|
||||||
- Parse from parsed_until_line + 1 to min(j2 + 1), hopefully not
|
- Parse from parsed_until_line + 1 to min(j2 + 1), hopefully not
|
||||||
much more.
|
much more.
|
||||||
Always:
|
|
||||||
- Set parsed_until_line
|
|
||||||
|
|
||||||
Returns the new module node.
|
Returns the new module node.
|
||||||
'''
|
'''
|
||||||
@@ -189,13 +184,12 @@ class DiffParser(object):
|
|||||||
self._cleanup()
|
self._cleanup()
|
||||||
if self._added_newline:
|
if self._added_newline:
|
||||||
self._parser.remove_last_newline()
|
self._parser.remove_last_newline()
|
||||||
self._nodes_stack.parsed_until_line -= 1
|
|
||||||
|
|
||||||
self._parser.source = ''.join(lines_new)
|
self._parser.source = ''.join(lines_new)
|
||||||
|
|
||||||
assert self._old_module.end_pos[0] == line_length
|
assert self._module.end_pos[0] == line_length
|
||||||
|
|
||||||
return self._old_module
|
return self._module
|
||||||
|
|
||||||
def _copy_from_old_parser(self, line_offset, until_line_old, until_line_new):
|
def _copy_from_old_parser(self, line_offset, until_line_old, until_line_new):
|
||||||
copied_nodes = [None]
|
copied_nodes = [None]
|
||||||
@@ -235,7 +229,7 @@ class DiffParser(object):
|
|||||||
break
|
break
|
||||||
|
|
||||||
def _get_old_line_stmt(self, old_line):
|
def _get_old_line_stmt(self, old_line):
|
||||||
leaf = self._old_module.get_leaf_for_position((old_line, 0), include_prefixes=True)
|
leaf = self._module.get_leaf_for_position((old_line, 0), include_prefixes=True)
|
||||||
|
|
||||||
if leaf.type == 'newline':
|
if leaf.type == 'newline':
|
||||||
leaf = leaf.get_next_leaf()
|
leaf = leaf.get_next_leaf()
|
||||||
@@ -365,7 +359,7 @@ class DiffParser(object):
|
|||||||
copied_line_numbers.update(range(l1, l2 + 1))
|
copied_line_numbers.update(range(l1, l2 + 1))
|
||||||
|
|
||||||
new_used_names = self._new_used_names
|
new_used_names = self._new_used_names
|
||||||
for key, names in self._old_module.used_names.items():
|
for key, names in self._module.used_names.items():
|
||||||
for name in names:
|
for name in names:
|
||||||
if name.start_pos[0] in copied_line_numbers:
|
if name.start_pos[0] in copied_line_numbers:
|
||||||
new_used_names.setdefault(key, []).append(name)
|
new_used_names.setdefault(key, []).append(name)
|
||||||
@@ -420,14 +414,16 @@ class DiffParser(object):
|
|||||||
|
|
||||||
|
|
||||||
class _NodesStackNode(object):
|
class _NodesStackNode(object):
|
||||||
|
ChildrenGroup = namedtuple('ChildrenGroup', 'children line_offset')
|
||||||
|
|
||||||
def __init__(self, tree_node, parent=None):
|
def __init__(self, tree_node, parent=None):
|
||||||
self.tree_node = tree_node
|
self.tree_node = tree_node
|
||||||
self._children_groups = []
|
self.children_groups = []
|
||||||
self.parent = parent
|
self.parent = parent
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
children = []
|
children = []
|
||||||
for children_part, line_offset in self._children_groups:
|
for children_part, line_offset in self.children_groups:
|
||||||
_update_positions(children_part, line_offset)
|
_update_positions(children_part, line_offset)
|
||||||
children += children_part
|
children += children_part
|
||||||
self.tree_node.children = children
|
self.tree_node.children = children
|
||||||
@@ -436,11 +432,32 @@ class _NodesStackNode(object):
|
|||||||
node.parent = self.tree_node
|
node.parent = self.tree_node
|
||||||
|
|
||||||
def add(self, children, line_offset=0):
|
def add(self, children, line_offset=0):
|
||||||
self._children_groups.append((children, line_offset))
|
group = self.ChildrenGroup(children, line_offset)
|
||||||
|
self.children_groups.append(group)
|
||||||
|
|
||||||
def update_last_children_group(self, new_children):
|
def update_last_children_group(self, new_children):
|
||||||
self._children_groups[-1] = (new_children, self._children_groups[-1][1])
|
group = self.ChildrenGroup(new_children, self.children_groups[-1].line_offset)
|
||||||
|
self.children_groups[-1] = group
|
||||||
|
|
||||||
|
def get_last_line(self):
|
||||||
|
if not self.children_groups:
|
||||||
|
assert not self.parent
|
||||||
|
return 0
|
||||||
|
|
||||||
|
last_leaf = self.children_groups[-1].children[-1].last_leaf()
|
||||||
|
line = last_leaf.end_pos[0]
|
||||||
|
|
||||||
|
# Calculate the line offsets
|
||||||
|
element = self
|
||||||
|
while element is not None:
|
||||||
|
line += element.children_groups[-1].line_offset
|
||||||
|
element = element.parent
|
||||||
|
|
||||||
|
# Newlines end on the next line, which means that they would cover
|
||||||
|
# the next line. That line is not fully parsed at this point.
|
||||||
|
if last_leaf.type == 'newline':
|
||||||
|
line -= 1
|
||||||
|
return line
|
||||||
|
|
||||||
|
|
||||||
class _NodesStack(object):
|
class _NodesStack(object):
|
||||||
@@ -450,12 +467,16 @@ class _NodesStack(object):
|
|||||||
# Top of stack
|
# Top of stack
|
||||||
self._tos = self._base_node = _NodesStackNode(module)
|
self._tos = self._base_node = _NodesStackNode(module)
|
||||||
self._module = module
|
self._module = module
|
||||||
|
self._last_prefix = ''
|
||||||
self.prefix = ''
|
self.prefix = ''
|
||||||
self.parsed_until_line = 0
|
|
||||||
|
|
||||||
def is_empty(self):
|
def is_empty(self):
|
||||||
return not self._base_node.children
|
return not self._base_node.children
|
||||||
|
|
||||||
|
@property
|
||||||
|
def parsed_until_line(self):
|
||||||
|
return self._tos.get_last_line() + self.prefix.count('\n')
|
||||||
|
|
||||||
def _get_insertion_node(self, indentation_node):
|
def _get_insertion_node(self, indentation_node):
|
||||||
indentation = indentation_node.start_pos[1]
|
indentation = indentation_node.start_pos[1]
|
||||||
|
|
||||||
@@ -480,7 +501,7 @@ class _NodesStack(object):
|
|||||||
node = node.parent
|
node = node.parent
|
||||||
|
|
||||||
def add_parsed_nodes(self, tree_nodes):
|
def add_parsed_nodes(self, tree_nodes):
|
||||||
tree_nodes = self._cleanup_nodes(tree_nodes)
|
tree_nodes = self._remove_endmarker(tree_nodes)
|
||||||
if not tree_nodes:
|
if not tree_nodes:
|
||||||
return
|
return
|
||||||
|
|
||||||
@@ -491,18 +512,14 @@ class _NodesStack(object):
|
|||||||
node.add(tree_nodes)
|
node.add(tree_nodes)
|
||||||
self._update_tos(tree_nodes[-1])
|
self._update_tos(tree_nodes[-1])
|
||||||
|
|
||||||
def _cleanup_nodes(self, tree_nodes, line_offset=0):
|
def _remove_endmarker(self, tree_nodes, line_offset=0):
|
||||||
"""
|
"""
|
||||||
Helps cleaning up the tree nodes that get inserted:
|
Helps cleaning up the tree nodes that get inserted.
|
||||||
|
|
||||||
1. Sets parsed_until_line
|
|
||||||
2. Removes the endmarker
|
|
||||||
"""
|
"""
|
||||||
last_leaf = tree_nodes[-1].last_leaf()
|
last_leaf = tree_nodes[-1].last_leaf()
|
||||||
is_endmarker = last_leaf.type == self.endmarker_type
|
is_endmarker = last_leaf.type == self.endmarker_type
|
||||||
self._last_prefix = ''
|
self._last_prefix = ''
|
||||||
if is_endmarker:
|
if is_endmarker:
|
||||||
self.parsed_until_line = last_leaf.start_pos[0]
|
|
||||||
try:
|
try:
|
||||||
separation = last_leaf.prefix.rindex('\n')
|
separation = last_leaf.prefix.rindex('\n')
|
||||||
except ValueError:
|
except ValueError:
|
||||||
@@ -514,19 +531,8 @@ class _NodesStack(object):
|
|||||||
last_leaf.prefix, self._last_prefix = \
|
last_leaf.prefix, self._last_prefix = \
|
||||||
last_leaf.prefix[:separation + 1], last_leaf.prefix[separation + 1:]
|
last_leaf.prefix[:separation + 1], last_leaf.prefix[separation + 1:]
|
||||||
|
|
||||||
if _last_leaf_is_newline(last_leaf):
|
|
||||||
self.parsed_until_line -= 1
|
|
||||||
else:
|
|
||||||
if last_leaf.type == 'newline':
|
|
||||||
# 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.start_pos[0]
|
|
||||||
else:
|
|
||||||
self.parsed_until_line = last_leaf.end_pos[0]
|
|
||||||
self.parsed_until_line += line_offset
|
|
||||||
print([t.get_code() for t in tree_nodes], is_endmarker,
|
print([t.get_code() for t in tree_nodes], is_endmarker,
|
||||||
repr(last_leaf.prefix))
|
repr(last_leaf.prefix))
|
||||||
debug.dbg('set parsed_until %s', self.parsed_until_line)
|
|
||||||
|
|
||||||
first_leaf = tree_nodes[0].first_leaf()
|
first_leaf = tree_nodes[0].first_leaf()
|
||||||
#before_node = self._get_before_insertion_node()
|
#before_node = self._get_before_insertion_node()
|
||||||
@@ -548,13 +554,13 @@ class _NodesStack(object):
|
|||||||
"""
|
"""
|
||||||
tos = self._get_insertion_node(tree_nodes[0])
|
tos = self._get_insertion_node(tree_nodes[0])
|
||||||
|
|
||||||
new_nodes, self._tos = self._xyz(tos, tree_nodes, until_line, line_offset)
|
new_nodes, self._tos = self._copy_nodes(tos, tree_nodes, until_line, line_offset)
|
||||||
if new_nodes:
|
if new_nodes:
|
||||||
new_nodes = self._cleanup_nodes(new_nodes, line_offset)
|
new_nodes = self._remove_endmarker(new_nodes, line_offset)
|
||||||
self._tos.update_last_children_group(new_nodes)
|
tos.update_last_children_group(new_nodes)
|
||||||
return new_nodes
|
return new_nodes
|
||||||
|
|
||||||
def _xyz(self, tos, tree_nodes, until_line, line_offset=0):
|
def _copy_nodes(self, tos, tree_nodes, until_line, line_offset=0):
|
||||||
new_nodes = []
|
new_nodes = []
|
||||||
new_tos = tos
|
new_tos = tos
|
||||||
for tree_node in tree_nodes:
|
for tree_node in tree_nodes:
|
||||||
@@ -571,7 +577,7 @@ class _NodesStack(object):
|
|||||||
# Don't need to pass until_line here, it's already done by the
|
# Don't need to pass until_line here, it's already done by the
|
||||||
# parent.
|
# parent.
|
||||||
suite_tos = _NodesStackNode(suite)
|
suite_tos = _NodesStackNode(suite)
|
||||||
suite_nodes, recursive_tos = self._xyz(suite_tos, suite.children, until_line)
|
suite_nodes, recursive_tos = self._copy_nodes(suite_tos, suite.children, until_line)
|
||||||
|
|
||||||
if len(suite_nodes) < 2:
|
if len(suite_nodes) < 2:
|
||||||
# A suite only with newline is not valid.
|
# A suite only with newline is not valid.
|
||||||
@@ -579,9 +585,10 @@ class _NodesStack(object):
|
|||||||
|
|
||||||
suite_tos.parent = new_tos
|
suite_tos.parent = new_tos
|
||||||
new_tos = recursive_tos
|
new_tos = recursive_tos
|
||||||
else:
|
|
||||||
new_nodes.append(tree_node)
|
|
||||||
|
|
||||||
|
new_nodes.append(tree_node)
|
||||||
|
|
||||||
|
print('x', new_nodes)
|
||||||
if new_nodes and (new_nodes[-1].type in ('error_leaf', 'error_node') or
|
if new_nodes and (new_nodes[-1].type in ('error_leaf', 'error_node') or
|
||||||
_is_flow_node(new_nodes[-1])):
|
_is_flow_node(new_nodes[-1])):
|
||||||
# Error leafs/nodes don't have a defined start/end. Error
|
# Error leafs/nodes don't have a defined start/end. Error
|
||||||
|
|||||||
Reference in New Issue
Block a user