diff --git a/jedi/api/__init__.py b/jedi/api/__init__.py index a966c702..2207fb64 100644 --- a/jedi/api/__init__.py +++ b/jedi/api/__init__.py @@ -133,7 +133,8 @@ class Script(object): # TODO this closure is ugly. it also doesn't work with # simple_complete (used for Interpreter), somehow redo. module = self._parser.module() - names, level, only_modules = helpers.check_error_statements(module, self._pos) + names, level, only_modules, unfinished_dotted = \ + helpers.check_error_statements(module, self._pos) completions = [] #print(importer.completion_names(self._evaluator, True)) if names is not None: @@ -144,13 +145,14 @@ class Script(object): # TODO this paragraph is necessary, but not sure it works. context = self._user_context.get_context() - - # print(next(self._user_context.get_context()), 'x') + if not next(context).startswith('.'): # skip the path if next(context) == 'from': # completion is just "import" if before stands from .. - completions += ((k, bs) for k in keywords.keyword_names('import')) - return completions + if unfinished_dotted: + return completions + else: + return [(k, bs) for k in keywords.keyword_names('import')] if isinstance(user_stmt, pr.Import): module = self._parser.module() @@ -286,7 +288,7 @@ class Script(object): return [] module = self._parser.module() - names, level, _ = helpers.check_error_statements(module, self._pos) + names, level, _, _ = helpers.check_error_statements(module, self._pos) if names: i = imports.get_importer(self._evaluator, names, module, level) return i.follow(self._evaluator) diff --git a/jedi/api/helpers.py b/jedi/api/helpers.py index f1f2c992..7288c496 100644 --- a/jedi/api/helpers.py +++ b/jedi/api/helpers.py @@ -39,7 +39,7 @@ def check_error_statements(module, pos): if error_statement.first_type in ('import_from', 'import_name') \ and error_statement.first_pos < pos <= error_statement.next_start_pos: return importer_from_error_statement(error_statement, pos) - return None, 0, False + return None, 0, False, False def importer_from_error_statement(error_statement, pos): @@ -51,12 +51,17 @@ def importer_from_error_statement(error_statement, pos): names = [] level = 0 only_modules = True + unfinished_dotted = False for typ, nodes in error_statement.stack: if typ == 'dotted_name': names += check_dotted(nodes) + if nodes[-1] == '.': + # An unfinished dotted_name + unfinished_dotted = True elif typ == 'import_name': if nodes[0].start_pos <= pos <= nodes[0].end_pos: - return None, 0, False + # We are on the import. + return None, 0, False, False elif typ == 'import_from': for node in nodes: if node.start_pos >= pos: @@ -70,4 +75,4 @@ def importer_from_error_statement(error_statement, pos): elif node == 'import': only_modules = False - return names, level, only_modules + return names, level, only_modules, unfinished_dotted diff --git a/test/completion/on_import.py b/test/completion/on_import.py index 0007cba5..18d82bdb 100644 --- a/test/completion/on_import.py +++ b/test/completion/on_import.py @@ -63,7 +63,7 @@ import datetime.date #? 21 ['import'] from import_tree.pkg import pkg -#? 22 ['import', 'mod1'] +#? 22 ['mod1'] from import_tree.pkg. import mod1 #? 17 ['mod1', 'mod2', 'random', 'pkg', 'rename1', 'rename2', 'recurse_class1', 'recurse_class2'] from import_tree. import pkg diff --git a/test/test_integration_import.py b/test/test_integration_import.py index ca6f37b8..6b5ad73a 100644 --- a/test/test_integration_import.py +++ b/test/test_integration_import.py @@ -74,6 +74,7 @@ def test_after_from(): completions = Script(source, column=column).completions() assert [c.name for c in completions] == result + check('\nfrom os. ', ['path']) check('\nfrom os ', ['import']) check('from os ', ['import']) check('\nfrom os import whatever', ['import'], len('from os im'))