Actual forward reference annotations are working pretty smooth now.

This commit is contained in:
Dave Halter
2015-12-20 22:57:24 +01:00
parent c4906e0e3f
commit 5791860861
5 changed files with 16 additions and 11 deletions

View File

@@ -322,12 +322,10 @@ class Script(object):
@memoize_default() @memoize_default()
def _get_under_cursor_stmt(self, cursor_txt, start_pos=None): def _get_under_cursor_stmt(self, cursor_txt, start_pos=None):
node = Parser(self._grammar, cursor_txt, 'eval_input').get_parsed_node() stmt = Parser(self._grammar, cursor_txt, 'eval_input').get_parsed_node()
if node is None: if stmt is None:
return None return None
stmt = node.children[0]
user_stmt = self._parser.user_stmt() user_stmt = self._parser.user_stmt()
if user_stmt is None: if user_stmt is None:
# Set the start_pos to a pseudo position, that doesn't exist but # Set the start_pos to a pseudo position, that doesn't exist but

View File

@@ -305,6 +305,8 @@ class Evaluator(object):
types = set(chain.from_iterable(self.find_types(typ, next_name) types = set(chain.from_iterable(self.find_types(typ, next_name)
for typ in types)) for typ in types))
types = types types = types
elif element.type == 'eval_input':
types = self._eval_element_not_cached(element.children[0])
else: else:
types = precedence.calculate_children(self, element.children) types = precedence.calculate_children(self, element.children)
debug.dbg('eval_element result %s', types) debug.dbg('eval_element result %s', types)

View File

@@ -32,7 +32,7 @@ def _evaluate_for_annotation(evaluator, annotation):
for definition in evaluator.eval_element(annotation): for definition in evaluator.eval_element(annotation):
if (isinstance(definition, CompiledObject) and if (isinstance(definition, CompiledObject) and
isinstance(definition.obj, str)): isinstance(definition.obj, str)):
p = Parser(load_grammar(), definition.obj, start='expr') p = Parser(load_grammar(), definition.obj, start='eval_input')
element = p.get_parsed_node() element = p.get_parsed_node()
if element is None: if element is None:
debug.warning('Annotation not parsed: %s' % definition.obj) debug.warning('Annotation not parsed: %s' % definition.obj)

View File

@@ -14,7 +14,7 @@ from jedi.common import unite
from jedi.evaluate import compiled from jedi.evaluate import compiled
from jedi.evaluate import representation as er from jedi.evaluate import representation as er
from jedi.evaluate import iterable from jedi.evaluate import iterable
from jedi.parser import Parser from jedi.parser import ParserWithRecovery
from jedi.parser import tree from jedi.parser import tree
from jedi import debug from jedi import debug
from jedi.evaluate import precedence from jedi.evaluate import precedence
@@ -243,7 +243,7 @@ def collections_namedtuple(evaluator, obj, arguments):
) )
# Parse source # Parse source
generated_class = Parser(evaluator.grammar, unicode(source)).module.subscopes[0] generated_class = ParserWithRecovery(evaluator.grammar, unicode(source)).module.subscopes[0]
return set([er.Class(evaluator, generated_class)]) return set([er.Class(evaluator, generated_class)])

View File

@@ -41,14 +41,19 @@ def test_simple_annotations():
@pytest.mark.parametrize('reference', [ @pytest.mark.parametrize('reference', [
'assert 1', 'assert 1',
'1', '1',
'lambda: 3',
'def x(): pass', 'def x(): pass',
'1, 2', '1, 2',
r'1\n' r'1\n'
]) ])
def test_illegal_forward_references(reference): def test_illegal_forward_references(reference):
source = """ source = 'def foo(bar: "%s"): bar' % reference
def foo(bar: "%s"):
bar""" % reference
assert not jedi.Script(source).goto_definitions() assert not jedi.Script(source).goto_definitions()
def test_lambda_forward_references():
source = 'def foo(bar: "lambda: 3"): bar'
# For now just receiving the 3 is ok. I'm doubting that this is what we
# want. We also execute functions. Should we only execute classes?
assert jedi.Script(source).goto_definitions()