diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index 0097821f..d6df3878 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -322,12 +322,10 @@ class Script(object): @memoize_default() def _get_under_cursor_stmt(self, cursor_txt, start_pos=None): - node = Parser(self._grammar, cursor_txt, 'eval_input').get_parsed_node() - if node is None: + stmt = Parser(self._grammar, cursor_txt, 'eval_input').get_parsed_node() + if stmt is None: return None - stmt = node.children[0] - user_stmt = self._parser.user_stmt() if user_stmt is None: # Set the start_pos to a pseudo position, that doesn't exist but diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 8167a5e6..6f63acc8 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -305,6 +305,8 @@ class Evaluator(object): types = set(chain.from_iterable(self.find_types(typ, next_name) for typ in types)) types = types + elif element.type == 'eval_input': + types = self._eval_element_not_cached(element.children[0]) else: types = precedence.calculate_children(self, element.children) debug.dbg('eval_element result %s', types) diff --git a/jedi/evaluate/pep0484.py b/jedi/evaluate/pep0484.py index 1896b8d0..d8948f47 100644 --- a/jedi/evaluate/pep0484.py +++ b/jedi/evaluate/pep0484.py @@ -32,7 +32,7 @@ def _evaluate_for_annotation(evaluator, annotation): for definition in evaluator.eval_element(annotation): if (isinstance(definition, CompiledObject) and 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() if element is None: debug.warning('Annotation not parsed: %s' % definition.obj) diff --git a/jedi/evaluate/stdlib.py b/jedi/evaluate/stdlib.py index acc3d901..0d4ebf1c 100644 --- a/jedi/evaluate/stdlib.py +++ b/jedi/evaluate/stdlib.py @@ -14,7 +14,7 @@ from jedi.common import unite from jedi.evaluate import compiled from jedi.evaluate import representation as er from jedi.evaluate import iterable -from jedi.parser import Parser +from jedi.parser import ParserWithRecovery from jedi.parser import tree from jedi import debug from jedi.evaluate import precedence @@ -243,7 +243,7 @@ def collections_namedtuple(evaluator, obj, arguments): ) # 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)]) diff --git a/test/test_evaluate/test_annotations.py b/test/test_evaluate/test_annotations.py index a1717cac..7897ffb0 100644 --- a/test/test_evaluate/test_annotations.py +++ b/test/test_evaluate/test_annotations.py @@ -41,14 +41,19 @@ def test_simple_annotations(): @pytest.mark.parametrize('reference', [ 'assert 1', '1', - 'lambda: 3', 'def x(): pass', '1, 2', r'1\n' ]) def test_illegal_forward_references(reference): - source = """ - def foo(bar: "%s"): - bar""" % reference + source = 'def foo(bar: "%s"): bar' % reference 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()