Better context completions for finally/except/else/elif

Fixes #837
This commit is contained in:
Dave Halter
2017-09-15 00:48:56 +02:00
parent e389c61377
commit 63edbdcc5b
3 changed files with 67 additions and 0 deletions

View File

@@ -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:

View File

@@ -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

View File

@@ -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