mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 22:14:27 +08:00
Fix an issue with creating contexts.
This commit is contained in:
@@ -518,7 +518,7 @@ class Evaluator(object):
|
|||||||
search_global=True, is_goto=True
|
search_global=True, is_goto=True
|
||||||
)
|
)
|
||||||
|
|
||||||
def create_context(self, base_context, node, node_is_context=False):
|
def create_context(self, base_context, node, node_is_context=False, node_is_object=False):
|
||||||
def parent_scope(node):
|
def parent_scope(node):
|
||||||
while True:
|
while True:
|
||||||
node = node.parent
|
node = node.parent
|
||||||
@@ -534,7 +534,7 @@ class Evaluator(object):
|
|||||||
if n.type == 'comp_for':
|
if n.type == 'comp_for':
|
||||||
return n
|
return n
|
||||||
|
|
||||||
def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True):
|
def from_scope_node(scope_node, child_is_funcdef=None, is_nested=True, node_is_object=False):
|
||||||
if scope_node == base_node:
|
if scope_node == base_node:
|
||||||
return base_context
|
return base_context
|
||||||
|
|
||||||
@@ -554,7 +554,7 @@ class Evaluator(object):
|
|||||||
parent_context,
|
parent_context,
|
||||||
scope_node
|
scope_node
|
||||||
)
|
)
|
||||||
if is_nested:
|
if is_nested and not node_is_object:
|
||||||
return func.get_function_execution()
|
return func.get_function_execution()
|
||||||
return func
|
return func
|
||||||
elif scope_node.type == 'classdef':
|
elif scope_node.type == 'classdef':
|
||||||
@@ -580,4 +580,4 @@ class Evaluator(object):
|
|||||||
# object itself and not its contents.
|
# object itself and not its contents.
|
||||||
node = node.parent
|
node = node.parent
|
||||||
scope_node = parent_scope(node)
|
scope_node = parent_scope(node)
|
||||||
return from_scope_node(scope_node, is_nested=not node_is_context)
|
return from_scope_node(scope_node, is_nested=True, node_is_object=node_is_object)
|
||||||
|
|||||||
@@ -46,7 +46,8 @@ class MixedObject(object):
|
|||||||
|
|
||||||
self._context = module_context.create_context(
|
self._context = module_context.create_context(
|
||||||
tree_name.parent,
|
tree_name.parent,
|
||||||
node_is_context=True
|
node_is_context=True,
|
||||||
|
node_is_object=True
|
||||||
)
|
)
|
||||||
|
|
||||||
# We have to overwrite everything that has to do with trailers, name
|
# We have to overwrite everything that has to do with trailers, name
|
||||||
|
|||||||
@@ -55,8 +55,8 @@ class Context(object):
|
|||||||
return self.evaluator.find_types(
|
return self.evaluator.find_types(
|
||||||
self, name_or_str, name_context, position, search_global, is_goto)
|
self, name_or_str, name_context, position, search_global, is_goto)
|
||||||
|
|
||||||
def create_context(self, node, node_is_context=False):
|
def create_context(self, node, node_is_context=False, node_is_object=False):
|
||||||
return self.evaluator.create_context(self, node, node_is_context)
|
return self.evaluator.create_context(self, node, node_is_context, node_is_object)
|
||||||
|
|
||||||
def is_class(self):
|
def is_class(self):
|
||||||
return False
|
return False
|
||||||
|
|||||||
@@ -162,35 +162,35 @@ class NameFinder(object):
|
|||||||
return types
|
return types
|
||||||
|
|
||||||
|
|
||||||
def _name_to_types(evaluator, context, name):
|
def _name_to_types(evaluator, context, tree_name):
|
||||||
types = []
|
types = []
|
||||||
node = name.get_definition()
|
node = tree_name.get_definition()
|
||||||
if node.isinstance(tree.ForStmt):
|
if node.isinstance(tree.ForStmt):
|
||||||
types = pep0484.find_type_from_comment_hint_for(context, node, name)
|
types = pep0484.find_type_from_comment_hint_for(context, node, tree_name)
|
||||||
if types:
|
if types:
|
||||||
return types
|
return types
|
||||||
if node.isinstance(tree.WithStmt):
|
if node.isinstance(tree.WithStmt):
|
||||||
types = pep0484.find_type_from_comment_hint_with(context, node, name)
|
types = pep0484.find_type_from_comment_hint_with(context, node, tree_name)
|
||||||
if types:
|
if types:
|
||||||
return types
|
return types
|
||||||
if node.type in ('for_stmt', 'comp_for'):
|
if node.type in ('for_stmt', 'comp_for'):
|
||||||
try:
|
try:
|
||||||
types = context.predefined_names[node][name.value]
|
types = context.predefined_names[node][tree_name.value]
|
||||||
except KeyError:
|
except KeyError:
|
||||||
container_types = context.eval_node(node.children[3])
|
container_types = context.eval_node(node.children[3])
|
||||||
for_types = iterable.py__iter__types(evaluator, container_types, node.children[3])
|
for_types = iterable.py__iter__types(evaluator, container_types, node.children[3])
|
||||||
types = check_tuple_assignments(evaluator, for_types, name)
|
types = check_tuple_assignments(evaluator, for_types, tree_name)
|
||||||
elif node.isinstance(tree.ExprStmt):
|
elif node.isinstance(tree.ExprStmt):
|
||||||
types = _remove_statements(evaluator, context, node, name)
|
types = _remove_statements(evaluator, context, node, tree_name)
|
||||||
elif node.isinstance(tree.WithStmt):
|
elif node.isinstance(tree.WithStmt):
|
||||||
types = context.eval_node(node.node_from_name(name))
|
types = context.eval_node(node.node_from_name(tree_name))
|
||||||
elif isinstance(node, tree.Import):
|
elif isinstance(node, tree.Import):
|
||||||
types = imports.infer_import(context, name)
|
types = imports.infer_import(context, tree_name)
|
||||||
elif node.type in ('funcdef', 'classdef'):
|
elif node.type in ('funcdef', 'classdef'):
|
||||||
types = _apply_decorators(evaluator, context, node)
|
types = _apply_decorators(evaluator, context, node)
|
||||||
elif node.type == 'global_stmt':
|
elif node.type == 'global_stmt':
|
||||||
context = evaluator.create_context(context, name)
|
context = evaluator.create_context(context, tree_name)
|
||||||
finder = NameFinder(evaluator, context, context, str(name))
|
finder = NameFinder(evaluator, context, context, str(tree_name))
|
||||||
filters = finder.get_filters(search_global=True)
|
filters = finder.get_filters(search_global=True)
|
||||||
# For global_stmt lookups, we only need the first possible scope,
|
# For global_stmt lookups, we only need the first possible scope,
|
||||||
# which means the function itself.
|
# which means the function itself.
|
||||||
@@ -200,7 +200,7 @@ def _name_to_types(evaluator, context, name):
|
|||||||
# TODO an exception can also be a tuple. Check for those.
|
# TODO an exception can also be a tuple. Check for those.
|
||||||
# TODO check for types that are not classes and add it to
|
# TODO check for types that are not classes and add it to
|
||||||
# the static analysis report.
|
# the static analysis report.
|
||||||
exceptions = context.eval_node(name.get_previous_sibling().get_previous_sibling())
|
exceptions = context.eval_node(tree_name.get_previous_sibling().get_previous_sibling())
|
||||||
types = unite(
|
types = unite(
|
||||||
evaluator.execute(t, param.ValuesArguments([]))
|
evaluator.execute(t, param.ValuesArguments([]))
|
||||||
for t in exceptions
|
for t in exceptions
|
||||||
|
|||||||
@@ -15,3 +15,16 @@ def test_empty_init():
|
|||||||
class X(object): pass
|
class X(object): pass
|
||||||
X(''')
|
X(''')
|
||||||
assert Script(code).completions()
|
assert Script(code).completions()
|
||||||
|
|
||||||
|
|
||||||
|
def test_in_empty_space():
|
||||||
|
code = dedent('''\
|
||||||
|
class X(object):
|
||||||
|
def __init__(self):
|
||||||
|
hello
|
||||||
|
''')
|
||||||
|
comps = Script(code, 3, 7).completions()
|
||||||
|
self, = [c for c in comps if c.name == 'self']
|
||||||
|
assert self.name == 'self'
|
||||||
|
def_, = self._goto_definitions()
|
||||||
|
assert def_.name == 'X'
|
||||||
|
|||||||
Reference in New Issue
Block a user