Skip to content

Commit 2e9c380

Browse files
committed
Merge from 5.x: PR #20317
Fixes # 20282
2 parents c48f11f + 2bb3542 commit 2e9c380

File tree

2 files changed

+77
-14
lines changed

2 files changed

+77
-14
lines changed

spyder/plugins/editor/widgets/codeeditor.py

Lines changed: 18 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -511,7 +511,7 @@ def __init__(self, parent=None):
511511
self.format_on_save = False
512512
self.format_eventloop = QEventLoop(None)
513513
self.format_timer = QTimer(self)
514-
self.__cursor_position_before_format = 0
514+
self.__line_number_before_format = 0
515515

516516
# Mouse tracking
517517
self.setMouseTracking(True)
@@ -1781,10 +1781,6 @@ def handle_go_to_definition(self, position):
17811781
# -------------------------------------------------------------------------
17821782
def format_document_or_range(self):
17831783
"""Format current document or selected text."""
1784-
# Save current cursor position to restore it after the current text has
1785-
# been replaced by the auto-formatted one.
1786-
self.__cursor_position_before_format = self.textCursor().position()
1787-
17881784
if self.has_selected_text() and self.range_formatting_enabled:
17891785
self.format_document_range()
17901786
else:
@@ -1793,6 +1789,8 @@ def format_document_or_range(self):
17931789
@schedule_request(method=CompletionRequestTypes.DOCUMENT_FORMATTING)
17941790
def format_document(self):
17951791
"""Format current document."""
1792+
self.__line_number_before_format = self.textCursor().blockNumber()
1793+
17961794
if not self.formatting_enabled:
17971795
return
17981796
if self.formatting_in_progress:
@@ -1826,6 +1824,8 @@ def format_document(self):
18261824
@schedule_request(method=CompletionRequestTypes.DOCUMENT_RANGE_FORMATTING)
18271825
def format_document_range(self):
18281826
"""Format selected text."""
1827+
self.__line_number_before_format = self.textCursor().blockNumber()
1828+
18291829
if not self.range_formatting_enabled or not self.has_selected_text():
18301830
return
18311831
if self.formatting_in_progress:
@@ -1984,18 +1984,22 @@ def _apply_document_edits(self, edits):
19841984
# Insert formatted text in place of the previous one
19851985
cursor.insertText(merged_text)
19861986

1987-
# Don't run the lines below when testing because they give
1988-
# segfaults.
1989-
if not running_under_pytest():
1990-
# Restore previous cursor position and center it.
1991-
# Fixes spyder-ide/spyder#19958
1992-
cursor.setPosition(self.__cursor_position_before_format)
1993-
self.setTextCursor(cursor)
1994-
self.centerCursor()
1995-
19961987
# End text insertion
19971988
cursor.endEditBlock()
19981989

1990+
# Restore previous cursor line and center it.
1991+
# Fixes spyder-ide/spyder#19958
1992+
if self.__line_number_before_format < self.blockCount():
1993+
self.moveCursor(QTextCursor.Start)
1994+
cursor = self.textCursor()
1995+
cursor.movePosition(
1996+
QTextCursor.Down,
1997+
QTextCursor.MoveAnchor,
1998+
self.__line_number_before_format
1999+
)
2000+
self.setTextCursor(cursor)
2001+
self.centerCursor()
2002+
19992003
# ---- LSP: Code folding
20002004
# -------------------------------------------------------------------------
20012005
def compute_whitespace(self, line):

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

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,11 @@
99
# Standard library imports
1010
import os
1111
import os.path as osp
12+
import random
1213

1314
# Third party imports
1415
import pytest
16+
from qtpy.QtCore import Qt
1517
from qtpy.QtGui import QTextCursor
1618
from qtpy.QtWidgets import QMessageBox
1719
import yapf
@@ -257,3 +259,60 @@ def test_closing_document_formatting(
257259
code_editor = editorstack.load(str(file_path)).editor
258260

259261
assert code_editor.get_text_with_eol() == expected
262+
263+
264+
@pytest.mark.order(1)
265+
@pytest.mark.parametrize('formatter', [autopep8, black])
266+
def test_formatting_on_save(completions_editor, formatter, qtbot):
267+
"""
268+
Check that auto-formatting on save works as expected and that we restore
269+
the current line after doing it.
270+
271+
This includes a regression test for issue spyder-ide/spyder#19958
272+
"""
273+
file_path, editorstack, code_editor, completion_plugin = completions_editor
274+
text, expected = get_formatter_values(formatter, newline='\n')
275+
276+
# Set formatter
277+
editorstack.set_format_on_save(True)
278+
CONF.set(
279+
'completions',
280+
('provider_configuration', 'lsp', 'values', 'formatting'),
281+
formatter
282+
)
283+
284+
with qtbot.waitSignal(completion_plugin.sig_editor_rpc):
285+
completion_plugin.after_configuration_update([])
286+
qtbot.wait(2000)
287+
288+
# Set text in editor
289+
code_editor.set_text(text)
290+
291+
# Notify changes
292+
with qtbot.waitSignal(
293+
code_editor.completions_response_signal, timeout=30000):
294+
code_editor.document_did_change()
295+
296+
# Set a random current line
297+
current_line = random.randint(0, code_editor.blockCount())
298+
code_editor.moveCursor(QTextCursor.Start)
299+
cursor = code_editor.textCursor()
300+
cursor.movePosition(QTextCursor.Down, QTextCursor.MoveAnchor, current_line)
301+
code_editor.setTextCursor(cursor)
302+
qtbot.wait(500)
303+
304+
# Make a simple change to the file
305+
code_editor.moveCursor(QTextCursor.EndOfLine)
306+
qtbot.keyPress(code_editor, Qt.Key_Space)
307+
qtbot.wait(500)
308+
309+
# Save the file
310+
with qtbot.waitSignal(
311+
code_editor.completions_response_signal, timeout=30000):
312+
editorstack.save(force=True)
313+
qtbot.wait(500)
314+
315+
# Check that auto-formatting was applied on save and that we restored the
316+
# previous line.
317+
assert code_editor.get_text_with_eol() == expected
318+
assert code_editor.textCursor().blockNumber() == current_line

0 commit comments

Comments
 (0)