Conversation
metif12
force-pushed
the
fix/format-crlf-line-endings
branch
from
October 3, 2026 11:39
52d012b to
b249635
Compare
`v fmt` always writes LF, on every platform including Windows. VLS formats by
writing the buffer to a temp file, running `v fmt -inprocess -w` on it, and
reading the result back, so a CRLF document came back with every CR stripped:
```
module main\r\n\r\nfn main() {\r\n\tprintln('hi')\r\n}\r\n
|
v fmt -inprocess -w
v
module main\n\nfn main() {\n\tprintln('hi')\n}\n
```
That output was then returned verbatim as a whole-document `TextEdit`. Two
problems follow, and the second is the worse one:
1. Format Document silently converts the file's line endings, so every line
shows as changed and the diff is the entire file.
2. `format_content` returns no edits when the formatted text equals the input.
With the CRs gone that comparison could never hold for a CRLF document, so
VLS reported a change even for code that was already correctly formatted.
Restore the terminator the document already uses:
```v
formatted = restore_line_endings(content, formatted)
```
The terminator is taken from the document's first line break. An LF document is
untouched, output that already contains CRLF is not given a second CR, and a
document with no line break has no convention to preserve. A file with mixed
endings is normalized to its first ending, which is what a formatter that
respects the dominant convention does.
This is the same bug reported independently by users on Windows, where CRLF is
the default for `core.autocrlf` and for editors that preserve the file's
endings. The fix is platform-neutral: a CRLF document keeps CRLF on any
platform.
metif12
force-pushed
the
fix/format-crlf-line-endings
branch
from
October 3, 2026 11:47
b249635 to
b4b6b7d
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
v fmtalways writes LF line endings, on every platform including Windows. VLSformats by writing the buffer to a temp file, running
v fmt -inprocess -wonit, and reading the result back:
So a CRLF document came back with every CR stripped, and that output was
returned verbatim as a whole-document
TextEdit. Confirmed directly againstv fmton Windows:Two problems follow, and the second is the worse one:
Format Document silently rewrites the file's line endings. Every line
shows as changed and the diff is the whole file.
Already-formatted code is reported as changed.
format_contentreturnsno edits when the formatted text equals the input:
With the CRs removed that comparison can never hold for a CRLF document, so
VLS always returns an edit — even when the only difference is line endings and
the code itself was already correctly formatted.
Fix
Restore the terminator the document already uses, before the comparison:
The terminator is taken from the document's first line break, so:
the dominant convention does.
Tests
Three new tests in
handlers_test.v:test_handle_formatting_preserves_crlf_line_endings— a CRLF buffer throughtextDocument/formatting: the code is formatted and the result has no bareLF anywhere.
test_handle_formatting_already_formatted_crlf_is_a_no_op— the stronger halfof the bug: already-formatted CRLF content must produce zero edits.
test_restore_line_endings_leaves_lf_documents_alone— pins the LF path, theno-line-break case, already-CRLF output, and mixed endings.
I verified these are real regression tests by reverting the one-line fix and
re-running; both behavioural tests fail without it:
There was no line-ending coverage in
format_contentbefore.Validation
V
0137eb5(thevlang/vrevision CI builds from), Windows.handlers_test.von this branch's change applied over#526 +
#527 +
#528 +
#529 +
#530:
v fmt -verify .exits 0. On this branch alone,v .builds and the three testfiles that compile on
masterpass;handlers_test.vneeds#526 to compile on
masterat all.Note on the diff
As with #529 and #530, this branch runs
v fmtover the two files it touches,since
masteris notv fmt-clean (#528). The semantic change isrestore_line_endingsplus its one call site and three tests;
git diff -wshows only that.