mirror of
https://github.com/davidhalter/jedi.git
synced 2025-12-06 14:04:26 +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
|
||||
)
|
||||
|
||||
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):
|
||||
while True:
|
||||
node = node.parent
|
||||
@@ -534,7 +534,7 @@ class Evaluator(object):
|
||||
if n.type == 'comp_for':
|
||||
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:
|
||||
return base_context
|
||||
|
||||
@@ -554,7 +554,7 @@ class Evaluator(object):
|
||||
parent_context,
|
||||
scope_node
|
||||
)
|
||||
if is_nested:
|
||||
if is_nested and not node_is_object:
|
||||
return func.get_function_execution()
|
||||
return func
|
||||
elif scope_node.type == 'classdef':
|
||||
@@ -580,4 +580,4 @@ class Evaluator(object):
|
||||
# object itself and not its contents.
|
||||
node = node.parent
|
||||
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(
|
||||
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
|
||||
|
||||
@@ -55,8 +55,8 @@ class Context(object):
|
||||
return self.evaluator.find_types(
|
||||
self, name_or_str, name_context, position, search_global, is_goto)
|
||||
|
||||
def create_context(self, node, node_is_context=False):
|
||||
return self.evaluator.create_context(self, node, node_is_context)
|
||||
def create_context(self, node, node_is_context=False, node_is_object=False):
|
||||
return self.evaluator.create_context(self, node, node_is_context, node_is_object)
|
||||
|
||||
def is_class(self):
|
||||
return False
|
||||
|
||||
@@ -162,35 +162,35 @@ class NameFinder(object):
|
||||
return types
|
||||
|
||||
|
||||
def _name_to_types(evaluator, context, name):
|
||||
def _name_to_types(evaluator, context, tree_name):
|
||||
types = []
|
||||
node = name.get_definition()
|
||||
node = tree_name.get_definition()
|
||||
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:
|
||||
return types
|
||||
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:
|
||||
return types
|
||||
if node.type in ('for_stmt', 'comp_for'):
|
||||
try:
|
||||
types = context.predefined_names[node][name.value]
|
||||
types = context.predefined_names[node][tree_name.value]
|
||||
except KeyError:
|
||||
container_types = context.eval_node(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):
|
||||
types = _remove_statements(evaluator, context, node, name)
|
||||
types = _remove_statements(evaluator, context, node, tree_name)
|
||||
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):
|
||||
types = imports.infer_import(context, name)
|
||||
types = imports.infer_import(context, tree_name)
|
||||
elif node.type in ('funcdef', 'classdef'):
|
||||
types = _apply_decorators(evaluator, context, node)
|
||||
elif node.type == 'global_stmt':
|
||||
context = evaluator.create_context(context, name)
|
||||
finder = NameFinder(evaluator, context, context, str(name))
|
||||
context = evaluator.create_context(context, tree_name)
|
||||
finder = NameFinder(evaluator, context, context, str(tree_name))
|
||||
filters = finder.get_filters(search_global=True)
|
||||
# For global_stmt lookups, we only need the first possible scope,
|
||||
# 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 check for types that are not classes and add it to
|
||||
# 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(
|
||||
evaluator.execute(t, param.ValuesArguments([]))
|
||||
for t in exceptions
|
||||
|
||||
@@ -15,3 +15,16 @@ def test_empty_init():
|
||||
class X(object): pass
|
||||
X(''')
|
||||
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