Skip to content

Commit 9de3241

Browse files
committed
Editor: Fix dot completions and preserve file ones that start with numbers
1 parent 4246562 commit 9de3241

File tree

3 files changed

+82
-4
lines changed

3 files changed

+82
-4
lines changed

spyder/plugins/editor/widgets/base.py

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -909,7 +909,8 @@ def select_completion_list(self):
909909
self.completion_widget.item_selected()
910910

911911
def insert_completion(self, completion, completion_position):
912-
"""Insert a completion into the editor.
912+
"""
913+
Insert a completion into the editor.
913914
914915
completion_position is where the completion was generated.
915916
@@ -944,15 +945,18 @@ def insert_completion(self, completion, completion_position):
944945
text = completion['insertText']
945946
text = to_text_string(text)
946947

947-
# Get word on the left of the cursor.
948-
result = self.get_current_word_and_position(completion=True)
948+
# Get word to the left of the cursor.
949+
result = self.get_current_word_and_position(
950+
completion=True, valid_python_variable=False)
949951
if result is not None:
950952
current_text, start_position = result
951953
end_position = start_position + len(current_text)
954+
952955
# Check if the completion position is in the expected range
953956
if not start_position <= completion_position <= end_position:
954957
return
955958
cursor.setPosition(start_position)
959+
956960
# Remove the word under the cursor
957961
cursor.setPosition(end_position,
958962
QTextCursor.KeepAnchor)

spyder/plugins/editor/widgets/tests/test_introspection.py

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@
2323
# Local imports
2424
from spyder.config.base import running_in_ci, running_in_ci_with_conda
2525
from spyder.config.utils import is_anaconda
26+
from spyder.plugins.completion.api import (
27+
CompletionRequestTypes, CompletionItemKind)
28+
from spyder.plugins.completion.providers.languageserver.providers.utils import (
29+
path_as_uri)
2630
from spyder.plugins.completion.providers.kite.utils.status import (
2731
check_if_kite_installed, check_if_kite_running)
2832
from spyder.py3compat import PY2
@@ -1178,5 +1182,75 @@ def test_completions_environment(completions_codeeditor, qtbot, tmpdir):
11781182
completion_plugin.after_configuration_update([])
11791183

11801184

1185+
@pytest.mark.slow
1186+
@pytest.mark.order(1)
1187+
@flaky(max_runs=5)
1188+
def test_dot_completions(completions_codeeditor, qtbot):
1189+
"""
1190+
Test that completions after a dot are working as expected.
1191+
1192+
This is a regression test for issue spyder-ide/spyder#20285
1193+
"""
1194+
code_editor, _ = completions_codeeditor
1195+
completion = code_editor.completion_widget
1196+
1197+
# Import module and check completions are shown for it after writing a dot
1198+
# after it
1199+
qtbot.keyClicks(code_editor, "import math")
1200+
qtbot.keyPress(code_editor, Qt.Key_Enter)
1201+
1202+
qtbot.wait(500)
1203+
assert not completion.isVisible()
1204+
1205+
with qtbot.waitSignal(completion.sig_show_completions, timeout=10000):
1206+
qtbot.keyClicks(code_editor, "math.")
1207+
1208+
qtbot.wait(500)
1209+
assert completion.isVisible()
1210+
1211+
1212+
@pytest.mark.slow
1213+
@pytest.mark.order(1)
1214+
def test_completions_for_files_that_start_with_numbers(
1215+
mock_completions_codeeditor, qtbot):
1216+
"""
1217+
Test that completions for files that start with numbers are handled as
1218+
expected.
1219+
1220+
This is a regression test for issue spyder-ide/spyder#20156
1221+
"""
1222+
code_editor, mock_response = mock_completions_codeeditor
1223+
completion = code_editor.completion_widget
1224+
file_name = '000_testing.txt'
1225+
1226+
# Set text to complete and move cursor to the position we want to ask for
1227+
# completions.
1228+
qtbot.keyClicks(code_editor, "'0'")
1229+
code_editor.moveCursor(QTextCursor.PreviousCharacter)
1230+
qtbot.wait(500)
1231+
1232+
# Complete '0' -> '000_testing.txt'
1233+
mock_response.side_effect = lambda lang, method, params: {'params': [{
1234+
'label': f'{file_name}',
1235+
'kind': CompletionItemKind.FILE,
1236+
'sortText': (0, f'a{file_name}'),
1237+
'insertText': f'{file_name}',
1238+
'data': {'doc_uri': path_as_uri(__file__)},
1239+
'detail': '',
1240+
'documentation': '',
1241+
'filterText': f'{file_name}',
1242+
'insertTextFormat': 1,
1243+
'provider': 'LSP',
1244+
'resolve': True
1245+
}]} if method == CompletionRequestTypes.DOCUMENT_COMPLETION else None
1246+
1247+
with qtbot.waitSignal(completion.sig_show_completions,
1248+
timeout=10000):
1249+
qtbot.keyPress(code_editor, Qt.Key_Tab, delay=300)
1250+
1251+
qtbot.wait(500)
1252+
assert code_editor.get_text_with_eol() == f"'{file_name}'"
1253+
1254+
11811255
if __name__ == '__main__':
11821256
pytest.main(['test_introspection.py', '--run-slow'])

spyder/widgets/mixins.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1083,7 +1083,7 @@ def is_special_character(move):
10831083
startpos = cursor.selectionStart()
10841084

10851085
# Find a valid Python variable name
1086-
if valid_python_variable and not completion:
1086+
if valid_python_variable:
10871087
match = re.findall(r'([^\d\W]\w*)', text, re.UNICODE)
10881088
if not match:
10891089
# This is assumed in several places of our codebase,

0 commit comments

Comments
 (0)