diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 4ff935f7..559a4d3f 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -1,5 +1,7 @@ from parso.python import token from parso.python import tree +from parso.tree import search_ancestor, Leaf + from jedi import debug from jedi import settings from jedi.api import classes @@ -137,6 +139,38 @@ class Completion: allowed_keywords, allowed_tokens = \ helpers.get_possible_completion_types(grammar._pgen_grammar, self.stack) + if 'if' in allowed_keywords: + leaf = self._module_node.get_leaf_for_position(self._position, include_prefixes=True) + previous_leaf = leaf.get_previous_leaf() + + indent = self._position[1] + if not (leaf.start_pos <= self._position <= leaf.end_pos): + indent = leaf.start_pos[1] + + if previous_leaf is not None: + stmt = previous_leaf + while True: + stmt = search_ancestor( + stmt, 'if_stmt', 'for_stmt', 'while_stmt', 'try_stmt', + 'error_node', + ) + if stmt is None: + break + + type_ = stmt.type + if type_ == 'error_node': + first = stmt.children[0] + if isinstance(first, Leaf): + type_ = first.value + '_stmt' + # Compare indents + if stmt.start_pos[1] == indent: + if type_ == 'if_stmt': + allowed_keywords += ['elif', 'else'] + elif type_ == 'try_stmt': + allowed_keywords += ['except', 'finally', 'else'] + elif type_ == 'for_stmt': + allowed_keywords.append('else') + completion_names = list(self._get_keyword_completion_names(allowed_keywords)) if token.NAME in allowed_tokens or token.INDENT in allowed_tokens: diff --git a/test/completion/completion.py b/test/completion/completion.py index 91bc2aa5..6700fa68 100644 --- a/test/completion/completion.py +++ b/test/completion/completion.py @@ -24,3 +24,27 @@ class MyClass: tuple, ): return 1 + + +if x: + pass +#? ['else'] +else + +try: + pass +#? ['except', 'Exception'] +except + +try: + pass +#? 6 ['except', 'Exception'] +except AttributeError: + pass +#? ['finally'] +finally + +for x in y: + pass +#? ['else'] +else diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index eb65f4f6..6cd7e04b 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -38,3 +38,12 @@ def test_indent_context(): code = 'if 1:\nisinstanc' comp, = Script(code).completions() assert comp.name == 'isinstance' + + +def test_keyword_context(): + def get_names(*args, **kwargs): + return [d.name for d in Script(*args, **kwargs).completions()] + + names = get_names('if 1:\n pass\n') + assert 'if' in names + assert 'elif' in names