From 6f2390c74f4c76cddd00bb3ec19ea58dc0340600 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 13 Jun 2025 12:22:13 +1000 Subject: [PATCH 01/10] Don't hard code the complex edit command name --- .../Completion/Delegation/DelegatedCompletionHelper.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs index a3714ee0783..e5f2d965725 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Completion/Delegation/DelegatedCompletionHelper.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Language.Syntax; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; @@ -285,7 +286,7 @@ public static async Task FormatCSharpCompletionItemAsy { // In VS Code, Roslyn does resolve via a custom command. Thats fine, but we have to modify the text edit sitting within it, // rather than the one LSP knows about. - if (resolvedCompletionItem.Command is { CommandIdentifier: "roslyn.client.completionComplexEdit", Arguments: var args }) + if (resolvedCompletionItem.Command is { CommandIdentifier: Constants.CompleteComplexEditCommand, Arguments: var args }) { if (args is [TextDocumentIdentifier, TextEdit complexEdit, _, int nextCursorPosition]) { @@ -310,7 +311,7 @@ public static async Task FormatCSharpCompletionItemAsy } else { - logger.LogError($"Unexpected arguments for command '{resolvedCompletionItem.Command.CommandIdentifier}': Expected: [TextDocumentIdentifier, TextEdit, _, int], Actual: {GetArgumentTypesLogString(resolvedCompletionItem)}"); + logger.LogError($"Unexpected arguments for command '{Constants.CompleteComplexEditCommand}': Expected: [TextDocumentIdentifier, TextEdit, _, int], Actual: {GetArgumentTypesLogString(resolvedCompletionItem)}"); Debug.Fail("Unexpected arguments for Roslyn complex edit command. Have they changed things?"); } } From d7b2933fcdaa4884ccacfed78e85a07263584f85 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 13 Jun 2025 12:22:30 +1000 Subject: [PATCH 02/10] Specify formatting options instead of using string replacement --- .../CohostDocumentFormattingEndpoint.cs | 2 + .../Formatting/CSharpFormatter.cs | 21 ++++++++-- .../Formatting/Passes/CSharpFormattingPass.cs | 15 ++++++- .../Passes/New/CSharpFormattingPass.cs | 15 +++---- .../Formatting/RazorFormattingService.cs | 16 +++++--- .../DocumentFormattingTest.cs | 39 ++++++++----------- .../Formatting_NetFx/FormattingTestBase.cs | 10 ++--- .../TestRazorFormattingService.cs | 9 ++--- .../Cohost/FormattingTestBase.cs | 8 ++-- 9 files changed, 75 insertions(+), 60 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs index 2143bde024a..1f3c9545a44 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs @@ -79,6 +79,8 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie var options = RazorFormattingOptions.From(request.Options, _clientSettingsManager.GetClientSettings().AdvancedSettings.CodeBlockBraceOnNextLine); + + _logger.LogDebug($"Calling OOP with the {htmlChanges.Length} html edits, so it can fill in the rest"); var remoteResult = await _remoteServiceInvoker.TryInvokeAsync>( razorDocument.Project.Solution, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs index 136409550a4..c848d92b529 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/CSharpFormatter.cs @@ -11,6 +11,7 @@ using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Text; @@ -23,14 +24,20 @@ internal sealed class CSharpFormatter(IDocumentMappingService documentMappingSer private readonly IDocumentMappingService _documentMappingService = documentMappingService; - public async Task> FormatAsync(HostWorkspaceServices hostWorkspaceServices, Document csharpDocument, FormattingContext context, LinePositionSpan spanToFormat, CancellationToken cancellationToken) + public async Task> FormatAsync( + HostWorkspaceServices hostWorkspaceServices, + Document csharpDocument, + FormattingContext context, + LinePositionSpan spanToFormat, + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride, + CancellationToken cancellationToken) { if (!_documentMappingService.TryMapToGeneratedDocumentRange(context.CodeDocument.GetRequiredCSharpDocument(), spanToFormat, out var projectedSpan)) { return []; } - var edits = await GetFormattingEditsAsync(hostWorkspaceServices, csharpDocument, projectedSpan, context.Options.ToIndentationOptions(), cancellationToken).ConfigureAwait(false); + var edits = await GetFormattingEditsAsync(hostWorkspaceServices, csharpDocument, projectedSpan, context.Options.ToIndentationOptions(), formattingOptionsOverride, cancellationToken).ConfigureAwait(false); var mappedEdits = MapEditsToHostDocument(context.CodeDocument, edits); return mappedEdits; } @@ -56,14 +63,20 @@ private ImmutableArray MapEditsToHostDocument(RazorCodeDocument code return actualEdits.ToImmutableArray(); } - private static async Task> GetFormattingEditsAsync(HostWorkspaceServices hostWorkspaceServices, Document csharpDocument, LinePositionSpan projectedSpan, RazorIndentationOptions indentationOptions, CancellationToken cancellationToken) + private static async Task> GetFormattingEditsAsync( + HostWorkspaceServices hostWorkspaceServices, + Document csharpDocument, + LinePositionSpan projectedSpan, + RazorIndentationOptions indentationOptions, + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride, + CancellationToken cancellationToken) { var root = await csharpDocument.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false); var csharpSourceText = await csharpDocument.GetTextAsync(cancellationToken).ConfigureAwait(false); var spanToFormat = csharpSourceText.GetTextSpan(projectedSpan); Assumes.NotNull(root); - var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(hostWorkspaceServices, root, spanToFormat, indentationOptions, cancellationToken); + var changes = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(hostWorkspaceServices, root, spanToFormat, indentationOptions, formattingOptionsOverride, cancellationToken); return changes.ToImmutableArray(); } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs index 6e53d1211ef..afc82ac6435 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/CSharpFormattingPass.cs @@ -7,6 +7,7 @@ using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.PooledObjects; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Host; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; @@ -27,6 +28,8 @@ internal sealed class CSharpFormattingPass( private readonly CSharpFormatter _csharpFormatter = new(documentMappingService); private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); + private RazorCSharpSyntaxFormattingOptions? _csharpSyntaxFormattingOptionsOverride; + protected async override Task> ExecuteCoreAsync(FormattingContext context, RoslynWorkspaceHelper roslynWorkspaceHelper, ImmutableArray changes, CancellationToken cancellationToken) { // Apply previous edits if any. @@ -87,10 +90,20 @@ private async Task> FormatCSharpAsync(FormattingConte // These should already be remapped. var spanToFormat = sourceText.GetLinePositionSpan(span); - var changes = await _csharpFormatter.FormatAsync(hostWorkspaceServices, csharpDocument, context, spanToFormat, cancellationToken).ConfigureAwait(false); + var changes = await _csharpFormatter.FormatAsync(hostWorkspaceServices, csharpDocument, context, spanToFormat, _csharpSyntaxFormattingOptionsOverride, cancellationToken).ConfigureAwait(false); csharpChanges.AddRange(changes.Where(e => spanToFormat.Contains(sourceText.GetLinePositionSpan(e.Span)))); } return csharpChanges.ToImmutable(); } + + internal TestAccessor GetTestAccessor() => new TestAccessor(this); + + internal readonly struct TestAccessor(CSharpFormattingPass instance) + { + public void SetCSharpSyntaxFormattingOptionsOverride(RazorCSharpSyntaxFormattingOptions? optionsOverride) + { + instance._csharpSyntaxFormattingOptionsOverride = optionsOverride; + } + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/New/CSharpFormattingPass.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/New/CSharpFormattingPass.cs index f26246d3d5b..74ae444cdb7 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/New/CSharpFormattingPass.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/Passes/New/CSharpFormattingPass.cs @@ -10,6 +10,7 @@ using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; @@ -21,7 +22,7 @@ internal sealed partial class CSharpFormattingPass(IHostServicesProvider hostSer private readonly ILogger _logger = loggerFactory.GetOrCreateLogger(); private readonly IHostServicesProvider _hostServicesProvider = hostServicesProvider; - private Func? _formattedCSharpDocumentModifierFunc = null; + private RazorCSharpSyntaxFormattingOptions? _csharpSyntaxFormattingOptionsOverride; public async Task> ExecuteAsync(FormattingContext context, ImmutableArray changes, CancellationToken cancellationToken) { @@ -38,12 +39,6 @@ public async Task> ExecuteAsync(FormattingContext con var formattedCSharpText = await FormatCSharpAsync(generatedCSharpText, context.Options.ToIndentationOptions(), cancellationToken).ConfigureAwait(false); _logger.LogTestOnly($"Formatted generated C# document:\r\n{formattedCSharpText}"); - if (_formattedCSharpDocumentModifierFunc is { } func) - { - formattedCSharpText = func(formattedCSharpText); - _logger.LogTestOnly($"Formatted generated C# document (after func):\r\n{formattedCSharpText}"); - } - // We now have a formatted C# document, and an original document, but we can't just apply the changes to the original // document as they come from very different places. What we want to do is go through each line of the generated document, // take the indentation that is in it, and apply it to the original document, and then take any formatting changes @@ -211,7 +206,7 @@ private async Task FormatCSharpAsync(SourceText generatedCSharpText, var tree = CSharpSyntaxTree.ParseText(generatedCSharpText, cancellationToken: cancellationToken); var csharpRoot = await tree.GetRootAsync(cancellationToken).ConfigureAwait(false); - var csharpChanges = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(helper.HostWorkspaceServices, csharpRoot, csharpRoot.FullSpan, options, cancellationToken); + var csharpChanges = RazorCSharpFormattingInteractionService.GetFormattedTextChanges(helper.HostWorkspaceServices, csharpRoot, csharpRoot.FullSpan, options, _csharpSyntaxFormattingOptionsOverride, cancellationToken); return generatedCSharpText.WithChanges(csharpChanges); } @@ -224,9 +219,9 @@ internal static string GetFormattingDocumentContentsForSyntaxVisualizer(RazorCod internal readonly struct TestAccessor(CSharpFormattingPass instance) { - public void SetFormattedCSharpDocumentModifierFunc(Func func) + public void SetCSharpSyntaxFormattingOptionsOverride(RazorCSharpSyntaxFormattingOptions? optionsOverride) { - instance._formattedCSharpDocumentModifierFunc = func; + instance._csharpSyntaxFormattingOptionsOverride = optionsOverride; } } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs index 07b64d37d78..bc44ebdca93 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Formatting/RazorFormattingService.cs @@ -5,13 +5,13 @@ using System.Collections.Frozen; using System.Collections.Generic; using System.Collections.Immutable; -using System.Diagnostics; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.DocumentMapping; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; @@ -397,13 +397,17 @@ public void SetDebugAssertsEnabled(bool debugAssertsEnabled) contentValidationPass.DebugAssertsEnabled = debugAssertsEnabled; } - public void SetFormattedCSharpDocumentModifierFunc(Func func) + public void SetCSharpSyntaxFormattingOptionsOverride(RazorCSharpSyntaxFormattingOptions? optionsOverride) { - // This is only valid for the new formatting engine, so a test that sets it for the old formatter is probably written incorrectly. - Debug.Assert(service._languageServerFeatureOptions.UseNewFormattingEngine); + if (service._documentFormattingPasses.OfType().SingleOrDefault() is { } pass) + { + pass.GetTestAccessor().SetCSharpSyntaxFormattingOptionsOverride(optionsOverride); + } - var pass = service._documentFormattingPasses.OfType().Single(); - pass.GetTestAccessor().SetFormattedCSharpDocumentModifierFunc(func); + if (service._documentFormattingPasses.OfType().SingleOrDefault() is { } newPass) + { + newPass.GetTestAccessor().SetCSharpSyntaxFormattingOptionsOverride(optionsOverride); + } } } } diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentFormattingTest.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentFormattingTest.cs index 898d8232a06..114c22e29ff 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentFormattingTest.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/DocumentFormattingTest.cs @@ -1,12 +1,12 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. -using System.Text.RegularExpressions; +using System; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; using Microsoft.AspNetCore.Razor.Test.Common; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.Formatting; -using Microsoft.CodeAnalysis.Text; using Xunit; using Xunit.Abstractions; @@ -30,7 +30,7 @@ await RunFormattingTestAsync( expected: ""); } - [FormattingTestFact(SkipOldFormattingEngine = true)] + [FormattingTestFact] public async Task RoslynFormatBracesAsKandR() { // To format code blocks we emit a class so that class members are parsed properly by Roslyn, and ignore @@ -66,16 +66,13 @@ public void Bar() { } } """, - // I'm so sorry, but I could not find any way to change Roslyn formatting options from our test infra. Forgive my hacky sins - csharpModifierFunc: formattedCSharpText => SourceText.From( - Regex.Replace( - formattedCSharpText.ToString(), - @"(class|void) ([\S]+)[\s]+{", - "$1 $2 {" - ))); + formattingOptionsOverride: new RazorCSharpSyntaxFormattingOptions() with + { + NewLines = RazorNewLinePlacement.None + }); } - [FormattingTestFact(SkipOldFormattingEngine = true)] + [FormattingTestFact] public async Task PropertyShrunkToOneLine() { await RunFormattingTestAsync( @@ -90,20 +87,16 @@ public string Name """, expected: """ @code { - public string Name { get; set; } + public string Name { + get; + set; + } } """, - // I'm so sorry, but I could not find any way to change Roslyn formatting options from our test infra. Forgive my hacky sins - csharpModifierFunc: formattedCSharpText => SourceText.From( - formattedCSharpText.ToString().Replace( - """ - public string Name - { - get; - set; - } - """, - "public string Name { get; set; }"))); + formattingOptionsOverride: new RazorCSharpSyntaxFormattingOptions() with + { + NewLines = RazorNewLinePlacement.None + }); } [FormattingTestFact] 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 48a8a13ef9d..b83ba20bfe5 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 @@ -19,7 +19,7 @@ using Microsoft.AspNetCore.Razor.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectEngineHost; @@ -66,13 +66,13 @@ private protected async Task RunFormattingTestAsync( bool codeBlockBraceOnNextLine = false, bool inGlobalNamespace = false, bool debugAssertsEnabled = true, - Func? csharpModifierFunc = null) + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride = null) { (input, expected) = ProcessFormattingContext(input, expected); var razorLSPOptions = RazorLSPOptions.Default with { CodeBlockBraceOnNextLine = codeBlockBraceOnNextLine }; - await RunFormattingTestInternalAsync(input, expected, tabSize, insertSpaces, fileKind, tagHelpers, allowDiagnostics, razorLSPOptions, inGlobalNamespace, debugAssertsEnabled, csharpModifierFunc); + await RunFormattingTestInternalAsync(input, expected, tabSize, insertSpaces, fileKind, tagHelpers, allowDiagnostics, razorLSPOptions, inGlobalNamespace, debugAssertsEnabled, formattingOptionsOverride); } private async Task RunFormattingTestInternalAsync( @@ -86,7 +86,7 @@ private async Task RunFormattingTestInternalAsync( RazorLSPOptions? razorLSPOptions, bool inGlobalNamespace, bool debugAssertsEnabled, - Func? csharpModifierFunc) + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride) { // Arrange var fileKindValue = fileKind ?? RazorFileKind.Component; @@ -113,7 +113,7 @@ private async Task RunFormattingTestInternalAsync( var languageServerFeatureOptions = new TestLanguageServerFeatureOptions(useNewFormattingEngine: _context.UseNewFormattingEngine); - var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, codeDocument, razorLSPOptions, languageServerFeatureOptions, debugAssertsEnabled, csharpModifierFunc); + var formattingService = await TestRazorFormattingService.CreateWithFullSupportAsync(LoggerFactory, codeDocument, razorLSPOptions, languageServerFeatureOptions, debugAssertsEnabled, formattingOptionsOverride); var documentContext = new DocumentContext(uri, documentSnapshot, projectContext: null); var client = new FormattingLanguageServerClient(_htmlFormattingService, LoggerFactory); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs index c5d3c78a725..6e3877e60f4 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.LanguageServer.Test/Formatting_NetFx/TestRazorFormattingService.cs @@ -8,10 +8,10 @@ using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; using Microsoft.AspNetCore.Razor.Test.Common.Workspaces; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Workspaces; -using Microsoft.CodeAnalysis.Text; using Moq; namespace Microsoft.AspNetCore.Razor.LanguageServer.Formatting; @@ -24,7 +24,7 @@ public static async Task CreateWithFullSupportAsync( RazorLSPOptions? razorLSPOptions = null, LanguageServerFeatureOptions? languageServerFeatureOptions = null, bool debugAssertsEnabled = false, - Func? csharpModifierFunc = null) + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride = null) { codeDocument ??= TestRazorCodeDocument.CreateEmpty(); @@ -50,10 +50,7 @@ public static async Task CreateWithFullSupportAsync( var service = new RazorFormattingService(mappingService, hostServicesProvider, languageServerFeatureOptions, loggerFactory); var accessor = service.GetTestAccessor(); accessor.SetDebugAssertsEnabled(debugAssertsEnabled); - if (csharpModifierFunc is not null) - { - accessor.SetFormattedCSharpDocumentModifierFunc(csharpModifierFunc); - } + accessor.SetCSharpSyntaxFormattingOptionsOverride(formattingOptionsOverride); return service; } diff --git a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/FormattingTestBase.cs b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/FormattingTestBase.cs index e3fb7f1f28b..999a6c4a8b0 100644 --- a/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/FormattingTestBase.cs +++ b/src/Razor/test/Microsoft.VisualStudio.LanguageServices.Razor.Test/Cohost/FormattingTestBase.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Razor.Test.Common; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.CodeAnalysis.ExternalAccess.Razor.Features; using Microsoft.CodeAnalysis.Razor.Formatting; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.Remote; @@ -45,7 +46,7 @@ private protected async Task RunFormattingTestAsync( int tabSize = 4, bool allowDiagnostics = false, bool debugAssertsEnabled = true, - Func? csharpModifierFunc = null) + RazorCSharpSyntaxFormattingOptions? formattingOptionsOverride = null) { (input, expected) = ProcessFormattingContext(input, expected); @@ -65,10 +66,7 @@ private protected async Task RunFormattingTestAsync( var formattingService = (RazorFormattingService)OOPExportProvider.GetExportedValue(); var accessor = formattingService.GetTestAccessor(); accessor.SetDebugAssertsEnabled(debugAssertsEnabled); - if (csharpModifierFunc is not null) - { - accessor.SetFormattedCSharpDocumentModifierFunc(csharpModifierFunc); - } + accessor.SetCSharpSyntaxFormattingOptionsOverride(formattingOptionsOverride); var generatedHtml = await RemoteServiceInvoker.TryInvokeAsync(document.Project.Solution, (service, solutionInfo, ct) => service.GetHtmlDocumentTextAsync(solutionInfo, document.Id, ct), From f15257da825256402ca42f6299bc969282206679 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Fri, 13 Jun 2025 12:24:11 +1000 Subject: [PATCH 03/10] Update src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs --- .../Formatting/CohostDocumentFormattingEndpoint.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs index 1f3c9545a44..2143bde024a 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.CohostingShared/Formatting/CohostDocumentFormattingEndpoint.cs @@ -79,8 +79,6 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie var options = RazorFormattingOptions.From(request.Options, _clientSettingsManager.GetClientSettings().AdvancedSettings.CodeBlockBraceOnNextLine); - - _logger.LogDebug($"Calling OOP with the {htmlChanges.Length} html edits, so it can fill in the rest"); var remoteResult = await _remoteServiceInvoker.TryInvokeAsync>( razorDocument.Project.Solution, From 2b94c905a98aaf9c503cf4b687a555f6351815d9 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 17 Jun 2025 07:28:55 +1000 Subject: [PATCH 04/10] Bump Roslyn --- eng/Version.Details.xml | 84 ++++++++++++++++++++--------------------- eng/Versions.props | 41 ++++++++++---------- 2 files changed, 60 insertions(+), 65 deletions(-) diff --git a/eng/Version.Details.xml b/eng/Version.Details.xml index f9e9665f530..f6cfc32f699 100644 --- a/eng/Version.Details.xml +++ b/eng/Version.Details.xml @@ -2,89 +2,85 @@ - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb - + https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 - - - https://github.com/dotnet/roslyn - ded867328249b5a9b9e6e29e3f07abc19111f5d1 + e15bc0a7eb664d20e7237daef7ab6b76da6c16cb https://github.com/dotnet/roslyn diff --git a/eng/Versions.props b/eng/Versions.props index 5f6f276d9cc..18797452b2d 100644 --- a/eng/Versions.props +++ b/eng/Versions.props @@ -48,27 +48,26 @@ --> 3.12.0-beta1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 - 5.0.0-1.25230.6 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1 + 5.0.0-1.25316.1