1
0
forked from VimPlug/jedi

Fix an issue in the fast parser that caused stuff to be parsed always.

This commit is contained in:
Dave Halter
2015-01-21 02:03:06 +01:00
parent 7188105dc7
commit 91ab1d0ecd

View File

@@ -26,10 +26,7 @@ class FastModule(pr.Module, pr.Simple):
self.reset_caches() self.reset_caches()
def reset_caches(self): def reset_caches(self):
""" This module does a whole lot of caching, because it uses different self.modules = []
parsers. """
with common.ignored(AttributeError):
del self._used_names
def __getattr__(self, name): def __getattr__(self, name):
if name.startswith('__'): if name.startswith('__'):
@@ -58,15 +55,15 @@ class FastModule(pr.Module, pr.Simple):
class MergedNamesDict(object): class MergedNamesDict(object):
def __init__(self, dicts): def __init__(self, dicts):
self._dicts = dicts self.dicts = dicts
def __getitem__(self, value): def __getitem__(self, value):
print(value, self._dicts) print(value, self.dicts)
return list(chain.from_iterable(dct.get(value, []) for dct in self._dicts)) return list(chain.from_iterable(dct.get(value, []) for dct in self.dicts))
def values(self): def values(self):
lst = [] lst = []
for dct in self._dicts: for dct in self.dicts:
lst.append(dct.values()) lst.append(dct.values())
return lst return lst
@@ -126,7 +123,22 @@ class ParserNode(object):
self.node_children = [] self.node_children = []
def reset_node(self):
"""
Removes changes that were applied in this class.
"""
nd_scope = self._names_dict_scope
try:
# This works if it's a MergedNamesDict.
# We are correcting it, because the MergedNamesDicts are artificial
# and can change after closing a node.
print('module.names_dict', nd_scope.names_dict)
nd_scope.names_dict = nd_scope.names_dict.dicts[0]
except AttributeError:
pass
def reset_contents(self): def reset_contents(self):
raise NotImplementedError
""" """
scope = self._content_scope scope = self._content_scope
for key, c in self._contents.items(): for key, c in self._contents.items():
@@ -157,6 +169,7 @@ class ParserNode(object):
# 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._names_dict_scope.names_dict)
print('DCTS', dcts)
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):
@@ -258,6 +271,7 @@ class FastParser(use_metaclass(CachedFastParser)):
# set values like `pr.Module`. # set values like `pr.Module`.
self._grammar = grammar self._grammar = grammar
self.module_path = module_path self.module_path = module_path
self._reset_caches()
self.update(code) self.update(code)
def _reset_caches(self): def _reset_caches(self):
@@ -265,8 +279,7 @@ class FastParser(use_metaclass(CachedFastParser)):
self.current_node = ParserNode(self.module) self.current_node = ParserNode(self.module)
def update(self, code): def update(self, code):
self._reset_caches() self.module.reset_caches()
try: try:
self._parse(code) self._parse(code)
except: except:
@@ -342,7 +355,7 @@ class FastParser(use_metaclass(CachedFastParser)):
line_offset = 0 line_offset = 0
start = 0 start = 0
is_first = True is_first = True
nodes = self.current_node.all_nodes() nodes = list(self.current_node.all_nodes())
for code_part in self._split_parts(code): for code_part in self._split_parts(code):
if is_first or line_offset + 1 == self.current_node.parser.module.end_pos[0]: if is_first or line_offset + 1 == self.current_node.parser.module.end_pos[0]:
@@ -417,20 +430,25 @@ class FastParser(use_metaclass(CachedFastParser)):
for index, node in enumerate(list(nodes)): for index, node in enumerate(list(nodes)):
print('EQ', node, repr(node.code), repr(code)) 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()
nodes.remove(node) nodes.remove(node)
break break
else: else:
print('ACTUALLY PARSING')
tokenizer = FastTokenizer(parser_code, line_offset) tokenizer = FastTokenizer(parser_code, line_offset)
p = Parser(self._grammar, parser_code, self.module_path, tokenizer=tokenizer) p = Parser(self._grammar, parser_code, self.module_path, tokenizer=tokenizer)
#p.module.parent = self.module # With the new parser this is not #p.module.parent = self.module # With the new parser this is not
# necessary anymore? # necessary anymore?
node = ParserNode(self.module, self.current_node) node = ParserNode(self.module, self.current_node)
end = p.module.end_pos[0]
print('\nACTUALLY PARSING\n', end, len(self._lines))
if len(self._lines) != end:
# The actual used code_part is different from the given code # The actual used code_part is different from the given code
# part, because of docstrings for example there's a chance that # part, because of docstrings for example there's a chance that
# splits are wrong. # splits are wrong. Somehow it's different for the end
used_lines = self._lines[line_offset:p.module.end_pos[0] - 1] # position.
end -= 1
used_lines = self._lines[line_offset:end]
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)