Nimblesite / Nimblesite/SharpLsp
C# rename returns a single whole-document TextEdit — SourceText normalization defeats granular GetTextChanges (contrary to its own comment)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 132
- Forks
- 5
- Avg merge
- 6h 24m
- Merged PRs (30d)
- 27
Description
Symptom
textDocument/rename on a parameter in a real repo (FluentValidation @ 12.1.1, AbstractValidator.RuleFor's expression) returns a WorkspaceEdit containing one TextEdit spanning from 0:0 — a whole-document replacement — instead of granular edits for the declaration + 2 body uses.
The rename is semantically correct when applied, but whole-document edits destroy editor state (markers, decorations, undo granularity) and defeat LSP clients that preview/partially-apply edits.
Root cause
WorkspaceManager.cs (~line 766):
// Normalize to the same SourceText subtype so GetTextChanges
// produces granular diffs rather than a single whole-document replacement.
var newText = SourceText.From(rawNewText.ToString(), oldText.Encoding);
var textChanges = newText.GetTextChanges(oldText);
The comment's claim is inverted: SourceText.From(...) creates a text with no change-history lineage to oldText, and GetTextChanges between unrelated SourceTexts falls back to a single whole-document change. Granular diffs require using the renamed document's own SourceText (which carries ChangedText lineage from the original solution snapshot) — i.e. rawNewText.GetTextChanges(oldText) where both stem from the same solution fork, or an explicit diff.
Repro
MOCHA_GREP='structure . rename dry-run' npm test (real-repo FluentValidation suite). The e2e currently asserts the semantic outcome granularity-agnostically (new name appears 3+ times in the payload), so it passes — tighten it to assert granular edits once this is fixed.
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start at WorkspaceManager.cs around line 766 and trace how the rename result becomes TextEdits, paying attention to the SourceText instances used by GetTextChanges. Run MOCHA_GREP='structure . rename dry-run' npm test against the FluentValidation reproduction, then tighten the e2e assertion so it verifies granular edits for the declaration and two body uses rather than only semantic occurrence counts. Done means the rename remains correct and no longer emits a single 0:0 whole-document replacement.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- csharp
- Domain
- devtools, testing
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 75/100