Fix format selection deleting comments when selection ends inside comment trivia#3159
Fix format selection deleting comments when selection ends inside comment trivia#3159
Conversation
…nside comment Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
…ment trivia When the selection range ends inside a block comment (e.g., selecting part of /* comment */ in const test/* comment */=5;), the trailing edit block's contiguity check would incorrectly pass because previousRangeTriviaEnd was set to the end of the comment (beyond the selection range). This caused processPair to generate edits that replaced the comment text between previousRange and the next token, effectively deleting the comment. The fix adds an additional guard: previousRangeTriviaEnd must not exceed originalRange.End() for the trailing edit to proceed. When trivia extends beyond the selection range, it was not actually processed, so any edit spanning that trivia would be bogus. Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
|
@copilot you must not have run the tests. you broke formatSelectionEditAtEndOfRange_test |
…ectionEditAtEndOfRange The previous fix added a bounds check in the trailing edit block that was too broad - it blocked legitimate trailing edits when non-comment trivia (like newlines) extended past the original range. The new fix is in consumeTokenAndAdvanceScanner: when setting previousRangeTriviaEnd, cap it before any comment trivia that extends past the original range. This way, the contiguity check in execute() correctly fails for unprocessed comments but still works for legitimate cases like semicolon removal where only newline trivia extends past. Co-authored-by: jakebailey <5341706+jakebailey@users.noreply.github.com>
Fixed in 82bec94. The previous fix was too broad — it blocked all trailing edits when any trivia extended past the range, including legitimate cases like newline trivia in the semicolon-removal test. Moved the fix to |
Format Selection deletes block comments when the selection range ends inside the comment. For example, selecting any part of the comment (except the closing
/) inconst test/* comment */=5;and formatting deletes the comment entirely, producingconst test =5;.Root cause
In
consumeTokenAndAdvanceScanner,previousRangeTriviaEndis set to the end of all trailing trivia unconditionally. When a block comment in the trailing trivia extends pastoriginalRange.End(),processTriviacorrectly skips it (not fully contained by the range), butpreviousRangeTriviaEndstill points past the comment. This makes the trailing edit contiguity check inexecute()thinkpreviousRangeand the next token are adjacent, causingprocessPairto emit an edit that spans—and deletes—the unprocessed comment.Fix
In
consumeTokenAndAdvanceScanner, after settingpreviousRangeTriviaEnd, cap it before any comment trivia that is not contained byoriginalRange. This prevents the contiguity check from pairing across unprocessed comment content, while still allowing legitimate trailing edits when only non-comment trivia (e.g., newlines) extends past the range.internal/format/span.go: CappreviousRangeTriviaEndbefore unprocessed comment trivia inconsumeTokenAndAdvanceScannerinternal/format/comment_test.go: Regression tests for format selection preserving block commentsOriginal prompt
✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.