Remove dedents from the parser tree. No need for them.

This commit is contained in:
Dave Halter
2016-09-11 13:03:29 +02:00
parent d748f6fad6
commit 1226962922
7 changed files with 21 additions and 8 deletions

View File

@@ -101,6 +101,10 @@ def _get_code_for_stack(code_lines, module, position):
if leaf.type in ('indent', 'dedent'): if leaf.type in ('indent', 'dedent'):
return u('') return u('')
elif leaf.type == 'error_leaf' or leaf.type == 'string': elif leaf.type == 'error_leaf' or leaf.type == 'string':
if leaf.start_pos[0] < position[0]:
# On a different line, we just begin anew.
return u('')
# Error leafs cannot be parsed, completion in strings is also # Error leafs cannot be parsed, completion in strings is also
# impossible. # impossible.
raise OnErrorLeaf(leaf) raise OnErrorLeaf(leaf)
@@ -266,9 +270,14 @@ def _get_call_signature_details_from_error_node(node, position):
def get_call_signature_details(module, position): def get_call_signature_details(module, position):
leaf = module.get_leaf_for_position(position, include_prefixes=True) leaf = module.get_leaf_for_position(position, include_prefixes=True)
if leaf.start_pos >= position:
# Whitespace / comments after the leaf count towards the previous leaf.
leaf = leaf.get_previous_leaf()
if leaf == ')': if leaf == ')':
if leaf.end_pos == position: if leaf.end_pos == position:
leaf = leaf.get_next_leaf() leaf = leaf.get_next_leaf()
# Now that we know where we are in the syntax tree, we start to look at # Now that we know where we are in the syntax tree, we start to look at
# parents for possible function definitions. # parents for possible function definitions.
node = leaf.parent node = leaf.parent

View File

@@ -181,9 +181,9 @@ def _get_faked(module, obj, name=None):
doc = '"""%s"""' % obj.__doc__ # TODO need escapes. doc = '"""%s"""' % obj.__doc__ # TODO need escapes.
suite = result.children[-1] suite = result.children[-1]
string = pt.String(pt.zero_position_modifier, doc, (0, 0), '') string = pt.String(pt.zero_position_modifier, doc, (0, 0), '')
new_line = pt.Newline('\n', (0, 0), '') new_line = pt.Newline(pt.zero_position_modifier, '\n', (0, 0))
docstr_node = pt.Node('simple_stmt', [string, new_line]) docstr_node = pt.Node('simple_stmt', [string, new_line])
suite.children.insert(2, docstr_node) suite.children.insert(1, docstr_node)
return result return result

View File

@@ -136,7 +136,7 @@ def _evaluate_for_statement_string(evaluator, string, module):
pseudo_cls = p.module.subscopes[0] pseudo_cls = p.module.subscopes[0]
# First pick suite, then simple_stmt (-2 for DEDENT) and then the node, # First pick suite, then simple_stmt (-2 for DEDENT) and then the node,
# which is also not the last item, because there's a newline. # which is also not the last item, because there's a newline.
stmt = pseudo_cls.children[-1].children[-2].children[-2] stmt = pseudo_cls.children[-1].children[-1].children[-2]
except (AttributeError, IndexError): except (AttributeError, IndexError):
return [] return []

View File

@@ -169,6 +169,12 @@ class Parser(object):
try: try:
new_node = Parser.AST_MAPPING[symbol](children) new_node = Parser.AST_MAPPING[symbol](children)
except KeyError: except KeyError:
if symbol == 'suite':
# We don't want the INDENT/DEDENT in our parser tree. Those
# leaves are just cancer. They are virtual leaves and not real
# ones and therefore have pseudo start/end positions and no
# prefixes. Just ignore them.
children = [children[0]] + children[2:-1]
new_node = pt.Node(symbol, children) new_node = pt.Node(symbol, children)
# We need to check raw_node always, because the same node can be # We need to check raw_node always, because the same node can be

View File

@@ -74,7 +74,7 @@ class DocstringMixin(object):
elif isinstance(self, ClassOrFunc): elif isinstance(self, ClassOrFunc):
node = self.children[self.children.index(':') + 1] node = self.children[self.children.index(':') + 1]
if is_node(node, 'suite'): # Normally a suite if is_node(node, 'suite'): # Normally a suite
node = node.children[2] # -> NEWLINE INDENT stmt node = node.children[1] # -> NEWLINE stmt
else: # ExprStmt else: # ExprStmt
simple_stmt = self.parent simple_stmt = self.parent
c = simple_stmt.parent.children c = simple_stmt.parent.children

View File

@@ -130,7 +130,7 @@ On Linux, if environment variable ``$XDG_CACHE_HOME`` is set,
# parser # parser
# ---------------- # ----------------
fast_parser = True fast_parser = False
""" """
Use the fast parser. This means that reparsing is only being done if Use the fast parser. This means that reparsing is only being done if
something has been changed e.g. to a function. If this happens, only the something has been changed e.g. to a function. If this happens, only the

View File

@@ -177,9 +177,7 @@ def test_end_pos_error_correction():
m = ParserWithRecovery(load_grammar(), s).module m = ParserWithRecovery(load_grammar(), s).module
func = m.children[0] func = m.children[0]
assert func.type == 'funcdef' assert func.type == 'funcdef'
# This is not exactly correct, but ok, because it doesn't make a difference assert func.end_pos == (2, 2)
# at all. We just want to make sure that the module end_pos is correct!
assert func.end_pos == (3, 0)
assert m.end_pos == (2, 2) assert m.end_pos == (2, 2)