From ca85e01af9eaf2440328a43fc5ac02214b620213 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 14 Nov 2025 22:07:54 +1100 Subject: [PATCH 1/3] Add failing test --- .../Formatting_NetFx/OnTypeFormattingTest.cs | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/OnTypeFormattingTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/OnTypeFormattingTest.cs index 6b1b8189da3..b1b1cf4f19f 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/OnTypeFormattingTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/OnTypeFormattingTest.cs @@ -18,6 +18,44 @@ namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; public class OnTypeFormattingTest(FormattingTestContext context, HtmlFormattingFixture fixture, ITestOutputHelper testOutput) : FormattingTestBase(context, fixture.Service, testOutput), IClassFixture { + [FormattingTestFact] + public async Task FormatsElseCloseBrace() + { + await RunOnTypeFormattingTestAsync( + input: """ + @page "/" + + @if (true) + { + + } + else { + + }$$ + + @code { + private string? streetKind; + } + """, + expected: """ + @page "/" + + @if (true) + { + + } + else + { + + } + + @code { + private string? streetKind; + } + """, + triggerCharacter: '}'); + } + [FormattingTestFact] public async Task FormatsIfStatementInComponent() { From e3ddd0512d8cbb158b6701ef5e207b7fc89da393 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 14 Nov 2025 22:08:15 +1100 Subject: [PATCH 2/3] Don't format the start of implicit expressions --- .../Formatting/Passes/CSharpOnTypeFormattingPass.cs | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs index 93c8e3b9766..4e8b6f5db5c 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpOnTypeFormattingPass.cs @@ -339,7 +339,14 @@ private static void CleanupSourceMappingStart(FormattingContext context, LinePos var text = context.SourceText; var sourceMappingSpan = text.GetTextSpan(sourceMappingRange); - if (!ShouldFormat(context, sourceMappingSpan, allowImplicitStatements: false, out var owner)) + if (!ShouldFormat(context, + sourceMappingSpan, + new ShouldFormatOptions( + AllowImplicitStatements: false, + AllowImplicitExpressions: false, + AllowSingleLineExplicitExpressions: true, + IsLineRequest: false), + out var owner)) { // We don't want to run cleanup on this range. return; From a0b00a609a86e63e86837b83aa8e97728d27b160 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Sun, 16 Nov 2025 08:32:17 +1100 Subject: [PATCH 3/3] Enable debug asserts in on type formatting tests --- .../Formatting_NetFx/FormattingTestBase.cs | 2 +- .../Cohost/Formatting/FormattingTestBase.cs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs index 62ea2552419..be252e20a17 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/FormattingTestBase.cs @@ -166,7 +166,7 @@ private protected async Task RunOnTypeFormattingTestAsync( filePathService, new TestDocumentContextFactory(), LoggerFactory); var languageKind = codeDocument.GetLanguageKind(positionAfterTrigger, rightAssociative: false); - var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, TestOutputHelper, codeDocument, razorLSPOptions, languageServerFeatureOptions); + var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, TestOutputHelper, codeDocument, razorLSPOptions, languageServerFeatureOptions, debugAssertsEnabled: true); var options = new FormattingOptions() { TabSize = tabSize, diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/Formatting/FormattingTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/Formatting/FormattingTestBase.cs index 002db61d5b8..283757ea363 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/Formatting/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/Formatting/FormattingTestBase.cs @@ -123,7 +123,9 @@ private protected async Task RunOnTypeFormattingTestAsync( var position = inputText.GetPosition(input.Position); var formattingService = (RazorFormattingService)OOPExportProvider.GetExportedValue(); - formattingService.GetTestAccessor().SetFormattingLoggerFactory(new TestFormattingLoggerFactory(TestOutputHelper)); + var accessor = formattingService.GetTestAccessor(); + accessor.SetDebugAssertsEnabled(debugAssertsEnabled: true); + accessor.SetFormattingLoggerFactory(new TestFormattingLoggerFactory(TestOutputHelper)); var generatedHtml = await RemoteServiceInvoker.TryInvokeAsync(document.Project.Solution, (service, solutionInfo, ct) => service.GetHtmlDocumentTextAsync(solutionInfo, document.Id, ct),