diff --git a/jedi/evaluate/docstrings.py b/jedi/evaluate/docstrings.py index 3865093d..a927abd0 100644 --- a/jedi/evaluate/docstrings.py +++ b/jedi/evaluate/docstrings.py @@ -18,7 +18,7 @@ annotations. import re from textwrap import dedent -from parso import parse +from parso import parse, ParserSyntaxError from jedi._compatibility import u from jedi.evaluate.utils import indent_block @@ -202,7 +202,10 @@ def _evaluate_for_statement_string(module_context, string): # will be impossible to use `...` (Ellipsis) as a token. Docstring types # don't need to conform with the current grammar. grammar = module_context.evaluator.latest_grammar - module = grammar.parse(code.format(indent_block(string))) + try: + module = grammar.parse(code.format(indent_block(string)), error_recovery=False) + except ParserSyntaxError: + return [] try: funcdef = next(module.iter_funcdefs()) # First pick suite, then simple_stmt and then the node, diff --git a/jedi/evaluate/syntax_tree.py b/jedi/evaluate/syntax_tree.py index 76d29ae5..b89ea7aa 100644 --- a/jedi/evaluate/syntax_tree.py +++ b/jedi/evaluate/syntax_tree.py @@ -125,7 +125,9 @@ def eval_node(context, element): # Must be an ellipsis, other operators are not evaluated. # In Python 2 ellipsis is coded as three single dot tokens, not # as one token 3 dot token. - assert element.value in ('.', '...'), "The unhandled operator %s" % repr(element.value) + if element.value not in ('.', '...'): + origin = element.parent + raise AssertionError("unhandled operator %s in %s " % (repr(element.value), origin)) return ContextSet(compiled.builtin_from_name(evaluator, u'Ellipsis')) elif typ == 'dotted_name': context_set = eval_atom(context, element.children[0]) diff --git a/test/test_evaluate/test_docstring.py b/test/test_evaluate/test_docstring.py index 0b192701..3dfbc7af 100644 --- a/test/test_evaluate/test_docstring.py +++ b/test/test_evaluate/test_docstring.py @@ -196,6 +196,21 @@ def test_numpydoc_parameters_alternative_types(): assert 'append' in names +@pytest.mark.skipif(numpydoc_unavailable, + reason='numpydoc module is unavailable') +def test_numpydoc_invalid(): + s = dedent(''' + def foobar(x, y): + """ + Parameters + ---------- + x : int (str, py.path.local + """ + x.''') + + assert not jedi.Script(s).completions() + + @pytest.mark.skipif(numpydoc_unavailable, reason='numpydoc module is unavailable') def test_numpydoc_returns():