diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 30510e8c..bb113810 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -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) diff --git a/jedi/evaluate/compiled/mixed.py b/jedi/evaluate/compiled/mixed.py index e4f903e9..2c9fa5a9 100644 --- a/jedi/evaluate/compiled/mixed.py +++ b/jedi/evaluate/compiled/mixed.py @@ -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 diff --git a/jedi/evaluate/context.py b/jedi/evaluate/context.py index 8a81428c..ac96e939 100644 --- a/jedi/evaluate/context.py +++ b/jedi/evaluate/context.py @@ -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 diff --git a/jedi/evaluate/finder.py b/jedi/evaluate/finder.py index 3cb2973a..b8cfd8a1 100644 --- a/jedi/evaluate/finder.py +++ b/jedi/evaluate/finder.py @@ -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 diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 5b910e37..a0d146a7 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -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'