From fafd6b2ac6f1aec6fcdf377d5773d40d814a5f0a Mon Sep 17 00:00:00 2001 From: Dave Halter Date: Wed, 26 Jun 2019 15:04:46 +0200 Subject: [PATCH] Keyword completions are no longer possible directly after a number, fixes #1085 --- jedi/api/completion.py | 5 ++++- test/completion/basic.py | 6 ++++-- test/completion/classes.py | 2 +- test/test_api/test_api.py | 9 ++++++--- test/test_api/test_completion.py | 18 +++++++++++++++++- 5 files changed, 32 insertions(+), 8 deletions(-) diff --git a/jedi/api/completion.py b/jedi/api/completion.py index 5cae004e..48f002ba 100644 --- a/jedi/api/completion.py +++ b/jedi/api/completion.py @@ -171,7 +171,10 @@ class Completion: elif type_ == 'for_stmt': allowed_transitions.append('else') - completion_names = list(self._get_keyword_completion_names(allowed_transitions)) + completion_names = [] + current_line = self._code_lines[self._position[0] - 1][:self._position[1]] + if not current_line or current_line[-1] in ' \t.;': + completion_names += self._get_keyword_completion_names(allowed_transitions) if any(t in allowed_transitions for t in (PythonTokenTypes.NAME, PythonTokenTypes.INDENT)): diff --git a/test/completion/basic.py b/test/completion/basic.py index eaea8061..91e7f336 100644 --- a/test/completion/basic.py +++ b/test/completion/basic.py @@ -18,10 +18,12 @@ int(str) str.. #? [] a(0):. -#? 2 ['and', 'or', 'if', 'is', 'in', 'not'] +#? 2 [] 0x0 -#? ['and', 'or', 'if', 'is', 'in', 'not'] +#? [] 1j +#? ['and', 'or', 'if', 'is', 'in', 'not'] +1j x = None() #? x diff --git a/test/completion/classes.py b/test/completion/classes.py index 92d6b5bb..6ab4031b 100644 --- a/test/completion/classes.py +++ b/test/completion/classes.py @@ -279,7 +279,7 @@ V(1).c() V(1).d() # Only keywords should be possible to complete. #? ['is', 'in', 'not', 'and', 'or', 'if'] -V(1).d() +V(1).d() # ----------------- diff --git a/test/test_api/test_api.py b/test/test_api/test_api.py index 649cad57..af7b9e7e 100644 --- a/test/test_api/test_api.py +++ b/test/test_api/test_api.py @@ -73,7 +73,7 @@ def _check_number(Script, source, result='float'): def test_completion_on_number_literals(Script): # No completions on an int literal (is a float). - assert [c.name for c in Script('1.').completions()] \ + assert [c.name for c in Script('1. ').completions()] \ == ['and', 'if', 'in', 'is', 'not', 'or'] # Multiple points after an int literal basically mean that there's a float @@ -109,9 +109,12 @@ def test_completion_on_complex_literals(Script): _check_number(Script, '1j.', 'complex') _check_number(Script, '44.j.', 'complex') _check_number(Script, '4.0j.', 'complex') - # No dot no completion - I thought, but 4j is actually a literall after + # No dot no completion - I thought, but 4j is actually a literal after # which a keyword like or is allowed. Good times, haha! - assert ({c.name for c in Script('4j').completions()} == + # However this has been disabled again, because it apparently annoyed + # users. So no completion after j without a space :) + assert not Script('4j').completions() + assert ({c.name for c in Script('4j ').completions()} == {'if', 'and', 'in', 'is', 'not', 'or'}) diff --git a/test/test_api/test_completion.py b/test/test_api/test_completion.py index 01aeddf3..ccf77809 100644 --- a/test/test_api/test_completion.py +++ b/test/test_api/test_completion.py @@ -119,7 +119,8 @@ def test_generator(Script): def test_in_comment(Script): assert Script(" # Comment").completions() - assert Script("max_attr_value = int(2) # Cast to int for spe").completions() + # TODO this is a bit ugly, that the behaviors in comments are different. + assert not Script("max_attr_value = int(2) # Cast to int for spe").completions() def test_async(Script, environment): @@ -140,3 +141,18 @@ def test_async(Script, environment): def test_with_stmt_error_recovery(Script): assert Script('with open('') as foo: foo.\na', line=1).completions() + + +@pytest.mark.parametrize( + 'code, has_keywords', ( + ('', True), + ('x;', True), + ('1', False), + ('1 ', True), + ('1\t', True), + ('1\n', True), + ('1\\\n', True), + ) +) +def test_keyword_completion(Script, code, has_keywords): + assert has_keywords == any(x.is_keyword for x in Script(code).completions())