Add support for format_on_save only changed lines#49964
Conversation
format_on_save save only changed linesformat_on_save only changed lines
c0cb755 to
4e49c0f
Compare
4e49c0f to
35d18a5
Compare
|
Perhaps there is a better name for the 'modifiedlines' option. |
|
I get this, when trying to use it with ty for Python. Maybe this should be handled, instead of an error? When trying with Ruff, it just formats like normal without throwing any errors, so that also doesnt work :/ Seems to work for C++ though. |
Maybe take inspiration from VSCode They have a mode with fallback and one without called modificationsIfAvailable and modifications. That sounds pretty good |
🧪 Testing: LSP Range Formatting Support StatusSince let's track how different Language Servers and Formatters behave with 🧪 checklistLegend:
📦 Built-in Languages
🧩 Popular Extensions
How to test:
|
|
It seems VSCode has some workaround for languages that don't support range formatting. It works for Ty and Ruff for them... Hmm, doesnt seem like it https://github.com/microsoft/vscode/blob/f8f3e01afce0f5aea3acc6b87befe91a27aafa3f/src/vs/workbench/contrib/codeEditor/browser/saveParticipants.ts#L254C13-L254C14 |
488904e to
3f27878
Compare
@UnknownDK That is a great suggestion! I will finish the follow-up commits. |
Maybe because ty isn't a formater? According to Astral's official docs, |
Makes sense. My settings might be weird. I have however never had any warnings before for ty. |
e307b3f to
3259f88
Compare
166469e to
140371b
Compare
1d50c57 to
25fcdd4
Compare
|
Hi @SomeoneToIgnore, just checking in on this PR. Would a demo video help with the review? I will keep resolve the conflict if needed. |
|
Hey, sorry for the delay, I am just buried under all the rest of the PRs and trying to deal with the smaller ones first. To note, I disagree with #49964 (comment) as the only related detail is the formatting, the functionality is rather different, IMO, as this one includes VCS interactions. |
SomeoneToIgnore
left a comment
There was a problem hiding this comment.
FWIW I've even started with the PR at some point, if you're so eager to get some review...
(Re-posting for context — accidentally deleted the original)
|
|
Got it, thanks for the update. |
|
Heads up: |
SomeoneToIgnore
left a comment
There was a problem hiding this comment.
Overall, looks rather nice, thank you for coming up with this.
One major question I have is whether we can split that into two PRs instead: one for the whitespaces + ranges and another for the git diff-related logic.
7d9dcc2 to
41b4d7b
Compare
5718b61 to
9c7098a
Compare
|
Just split for the whitespaces + ranges into #53942 |
f2dc9ea to
9b57ecd
Compare
SomeoneToIgnore
left a comment
There was a problem hiding this comment.
Thank you, this looks much cleaner and now I could focus on the impl details better.
Had left a few comments, this seems to need a good pass on lsp_store.rs new code at least.
46339e6 to
5368336
Compare
cfc6a89 to
45e41d1
Compare
7813957 to
dbcbf9f
Compare
Summary
Introduces
format_on_savevariants that format only modified lines, limiting formatting to lines changed since the last commit. This prevents massive diffs when editing legacy codebases. Aligns with VS Code'seditor.formatOnSaveModenaming:"modifications"— formats only git-diffed lines. Requires source control; skips formatting if no diff is available."modifications_if_available"— formats only git-diffed lines, falling back to full-file formatting for untracked files, when source control is unavailable, or when the LSP does not support range formatting.Also supports importing equivalent VS Code settings (
formatOnSaveMode).This PR uses the range-based whitespace/newline infrastructure from the dependency PR above.
Changes
New settings, modified ranges computation, VS Code import
New settings (
language.rs,default.json,all-settings.md)Two new
FormatOnSavevariants:ModificationsandModificationsIfAvailable.Modified ranges computation (
items.rs)compute_format_decision()— readsformat_on_savesetting across all buffers, determines whether to use ranged formatting (Ranges), full formatting (Full), or skip (Skip).compute_modified_ranges()— extracts modified line ranges from git diff hunks viaBufferDiffSnapshot.is_empty_range()— helper to detect deletion-only hunks that produce no formatable content.The
save()method callscompute_format_decision()and dispatches accordingly.Modifications mode in
lsp_store.rsFormatOnSave::Modifications | FormatOnSave::ModificationsIfAvailableto the formatter selection match arm.ModificationsIfAvailablefalls back to full-file formatting when ranged formatting produces no results.VS Code settings import (
vscode_import.rs,settings_store.rs)Imports
editor.formatOnSaveModemapping:"modifications"→FormatOnSave::Modifications"modificationsIfAvailable"→FormatOnSave::ModificationsIfAvailable"file"→FormatOnSave::OnTests
test_modifications_format_on_save— basic modifications mode formatting with dirty buffertest_modifications_format_no_changes— clean buffer triggers no formattingtest_modifications_format_lsp_no_range_support— LSP without range formatting skips entirely forModificationstest_modifications_format_lsp_returns_empty_edits— empty edits handled gracefullytest_modifications_format_multiple_hunks— two non-adjacent edits produce two separate range formatting requestsSelf-Review Checklist:
Closes #16509
Depends on #53942
Release Notes:
modificationsandmodifications_if_availableoptions toformat_on_save, which format only git-changed lines instead of the entire fileremove_trailing_whitespace_on_saveandensure_final_newline_on_saveare also scoped to changed lines, preventing unwanted diff jitter in legacy codebaseseditor.formatOnSaveModesetting