From 10f5e15325dd065d2d1ffee35e96b3d36817b48c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 30 Dec 2015 23:05:01 +0100 Subject: [PATCH] I feel this is a nicer solution. Forward Reference busting should be part of the annotation resolving. It doesn not have anything to do with the typing module (and should indeed also happen if someone writes his own types outside of the typing module) --- jedi/evaluate/pep0484.py | 50 +++++++++++++++++++++----------------- test/completion/pep0484.py | 4 --- 2 files changed, 28 insertions(+), 26 deletions(-) diff --git a/jedi/evaluate/pep0484.py b/jedi/evaluate/pep0484.py index 5d0ec018..db80dd79 100644 --- a/jedi/evaluate/pep0484.py +++ b/jedi/evaluate/pep0484.py @@ -30,33 +30,45 @@ from jedi import debug def _evaluate_for_annotation(evaluator, annotation): if annotation is not None: - definitions = set() - module = annotation.get_parent_until() - for definition in evaluator.eval_element(annotation): - definitions |= \ - _fix_forward_reference(evaluator, definition, module) + dereferenced_annotation = _fix_forward_reference(evaluator, annotation) + definitions = evaluator.eval_element(dereferenced_annotation) return list(chain.from_iterable( evaluator.execute(d) for d in definitions)) else: return [] -def _fix_forward_reference(evaluator, item, module): - if (isinstance(item, compiled.CompiledObject) and - isinstance(item.obj, str)): +def _fix_forward_reference(evaluator, item): + """ + Gets something from the parse tree, and replaces any string literal + in there with the result of evaluating that string at the bottom of the + module + """ + if isinstance(item, tree.String): + compiledobjects = evaluator.eval_element(item) + assert len(compiledobjects) == 1 + compiledobject = list(compiledobjects)[0] try: - p = Parser( - load_grammar(), item.obj, start='eval_input') + p = Parser(load_grammar(), compiledobject.obj, start='eval_input') element = p.get_parsed_node() except ParseError: - debug.warning('Annotation not parsed: %s' % item.obj) - return set() + debug.warning('Annotation not parsed: %s' % compiledobject.obj) + return item else: + module = item.get_parent_until() p.position_modifier.line = module.end_pos[0] element.parent = module - return evaluator.eval_element(element) - else: - return set([item]) + dereferenced = _fix_forward_reference(evaluator, element) + return dereferenced + if isinstance(item, tree.Node): + newnode = tree.Node(item.type, []) + for child in item.children: + newchild = _fix_forward_reference(evaluator, child) + newchild.parent = newnode + newnode.children.append(newchild) + newnode.parent = item.parent + return newnode + return item @memoize_default(None, evaluator_is_first_arg=True) @@ -97,12 +109,6 @@ def get_types_for_typing_module(evaluator, typ, trailer): if not isinstance(indextypes, set): indextypes = set([indextypes]) - module = trailer.get_parent_until() - dereferencedindextypes = set() - for indextyp in indextypes: - dereferencedindextypes |= \ - _fix_forward_reference(evaluator, indextyp, module) - typing = _get_typing_replacement_module() factories = evaluator.find_types(typing, "factory") assert len(factories) == 1 @@ -117,7 +123,7 @@ def get_types_for_typing_module(evaluator, typ, trailer): compiled_classname = compiled.create(evaluator, typ.name.value) result = set() - for indextyp in dereferencedindextypes: + for indextyp in indextypes: result |= \ evaluator.execute_evaluated(factory, compiled_classname, indextyp) for singleresult in result: diff --git a/test/completion/pep0484.py b/test/completion/pep0484.py index fc08460f..298a7a4f 100644 --- a/test/completion/pep0484.py +++ b/test/completion/pep0484.py @@ -153,7 +153,3 @@ def function_with_assined_class_in_reference(x: X, y: "Y"): #? int() y Y = int - -def just_because_we_can(x: "flo" + "at"): - #? float() - x