mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-10 07:41:51 +08:00
Now ErrorLeaf and ErrorNode are part of the syntax tree. This makes probably sense. The documentation will follow once it's clear how they will shape out.
This commit is contained in:
@@ -133,7 +133,11 @@ class Completion:
|
|||||||
if completion_parts.name:
|
if completion_parts.name:
|
||||||
pos = pos[0], pos[1] - len(completion_parts.name)
|
pos = pos[0], pos[1] - len(completion_parts.name)
|
||||||
|
|
||||||
stack = helpers.get_stack_at_position(grammar, self._source, self._module, pos)
|
try:
|
||||||
|
stack = helpers.get_stack_at_position(grammar, self._source, self._module, pos)
|
||||||
|
except helpers.OnErrorLeaf:
|
||||||
|
return []
|
||||||
|
|
||||||
allowed_keywords, allowed_tokens = \
|
allowed_keywords, allowed_tokens = \
|
||||||
helpers.get_possible_completion_types(grammar, stack)
|
helpers.get_possible_completion_types(grammar, stack)
|
||||||
|
|
||||||
|
|||||||
@@ -69,13 +69,21 @@ def get_user_or_error_stmt(module, position):
|
|||||||
if user_stmt is None or user_stmt.type == 'whitespace':
|
if user_stmt is None or user_stmt.type == 'whitespace':
|
||||||
# If there's no error statement and we're just somewhere, we want
|
# If there's no error statement and we're just somewhere, we want
|
||||||
# completions for just whitespace.
|
# completions for just whitespace.
|
||||||
|
'''
|
||||||
for error_stmt in module.error_statements:
|
for error_stmt in module.error_statements:
|
||||||
if error_stmt.start_pos < position <= error_stmt.end_pos:
|
if error_stmt.start_pos < position <= error_stmt.end_pos:
|
||||||
return error_stmt
|
return error_stmt
|
||||||
|
'''
|
||||||
|
|
||||||
return user_stmt
|
return user_stmt
|
||||||
|
|
||||||
|
|
||||||
|
class OnErrorLeaf(Exception):
|
||||||
|
@property
|
||||||
|
def error_leaf(self):
|
||||||
|
return self.args[0]
|
||||||
|
|
||||||
|
|
||||||
def get_stack_at_position(grammar, source, module, pos):
|
def get_stack_at_position(grammar, source, module, pos):
|
||||||
"""
|
"""
|
||||||
Returns the possible node names (e.g. import_from, xor_test or yield_stmt).
|
Returns the possible node names (e.g. import_from, xor_test or yield_stmt).
|
||||||
@@ -87,19 +95,38 @@ def get_stack_at_position(grammar, source, module, pos):
|
|||||||
else:
|
else:
|
||||||
if user_stmt is None:
|
if user_stmt is None:
|
||||||
user_stmt = module.get_leaf_for_position(pos, include_prefixes=True)
|
user_stmt = module.get_leaf_for_position(pos, include_prefixes=True)
|
||||||
|
print(user_stmt)
|
||||||
|
if pos <= user_stmt.start_pos:
|
||||||
|
try:
|
||||||
|
leaf = user_stmt.get_previous_leaf()
|
||||||
|
except IndexError:
|
||||||
|
pass
|
||||||
|
else:
|
||||||
|
user_stmt = get_user_or_error_stmt(module, leaf.start_pos)
|
||||||
# Only if were in front of the leaf we want to get the stack,
|
# Only if were in front of the leaf we want to get the stack,
|
||||||
# because after there's probably a newline or whatever that would
|
# because after there's probably a newline or whatever that would
|
||||||
# be actually tokenized and is not just prefix.
|
# be actually tokenized and is not just prefix.
|
||||||
if pos <= user_stmt.start_pos:
|
if pos <= user_stmt.start_pos:
|
||||||
leaf = user_stmt.get_previous_leaf()
|
try:
|
||||||
for error_stmt in reversed(module.error_statements):
|
leaf = user_stmt.get_previous_leaf()
|
||||||
if leaf.start_pos <= error_stmt.start_pos <= user_stmt.start_pos:
|
except IndexError:
|
||||||
# The leaf appears not to be the last leaf. It's actually an
|
# Seems to be the first element.
|
||||||
# error statement.
|
pass
|
||||||
user_stmt = error_stmt
|
|
||||||
break
|
|
||||||
else:
|
else:
|
||||||
user_stmt = get_user_or_error_stmt(module, leaf.start_pos)
|
'''
|
||||||
|
for error_stmt in reversed(module.error_statements):
|
||||||
|
if leaf.start_pos <= error_stmt.start_pos <= user_stmt.start_pos:
|
||||||
|
# The leaf appears not to be the last leaf. It's actually an
|
||||||
|
# error statement.
|
||||||
|
user_stmt = error_stmt
|
||||||
|
break
|
||||||
|
else:
|
||||||
|
user_stmt = get_user_or_error_stmt(module, leaf.start_pos)
|
||||||
|
'''
|
||||||
|
|
||||||
|
if user_stmt.type == 'error_leaf':
|
||||||
|
# Error leafs cannot be parsed.
|
||||||
|
raise OnErrorLeaf(user_stmt)
|
||||||
|
|
||||||
print(user_stmt.start_pos, pos)
|
print(user_stmt.start_pos, pos)
|
||||||
code = _get_code(source, user_stmt.start_pos, pos)
|
code = _get_code(source, user_stmt.start_pos, pos)
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ def deep_ast_copy(obj, parent=None, new_elements=None):
|
|||||||
for child in obj.children:
|
for child in obj.children:
|
||||||
typ = child.type
|
typ = child.type
|
||||||
if typ in ('whitespace', 'operator', 'keyword', 'number', 'string',
|
if typ in ('whitespace', 'operator', 'keyword', 'number', 'string',
|
||||||
'indent', 'dedent'):
|
'indent', 'dedent', 'error_leaf'):
|
||||||
# At the moment we're not actually copying those primitive
|
# At the moment we're not actually copying those primitive
|
||||||
# elements, because there's really no need to. The parents are
|
# elements, because there's really no need to. The parents are
|
||||||
# obviously wrong, but that's not an issue.
|
# obviously wrong, but that's not an issue.
|
||||||
|
|||||||
@@ -422,6 +422,8 @@ class ParserWithRecovery(Parser):
|
|||||||
# TODO document the shizzle!
|
# TODO document the shizzle!
|
||||||
#self._error_statements.append(ErrorStatement(stack, None, None,
|
#self._error_statements.append(ErrorStatement(stack, None, None,
|
||||||
# self.position_modifier, error_leaf.end_pos))
|
# self.position_modifier, error_leaf.end_pos))
|
||||||
|
error_leaf = pt.ErrorLeaf(self.position_modifier, value, start_pos, prefix)
|
||||||
|
stack[-1][2][1].append(error_leaf)
|
||||||
return
|
return
|
||||||
|
|
||||||
if typ == INDENT:
|
if typ == INDENT:
|
||||||
@@ -462,17 +464,20 @@ class ParserWithRecovery(Parser):
|
|||||||
|
|
||||||
failed_stack = []
|
failed_stack = []
|
||||||
found = False
|
found = False
|
||||||
|
all_nodes = []
|
||||||
for dfa, state, (typ, nodes) in stack[start_index:]:
|
for dfa, state, (typ, nodes) in stack[start_index:]:
|
||||||
if nodes:
|
if nodes:
|
||||||
found = True
|
found = True
|
||||||
if found:
|
if found:
|
||||||
symbol = grammar.number2symbol[typ]
|
symbol = grammar.number2symbol[typ]
|
||||||
failed_stack.append((symbol, nodes))
|
failed_stack.append((symbol, nodes))
|
||||||
|
all_nodes += nodes
|
||||||
if nodes and nodes[0] in ('def', 'class', 'lambda'):
|
if nodes and nodes[0] in ('def', 'class', 'lambda'):
|
||||||
self._scope_names_stack.pop()
|
self._scope_names_stack.pop()
|
||||||
if failed_stack:
|
if failed_stack:
|
||||||
err = ErrorStatement(failed_stack, arcs, value, self.position_modifier, start_pos)
|
err = ErrorStatement(failed_stack, arcs, value, self.position_modifier, start_pos)
|
||||||
self._error_statements.append(err)
|
self._error_statements.append(err)
|
||||||
|
stack[start_index - 1][2][1].append(pt.ErrorNode(all_nodes))
|
||||||
|
|
||||||
self._last_failed_start_pos = start_pos
|
self._last_failed_start_pos = start_pos
|
||||||
|
|
||||||
|
|||||||
@@ -641,6 +641,22 @@ class Node(BaseNode):
|
|||||||
return "%s(%s, %r)" % (self.__class__.__name__, self.type, self.children)
|
return "%s(%s, %r)" % (self.__class__.__name__, self.type, self.children)
|
||||||
|
|
||||||
|
|
||||||
|
class ErrorNode(BaseNode):
|
||||||
|
"""
|
||||||
|
TODO doc
|
||||||
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
type = 'error_node'
|
||||||
|
|
||||||
|
|
||||||
|
class ErrorLeaf(Leaf):
|
||||||
|
"""
|
||||||
|
TODO doc
|
||||||
|
"""
|
||||||
|
__slots__ = ()
|
||||||
|
type = 'error_leaf'
|
||||||
|
|
||||||
|
|
||||||
class IsScopeMeta(type):
|
class IsScopeMeta(type):
|
||||||
def __instancecheck__(self, other):
|
def __instancecheck__(self, other):
|
||||||
return other.is_scope()
|
return other.is_scope()
|
||||||
|
|||||||
@@ -31,7 +31,8 @@ def wrong_indents():
|
|||||||
asdf = 3
|
asdf = 3
|
||||||
asdf
|
asdf
|
||||||
asdf(
|
asdf(
|
||||||
#? int()
|
# TODO this seems to be wrong now?
|
||||||
|
##? int()
|
||||||
asdf
|
asdf
|
||||||
def openbrace():
|
def openbrace():
|
||||||
asdf = 3
|
asdf = 3
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
#? ['raise']
|
#? ['raise']
|
||||||
raise
|
raise
|
||||||
|
|
||||||
#? ['except', 'Exception']
|
#? ['Exception']
|
||||||
except
|
except
|
||||||
|
|
||||||
#? []
|
#? []
|
||||||
|
|||||||
@@ -86,7 +86,7 @@ from os import path
|
|||||||
|
|
||||||
# should not return a function, because `a` is a function above
|
# should not return a function, because `a` is a function above
|
||||||
def f(b, a): return a
|
def f(b, a): return a
|
||||||
#? []
|
#? ['in', 'is', 'and', 'if', 'or', 'not']
|
||||||
f(b=3)
|
f(b=3)
|
||||||
|
|
||||||
# -----------------
|
# -----------------
|
||||||
|
|||||||
Reference in New Issue
Block a user