mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-17 19:15:55 +08:00
Get the position modifiers right.
This commit is contained in:
@@ -118,10 +118,9 @@ class ParserNode(object):
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
# With fast_parser we have either 1 subscope or only statements.
|
# With fast_parser we have either 1 subscope or only statements.
|
||||||
self._content_scope = self._names_dict_scope = parser.module.subscopes[0]
|
self._content_scope = parser.module.subscopes[0]
|
||||||
except IndexError:
|
except IndexError:
|
||||||
self._content_scope = parser.module
|
self._content_scope = parser.module
|
||||||
self._names_dict_scope = parser.module
|
|
||||||
|
|
||||||
# We need to be able to reset the original children of a parser.
|
# We need to be able to reset the original children of a parser.
|
||||||
self._old_children = list(self._content_scope.children)
|
self._old_children = list(self._content_scope.children)
|
||||||
@@ -183,14 +182,13 @@ class ParserNode(object):
|
|||||||
if self.parser is not None:
|
if self.parser is not None:
|
||||||
# The first Parser node contains all the others and is
|
# The first Parser node contains all the others and is
|
||||||
# typically empty.
|
# typically empty.
|
||||||
dcts.insert(0, self._names_dict_scope.names_dict)
|
dcts.insert(0, self._content_scope.names_dict)
|
||||||
print('DCTS', self.parser, dcts, self._node_children)
|
print('DCTS', self.parser, dcts, self._node_children)
|
||||||
self._content_scope.names_dict = MergedNamesDict(dcts)
|
self._content_scope.names_dict = MergedNamesDict(dcts)
|
||||||
|
|
||||||
def parent_until_indent(self, indent=None):
|
def parent_until_indent(self, indent=None):
|
||||||
if indent is None or self._indent >= indent and self.parent:
|
if indent is None or self._indent >= indent and self.parent:
|
||||||
if self.parent is not None:
|
if self.parent is not None:
|
||||||
print('until_indent')
|
|
||||||
self.close()
|
self.close()
|
||||||
return self.parent.parent_until_indent(indent)
|
return self.parent.parent_until_indent(indent)
|
||||||
return self
|
return self
|
||||||
@@ -231,7 +229,7 @@ class ParserNode(object):
|
|||||||
# Changing the line offsets is very important, because if they don't
|
# Changing the line offsets is very important, because if they don't
|
||||||
# fit, all the start_pos values will be wrong.
|
# fit, all the start_pos values will be wrong.
|
||||||
m = node.parser.module
|
m = node.parser.module
|
||||||
m.line_offset += line_offset + 1 - m.start_pos[0]
|
node.parser.position_modifier.line = line_offset + 1 - m.start_pos[0]
|
||||||
self._fast_module.modules.append(m)
|
self._fast_module.modules.append(m)
|
||||||
node.parent = self
|
node.parent = self
|
||||||
|
|
||||||
@@ -264,7 +262,6 @@ class ParserNode(object):
|
|||||||
def add_parser(self, parser, code):
|
def add_parser(self, parser, code):
|
||||||
# TODO REMOVE
|
# TODO REMOVE
|
||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
print('add parser')
|
|
||||||
return self.add_node(ParserNode(self._fast_module, parser, code, self), True)
|
return self.add_node(ParserNode(self._fast_module, parser, code, self), True)
|
||||||
|
|
||||||
def all_sub_nodes(self):
|
def all_sub_nodes(self):
|
||||||
@@ -294,12 +291,14 @@ class FastParser(use_metaclass(CachedFastParser)):
|
|||||||
self.current_node.set_parser(self, '')
|
self.current_node.set_parser(self, '')
|
||||||
|
|
||||||
def update(self, code):
|
def update(self, code):
|
||||||
|
# For testing purposes: It is important that the number of parsers used
|
||||||
|
# can be minimized. With this variable we can test it.
|
||||||
self.number_parsers_used = 0
|
self.number_parsers_used = 0
|
||||||
self.module.reset_caches()
|
self.module.reset_caches()
|
||||||
try:
|
try:
|
||||||
self._parse(code)
|
self._parse(code)
|
||||||
except:
|
except:
|
||||||
# FastParser is cached, be careful with exceptions
|
# FastParser is cached, be careful with exceptions.
|
||||||
self._reset_caches()
|
self._reset_caches()
|
||||||
raise
|
raise
|
||||||
|
|
||||||
@@ -446,7 +445,7 @@ class FastParser(use_metaclass(CachedFastParser)):
|
|||||||
"""
|
"""
|
||||||
h = hash(code)
|
h = hash(code)
|
||||||
for index, node in enumerate(nodes):
|
for index, node in enumerate(nodes):
|
||||||
print('EQ', node, repr(node.code), repr(code), id(node))
|
print('EQ', node, repr(node.code), repr(code))
|
||||||
if node.hash == h and node.code == code:
|
if node.hash == h and node.code == code:
|
||||||
node.reset_node()
|
node.reset_node()
|
||||||
nodes.remove(node)
|
nodes.remove(node)
|
||||||
@@ -471,7 +470,6 @@ class FastParser(use_metaclass(CachedFastParser)):
|
|||||||
code_part_actually_used = '\n'.join(used_lines)
|
code_part_actually_used = '\n'.join(used_lines)
|
||||||
node.set_parser(p, code_part_actually_used)
|
node.set_parser(p, code_part_actually_used)
|
||||||
|
|
||||||
print('add', id(node))
|
|
||||||
self.current_node.add_node(node, line_offset)
|
self.current_node.add_node(node, line_offset)
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@@ -527,7 +525,6 @@ class FastTokenizer(object):
|
|||||||
return current
|
return current
|
||||||
|
|
||||||
if self.previous[0] == DEDENT and not self._in_flow:
|
if self.previous[0] == DEDENT and not self._in_flow:
|
||||||
print('w', self.current, self.previous, self._first_stmt)
|
|
||||||
self._first_stmt = False
|
self._first_stmt = False
|
||||||
return self._close()
|
return self._close()
|
||||||
elif self.previous[0] in (None, NEWLINE, INDENT):
|
elif self.previous[0] in (None, NEWLINE, INDENT):
|
||||||
@@ -594,7 +591,6 @@ class FastTokenizer(object):
|
|||||||
return tokenize.DEDENT, '', start_pos, ''
|
return tokenize.DEDENT, '', start_pos, ''
|
||||||
elif not self._returned_endmarker:
|
elif not self._returned_endmarker:
|
||||||
self._returned_endmarker = True
|
self._returned_endmarker = True
|
||||||
print('end')
|
|
||||||
return ENDMARKER, '', start_pos, ''
|
return ENDMARKER, '', start_pos, ''
|
||||||
else:
|
else:
|
||||||
raise StopIteration
|
raise StopIteration
|
||||||
|
|||||||
@@ -158,6 +158,8 @@ class Leaf(Base):
|
|||||||
|
|
||||||
@start_pos.setter
|
@start_pos.setter
|
||||||
def start_pos(self, value):
|
def start_pos(self, value):
|
||||||
|
# TODO I think this is wrong, because the position_modifier.line needs
|
||||||
|
# to be looked at as well. Probably it needs to be substracted.
|
||||||
self._start_pos = value
|
self._start_pos = value
|
||||||
|
|
||||||
@property
|
@property
|
||||||
@@ -593,7 +595,7 @@ class SubModule(Scope, Module):
|
|||||||
of a module.
|
of a module.
|
||||||
"""
|
"""
|
||||||
__slots__ = ('path', 'global_names', 'used_names', '_name',
|
__slots__ = ('path', 'global_names', 'used_names', '_name',
|
||||||
'line_offset', 'use_as_parent', 'error_statement_stacks')
|
'use_as_parent', 'error_statement_stacks')
|
||||||
type = 'file_input'
|
type = 'file_input'
|
||||||
|
|
||||||
def __init__(self, children):
|
def __init__(self, children):
|
||||||
@@ -608,7 +610,6 @@ class SubModule(Scope, Module):
|
|||||||
super(SubModule, self).__init__(children)
|
super(SubModule, self).__init__(children)
|
||||||
self.path = None # Set later.
|
self.path = None # Set later.
|
||||||
# this may be changed depending on fast_parser
|
# this may be changed depending on fast_parser
|
||||||
self.line_offset = 0
|
|
||||||
|
|
||||||
def set_global_names(self, names):
|
def set_global_names(self, names):
|
||||||
"""
|
"""
|
||||||
|
|||||||
@@ -59,34 +59,51 @@ def test_carriage_return_splitting():
|
|||||||
assert [n.value for lst in p.module.names_dict.values() for n in lst] == ['Foo']
|
assert [n.value for lst in p.module.names_dict.values() for n in lst] == ['Foo']
|
||||||
|
|
||||||
|
|
||||||
|
def check_fp(src, number_parsers_used):
|
||||||
|
p = FastParser(load_grammar(), u(src))
|
||||||
|
cache.save_parser(None, None, p, pickling=False)
|
||||||
|
|
||||||
|
# TODO Don't change get_code, the whole thing should be the same.
|
||||||
|
# -> Need to refactor the parser first, though.
|
||||||
|
assert src == p.module.get_code()[:-1]
|
||||||
|
assert p.number_parsers_used == number_parsers_used
|
||||||
|
return p.module
|
||||||
|
|
||||||
|
|
||||||
def test_change_and_undo():
|
def test_change_and_undo():
|
||||||
|
# Empty the parser cache for the path None.
|
||||||
def fp(src, number_parsers_used):
|
|
||||||
p = FastParser(load_grammar(), u(src))
|
|
||||||
cache.save_parser(None, None, p, pickling=False)
|
|
||||||
|
|
||||||
# TODO Don't change get_code, the whole thing should be the same.
|
|
||||||
# -> Need to refactor the parser first, though.
|
|
||||||
assert src == p.module.get_code()[:-1]
|
|
||||||
assert p.number_parsers_used == number_parsers_used
|
|
||||||
|
|
||||||
cache.parser_cache.pop(None, None)
|
cache.parser_cache.pop(None, None)
|
||||||
func_before = 'def func():\n pass\n'
|
func_before = 'def func():\n pass\n'
|
||||||
# Parse the function and a.
|
# Parse the function and a.
|
||||||
fp(func_before + 'a', 2)
|
check_fp(func_before + 'a', 2)
|
||||||
# Parse just b.
|
# Parse just b.
|
||||||
fp(func_before + 'b', 1)
|
check_fp(func_before + 'b', 1)
|
||||||
# b has changed to a again, so parse that.
|
# b has changed to a again, so parse that.
|
||||||
fp(func_before + 'a', 1)
|
check_fp(func_before + 'a', 1)
|
||||||
# Same as before no parsers should be used.
|
# Same as before no parsers should be used.
|
||||||
fp(func_before + 'a', 0)
|
check_fp(func_before + 'a', 0)
|
||||||
|
|
||||||
# Getting rid of an old parser: Still no parsers used.
|
# Getting rid of an old parser: Still no parsers used.
|
||||||
fp('a', 0)
|
check_fp('a', 0)
|
||||||
# Now the file has completely change and we need to parse.
|
# Now the file has completely change and we need to parse.
|
||||||
fp('b', 1)
|
check_fp('b', 1)
|
||||||
# And again.
|
# And again.
|
||||||
fp('a', 1)
|
check_fp('a', 1)
|
||||||
|
|
||||||
|
|
||||||
|
def test_positions():
|
||||||
|
# Empty the parser cache for the path None.
|
||||||
|
cache.parser_cache.pop(None, None)
|
||||||
|
|
||||||
|
func_before = 'class A:\n pass\n'
|
||||||
|
m = check_fp(func_before + 'a', 2)
|
||||||
|
assert m.start_pos == (1, 0)
|
||||||
|
assert m.end_pos == (3, 1)
|
||||||
|
|
||||||
|
m = check_fp('a', 0)
|
||||||
|
assert m.start_pos == (1, 0)
|
||||||
|
assert m.end_pos == (1, 1)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def test_incomplete_function():
|
def test_incomplete_function():
|
||||||
|
|||||||
Reference in New Issue
Block a user