From 865c87a18f2c303bfb118023180423df932972ea Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 27 Jul 2026 11:41:44 +1000 Subject: [PATCH 1/2] Preserve line breaks in Razor folding ranges Razor syntax nodes can include the line break after their closing brace. Keep it outside the folding range so following content stays on its own line. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f41854b7-faf2-4b17-bf28-bd817df1cf31 --- .../FoldingRanges/AbstractSyntaxNodeFoldingProvider.cs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/AbstractSyntaxNodeFoldingProvider.cs b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/AbstractSyntaxNodeFoldingProvider.cs index 132c69a98534..344564e53548 100644 --- a/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/AbstractSyntaxNodeFoldingProvider.cs +++ b/src/Razor/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/FoldingRanges/AbstractSyntaxNodeFoldingProvider.cs @@ -22,6 +22,15 @@ public ImmutableArray GetFoldingRanges(RazorCodeDocument codeDocum foreach (var node in nodes) { var (start, end) = sourceText.GetLinePositionSpan(node.Span); + + // Razor nodes can include the line break after their closing brace. Folding that line break + // pulls the following content onto the collapsed line. + if (end.Character == 0 && end.Line > start.Line) + { + var previousLine = sourceText.Lines[end.Line - 1]; + end = new(end.Line - 1, previousLine.Span.Length); + } + var foldingRange = new FoldingRange() { StartCharacter = start.Character, From 70460ca66bb20fb9b64fdd6ccad4b7c860f5336b Mon Sep 17 00:00:00 2001 From: David Wengier Date: Mon, 27 Jul 2026 11:41:56 +1000 Subject: [PATCH 2/2] Update Razor folding range baselines Restore range ends at closing braces, cover adjacent @if blocks, and re-enable the integration test for dotnet/razor#10860. Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com> Copilot-Session: f41854b7-faf2-4b17-bf28-bd817df1cf31 --- .../CohostFoldingRangeEndpointTest.cs | 37 +++++++++++++------ .../CodeFoldingTests.cs | 2 +- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs index 1e7a679ea84d..133f5a2bbd32 100644 --- a/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs +++ b/src/Razor/src/Razor/test/Microsoft.CodeAnalysis.Razor.CohostingShared.UnitTests/Endpoints/CohostFoldingRangeEndpointTest.cs @@ -27,15 +27,15 @@ public Task BadLooseFileUri()
Hello World
- } - |] + }|] + @if (true) {[|
Hello World
- } - |] + }|] + @if (true) {[| }|] """, @@ -52,20 +52,35 @@ public Task IfStatements(bool miscellaneousFile)
Hello World
- } - |] + }|] + @if (true) {[|
Hello World
- } - |] + }|] + @if (true) {[| }|] """, miscellaneousFile: miscellaneousFile); + [Fact] + public Task IfStatements_Adjacent() + => VerifyFoldingRangesAsync(""" + @if (true) {[| +
+ Hello World +
+ }|] + @if (false) {[| +
+ Goodbye World +
+ }|] + """); + [Fact] public Task LockStatement() => VerifyFoldingRangesAsync(""" @@ -92,8 +107,7 @@ Hello World
Goodbye World
- }|] - |] } + }|]|] """); @@ -285,8 +299,7 @@ Hello World
Goodbye World
- |] } - |] } + |] }|] @code[| diff --git a/src/Razor/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs b/src/Razor/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs index b2278f057d34..fc5c2ff006f5 100644 --- a/src/Razor/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs +++ b/src/Razor/src/Razor/test/Microsoft.VisualStudio.Razor.IntegrationTests/CodeFoldingTests.cs @@ -178,7 +178,7 @@ private void IncrementCount() """); } - [IdeFact(Skip = "https://github.com/dotnet/razor/issues/10860")] // FUSE changes whitespace on folding ranges + [IdeFact] public async Task CodeFolding_IfBlock() { await TestServices.SolutionExplorer.AddFileAsync(