diff --git a/jedi/api/classes.py b/jedi/api/classes.py index 79c94dbf..0380d544 100644 --- a/jedi/api/classes.py +++ b/jedi/api/classes.py @@ -4,7 +4,6 @@ These classes are the much bigger part of the whole API, because they contain the interesting information about completion and goto operations. """ import warnings -from itertools import chain import re from jedi._compatibility import unicode @@ -19,21 +18,23 @@ from jedi.evaluate import iterable from jedi.evaluate import imports from jedi.evaluate import compiled from jedi.evaluate.filters import ParamName -from jedi.evaluate.finder import filter_definition_names from jedi.api.keywords import KeywordName -def defined_names(evaluator, scope): +def _sort_names_by_start_pos(names): + return sorted(names, key=lambda s: s.start_pos or (0, 0)) + + +def defined_names(evaluator, context): """ List sub-definitions (e.g., methods in class). :type scope: Scope :rtype: list of Definition """ - dct = scope.names_dict - names = list(chain.from_iterable(dct.values())) - names = filter_definition_names(names, scope) - return [Definition(evaluator, d) for d in sorted(names, key=lambda s: s.start_pos)] + filter = next(context.get_filters(search_global=True)) + names = [name for name in filter.values()] + return [Definition(evaluator, n) for n in _sort_names_by_start_pos(names)] class BaseDefinition(object): @@ -169,8 +170,14 @@ class BaseDefinition(object): name = list(name.infer())[0].name except IndexError: pass - yield name.string_name - name.api_type + + if name.api_type == 'module': + module_context, = name.infer() + for n in reversed(module_context.py__name__().split('.')): + yield n + else: + yield name.string_name + parent_context = name.parent_context while parent_context is not None: try: @@ -181,8 +188,7 @@ class BaseDefinition(object): except AttributeError: pass else: - # TODO this main clause seems strange. - for name in (method() or '__main__').split('.'): + for name in reversed(method().split('.')): yield name parent_context = parent_context.parent_context return reversed(list(to_reverse())) @@ -640,12 +646,10 @@ class Definition(BaseDefinition): :rtype: list of Definition """ - defs = self._follow_statements_imports() - # For now we don't want base classes or evaluate decorators. - defs = [d.base if isinstance(d, (er.Class, er.Function)) else d for d in defs] - iterable = (defined_names(self._evaluator, d) for d in defs) - iterable = list(iterable) - return list(chain.from_iterable(iterable)) + defs = self._name.infer() + return _sort_names_by_start_pos( + common.unite(defined_names(self._evaluator, d) for d in defs) + ) def is_definition(self): """ diff --git a/jedi/evaluate/__init__.py b/jedi/evaluate/__init__.py index 9a52ec66..4fbcdc62 100644 --- a/jedi/evaluate/__init__.py +++ b/jedi/evaluate/__init__.py @@ -62,7 +62,6 @@ that are not used are just being ignored. import copy import sys -from itertools import chain from jedi.parser import tree from jedi import debug diff --git a/jedi/evaluate/iterable.py b/jedi/evaluate/iterable.py index 6fb52d06..ca4b4448 100644 --- a/jedi/evaluate/iterable.py +++ b/jedi/evaluate/iterable.py @@ -166,7 +166,7 @@ class Generator(GeneratorMixin, context.Context): """Handling of `yield` functions.""" def __init__(self, evaluator, func_execution_context): - super(Generator, self).__init__(evaluator) + super(Generator, self).__init__(evaluator, parent_context=evaluator.BUILTINS) self._func_execution_context = func_execution_context def py__iter__(self): diff --git a/jedi/evaluate/representation.py b/jedi/evaluate/representation.py index c1446652..d863584c 100644 --- a/jedi/evaluate/representation.py +++ b/jedi/evaluate/representation.py @@ -538,7 +538,7 @@ class ModuleContext(use_metaclass(CachedMetaClass, context.TreeContext)): def py__name__(self): for name, module in self.evaluator.modules.items(): - if module == self: + if module == self and name != '': return name return '__main__' diff --git a/test/test_api/test_defined_names.py b/test/test_api/test_defined_names.py index aae1f6ca..da6f25a7 100644 --- a/test/test_api/test_defined_names.py +++ b/test/test_api/test_defined_names.py @@ -55,7 +55,7 @@ class TestDefinedNames(TestCase): subdefinitions = definitions[0].defined_names() self.assert_definition_names(subdefinitions, ['f', 'g']) self.assertEqual([d.full_name for d in subdefinitions], - ['Class.f', 'Class.g']) + ['__main__.Class.f', '__main__.Class.g']) def test_nested_class(self): definitions = self.check_defined_names("""