diff --git a/jedi/evaluate/pep0484.py b/jedi/evaluate/pep0484.py index 536e624b..a9dc748c 100644 --- a/jedi/evaluate/pep0484.py +++ b/jedi/evaluate/pep0484.py @@ -7,8 +7,8 @@ as annotations in future python versions. The (initial / probably incomplete) implementation todo list for pep-0484: v Function parameter annotations with builtin/custom type classes v Function returntype annotations with builtin/custom type classes -x Function parameter annotations with strings (forward reference) -x Function return type annotations with strings (forward reference) +v Function parameter annotations with strings (forward reference) +v Function return type annotations with strings (forward reference) x Local variable type hints x Assigned types: `Url = str\ndef get(url:Url) -> str:` x Type hints in `with` statements diff --git a/jedi/parser/tree.py b/jedi/parser/tree.py index c5fb0934..df116820 100644 --- a/jedi/parser/tree.py +++ b/jedi/parser/tree.py @@ -41,6 +41,7 @@ import textwrap from jedi._compatibility import (Python3Method, encoding, is_py3, utf8_repr, literal_eval, use_metaclass, unicode) from jedi import cache +import ast def is_node(node, *symbol_names): @@ -52,6 +53,19 @@ def is_node(node, *symbol_names): return type in symbol_names +def _fix_forward_reference(annotation): + if isinstance(annotation, String): + newannotation = Name( + annotation.position_modifier, + ast.literal_eval(annotation.value), + annotation.start_pos, + annotation.prefix) + newannotation.parent = annotation.parent + else: + newannotation = annotation + return newannotation + + class PositionModifier(object): """A start_pos modifier for the fast parser.""" def __init__(self): @@ -865,9 +879,12 @@ class Function(ClassOrFunc): return bool(self.yields) def annotation(self): + if self.children[0] == "lambda": + # lambda functions have no annotation + return None try: if self.children[3] == "->": - return self.children[4] + return _fix_forward_reference(self.children[4]) assert self.children[3] == ":" except IndexError: return None @@ -1409,7 +1426,8 @@ class Param(BaseNode): if is_node(tfpdef, 'tfpdef'): assert tfpdef.children[1] == ":" assert len(tfpdef.children) == 3 - return tfpdef.children[2] + annotation = tfpdef.children[2] + return _fix_forward_reference(annotation) else: return None diff --git a/test/completion/pep0484.py b/test/completion/pep0484.py index 52550405..6a7ce6ce 100644 --- a/test/completion/pep0484.py +++ b/test/completion/pep0484.py @@ -68,3 +68,23 @@ def return_annotation_and_docstring_different() -> str: #? str() return_annotation_and_docstring_different() + + +def annotation_forward_reference(b: "B") -> "B": + #? B() + b + +#? B() +annotation_forward_reference(1) + +class B: + pass + + +class SelfReference: + def test(x: "SelfReference") -> "SelfReference": + #? SelfReference() + x + +#? SelfReference() +SelfReference().test()