diff --git a/jedi/evaluate/imports.py b/jedi/evaluate/imports.py index 61548bf5..dd316196 100644 --- a/jedi/evaluate/imports.py +++ b/jedi/evaluate/imports.py @@ -422,6 +422,7 @@ class _Importer(object): :param only_modules: Indicates wheter it's possible to import a definition that is not defined in a module. """ + from jedi.evaluate import finder, representation as er names = [] if self.import_path: # flask @@ -438,7 +439,6 @@ class _Importer(object): if os.path.isdir(flaskext): names += self._get_module_names([flaskext]) - from jedi.evaluate import finder, representation as er for scope in self.follow(evaluator): # Non-modules are not completable. if not isinstance(scope, er.ModuleWrapper) and not (isinstance(scope, @@ -482,8 +482,10 @@ class _Importer(object): rel_path = os.path.join(self.get_relative_path(), '__init__.py') if os.path.exists(rel_path): - m = _load_module(self._evaluator, rel_path) - names += m.get_defined_names() + module = _load_module(self._evaluator, rel_path) + module = er.wrap(self._evaluator, module) + for names_dict in module.names_dicts(search_global=False): + names += chain.from_iterable(names_dict.values()) return names diff --git a/jedi/parser/tree.py b/jedi/parser/tree.py index 05e6ef78..586ad458 100644 --- a/jedi/parser/tree.py +++ b/jedi/parser/tree.py @@ -36,7 +36,6 @@ import textwrap from jedi._compatibility import (next, Python3Method, encoding, is_py3, literal_eval, use_metaclass, unicode) -from jedi import debug from jedi import cache @@ -530,37 +529,6 @@ class Scope(Simple, DocstringMixin): def is_scope(self): return True - @Python3Method - def get_defined_names(self): - """ - Get all defined names in this scope. Useful for autocompletion. - - >>> from jedi._compatibility import u - >>> from jedi.parser import Parser, load_grammar - >>> parser = Parser(load_grammar(), u(''' - ... a = x - ... b = y - ... b.c = z - ... ''')) - >>> parser.module.get_defined_names() - [, , ] - """ - def scan(children): - names = [] - for c in children: - if is_node(c, 'simple_stmt'): - names += chain.from_iterable( - [s.get_defined_names() for s in c.children - if isinstance(s, (ExprStmt, Import))]) - elif isinstance(c, (Function, Class)): - names.append(c.name) - elif isinstance(c, Flow) or is_node(c, 'suite', 'decorated'): - names += scan(c.children) - return names - - children = self.children - return scan(children) - @Python3Method def get_statement_for_position(self, pos, include_imports=False): checks = self.statements + self.asserts @@ -653,12 +621,6 @@ class SubModule(Scope, Module): """ self.global_names = names - def get_defined_names(self): - n = super(SubModule, self).get_defined_names() - # TODO uncomment - #n += self.global_names - return n - @property @cache.underscore_memoization def name(self): @@ -818,15 +780,6 @@ class Function(ClassOrFunc): except IndexError: return None - def get_defined_names(self): - n = super(Function, self).get_defined_names() - for p in self.params: - try: - n.append(p.get_name()) - except IndexError: - debug.warning("multiple names in param %s", n) - return n - def get_call_signature(self, width=72, func_name=None): """ Generate call signature of this function. @@ -958,9 +911,6 @@ class WithStmt(Flow): class Import(Simple): __slots__ = () - def get_all_import_names(self): - # TODO remove. do we even need this? - raise NotImplementedError def path_for_name(self, name): try: @@ -1104,6 +1054,7 @@ class KeywordStatement(Simple): `raise`, `return`, `yield`, `pass`, `continue`, `break`, `return`, `yield`. """ __slots__ = () + @property def keyword(self): return self.children[0].value diff --git a/test/test_parser/test_fast_parser.py b/test/test_parser/test_fast_parser.py index 80718031..793735da 100644 --- a/test/test_parser/test_fast_parser.py +++ b/test/test_parser/test_fast_parser.py @@ -56,7 +56,7 @@ def test_carriage_return_splitting(): ''')) source = source.replace('\n', '\r\n') p = FastParser(load_grammar(), source) - assert [str(n) for n in p.module.get_defined_names()] == ['Foo'] + assert [n.value for lst in p.module.names_dict.values() for n in lst] == ['Foo'] def test_change_and_undo():