mirror of
https://github.com/davidhalter/jedi.git
synced 2026-03-05 08:54:15 +08:00
Annotations can contain forward references even if they are not a string anymore
Since Python 3.7 this behavior can be imported with from future import __annotations
This commit is contained in:
@@ -216,5 +216,5 @@ class ModuleContext(TreeContext):
|
|||||||
return "<%s: %s@%s-%s is_stub=%s>" % (
|
return "<%s: %s@%s-%s is_stub=%s>" % (
|
||||||
self.__class__.__name__, self._string_name,
|
self.__class__.__name__, self._string_name,
|
||||||
self.tree_node.start_pos[0], self.tree_node.end_pos[0],
|
self.tree_node.start_pos[0], self.tree_node.end_pos[0],
|
||||||
self._path.endswith('.pyi')
|
self._path is not None and self._path.endswith('.pyi')
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ class NameFinder(object):
|
|||||||
ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef')
|
ancestor = search_ancestor(origin_scope, 'funcdef', 'classdef')
|
||||||
if ancestor is not None:
|
if ancestor is not None:
|
||||||
colon = ancestor.children[-2]
|
colon = ancestor.children[-2]
|
||||||
if position < colon.start_pos:
|
if position is not None and position < colon.start_pos:
|
||||||
if lambdef is None or position < lambdef.children[-2].start_pos:
|
if lambdef is None or position < lambdef.children[-2].start_pos:
|
||||||
position = ancestor.start_pos
|
position = ancestor.start_pos
|
||||||
|
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ def _evaluate_annotation_string(context, string, index=None):
|
|||||||
context_set = context.eval_node(node)
|
context_set = context.eval_node(node)
|
||||||
if index is not None:
|
if index is not None:
|
||||||
context_set = context_set.filter(
|
context_set = context_set.filter(
|
||||||
lambda context: context.array_type == u'tuple'
|
lambda context: context.array_type == u'tuple' # noqa
|
||||||
and len(list(context.py__iter__())) >= index
|
and len(list(context.py__iter__())) >= index
|
||||||
).py__getitem__(index)
|
).py__getitem__(index)
|
||||||
return context_set.execute_evaluated()
|
return context_set.execute_evaluated()
|
||||||
|
|||||||
@@ -196,9 +196,17 @@ def eval_atom(context, atom):
|
|||||||
) or atom
|
) or atom
|
||||||
if stmt.type == 'lambdef':
|
if stmt.type == 'lambdef':
|
||||||
stmt = atom
|
stmt = atom
|
||||||
|
position = stmt.start_pos
|
||||||
|
if _is_annotation_name(atom):
|
||||||
|
# Since Python 3.7 (with from __future__ import annotations),
|
||||||
|
# annotations are essentially strings and can reference objects
|
||||||
|
# that are defined further down in code. Therefore just set the
|
||||||
|
# position to None, so the finder will not try to stop at a certain
|
||||||
|
# position in the module.
|
||||||
|
position = None
|
||||||
return context.py__getattribute__(
|
return context.py__getattribute__(
|
||||||
name_or_str=atom,
|
name_or_str=atom,
|
||||||
position=stmt.start_pos,
|
position=position,
|
||||||
search_global=True
|
search_global=True
|
||||||
)
|
)
|
||||||
elif atom.type == 'keyword':
|
elif atom.type == 'keyword':
|
||||||
@@ -410,6 +418,22 @@ def _eval_comparison(evaluator, context, left_contexts, operator, right_contexts
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def _is_annotation_name(name):
|
||||||
|
ancestor = tree.search_ancestor(name, 'param', 'funcdef', 'expr_stmt')
|
||||||
|
if ancestor is None:
|
||||||
|
return False
|
||||||
|
|
||||||
|
if ancestor.type in ('param', 'funcdef'):
|
||||||
|
annotation = ancestor.annotation
|
||||||
|
if annotation is not None:
|
||||||
|
return annotation.start_pos <= name.start_pos < annotation.end_pos
|
||||||
|
elif ancestor.type == 'expr_stmt':
|
||||||
|
c = ancestor.children
|
||||||
|
if len(c) > 1 and c[1].type == 'annassign':
|
||||||
|
return c[1].start_pos <= name.start_pos < c[1].end_pos
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
def _is_tuple(context):
|
def _is_tuple(context):
|
||||||
return isinstance(context, iterable.Sequence) and context.array_type == 'tuple'
|
return isinstance(context, iterable.Sequence) and context.array_type == 'tuple'
|
||||||
|
|
||||||
@@ -497,7 +521,6 @@ def _remove_statements(evaluator, context, stmt, name):
|
|||||||
|
|
||||||
|
|
||||||
def tree_name_to_contexts(evaluator, context, tree_name):
|
def tree_name_to_contexts(evaluator, context, tree_name):
|
||||||
|
|
||||||
context_set = ContextSet()
|
context_set = ContextSet()
|
||||||
module_node = context.get_root_context().tree_node
|
module_node = context.get_root_context().tree_node
|
||||||
if module_node is not None:
|
if module_node is not None:
|
||||||
|
|||||||
Reference in New Issue
Block a user