diff --git a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/RazorLanguageServerHost.cs b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/RazorLanguageServerHost.cs index 56e9cb461b9..81a7dcb2111 100644 --- a/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/RazorLanguageServerHost.cs +++ b/src/Razor/src/Microsoft.AspNetCore.Razor.LanguageServer/Hosting/RazorLanguageServerHost.cs @@ -9,6 +9,7 @@ using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.Extensions.DependencyInjection; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -77,8 +78,7 @@ private static (JsonRpc, JsonSerializerOptions) CreateJsonRpc(Stream input, Stre { var messageFormatter = new SystemTextJsonFormatter(); - // In its infinite wisdom, the LSP client has a public method that takes Newtonsoft.Json types, but an internal method that takes System.Text.Json types. - typeof(VSInternalExtensionUtilities).GetMethod("AddVSInternalExtensionConverters", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)!.Invoke(null, [messageFormatter.JsonSerializerOptions]); + JsonHelpers.AddVSInternalExtensionConverters(messageFormatter.JsonSerializerOptions); var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(output, input, messageFormatter)); diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/JsonHelpers.cs b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/JsonHelpers.cs index 6bca8850e25..628b46695ef 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/JsonHelpers.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Protocol/JsonHelpers.cs @@ -1,7 +1,10 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the MIT license. See License.txt in the project root for license information. +using System; using System.Text.Json; +using Microsoft.CodeAnalysis.ExternalAccess.Razor; +using Microsoft.VisualStudio.LanguageServer.Protocol; using Newtonsoft.Json.Linq; namespace Microsoft.CodeAnalysis.Razor.Protocol; @@ -9,6 +12,8 @@ namespace Microsoft.CodeAnalysis.Razor.Protocol; internal static class JsonHelpers { private const string s_convertedFlag = "__convertedFromJObject"; + private static readonly Lazy s_roslynLspJsonSerializerOptions = new(CreateRoslynLspJsonSerializerOptions); + private static readonly Lazy s_vsLspJsonSerializerOptions = new(CreateVsLspJsonSerializerOptions); /// /// Normalizes data from JObject to JsonElement as thats what we expect to process @@ -37,4 +42,59 @@ internal static class JsonHelpers return data; } + + /// + /// Serializer options to use when serializing or deserializing a Roslyn LSP type + /// + internal static JsonSerializerOptions RoslynLspJsonSerializerOptions => s_roslynLspJsonSerializerOptions.Value; + + /// + /// Serializer options to use when serializing or deserializing a VS Platform LSP type + /// + internal static JsonSerializerOptions VsLspJsonSerializerOptions => s_vsLspJsonSerializerOptions.Value; + + /// + /// Converts a Roslyn LSP object to a VS Platform LSP object via serializing to text and deserializing to VS LSP type + /// + internal static TVsLspResult? ToVsLSP(TRoslynLspSource source) + { + return JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(source, RoslynLspJsonSerializerOptions), VsLspJsonSerializerOptions); + } + + /// + /// Converts a VS Platform LSP object to a Roslyn LSP object via serializing to text and deserializing to Roslyn LSP type + /// + internal static TRoslynLspResult? ToRoslynLSP(TVsLspSource? source) + { + return JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(source, VsLspJsonSerializerOptions), RoslynLspJsonSerializerOptions); + } + + /// + /// Adds VS Platform LSP converters for VSInternal variation of types (e.g. VSInternalClientCapability from ClientCapability) + /// + internal static void AddVSInternalExtensionConverters(JsonSerializerOptions serializerOptions) + { + // In its infinite wisdom, the LSP client has a public method that takes Newtonsoft.Json types, but an internal method that takes System.Text.Json types. + typeof(VSInternalExtensionUtilities).GetMethod("AddVSInternalExtensionConverters", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)!.Invoke(null, [serializerOptions]); + } + + private static JsonSerializerOptions CreateRoslynLspJsonSerializerOptions() + { + var serializerOptions = new JsonSerializerOptions(); + + foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) + { + serializerOptions.Converters.Add(converter); + } + + return serializerOptions; + } + + private static JsonSerializerOptions CreateVsLspJsonSerializerOptions() + { + var serializerOptions = new JsonSerializerOptions(); + + AddVSInternalExtensionConverters(serializerOptions); + return serializerOptions; + } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/RoslynCodeActionHelpers.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/RoslynCodeActionHelpers.cs index b0add9ea4b4..4f46a45d0ea 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/RoslynCodeActionHelpers.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/CodeActions/RoslynCodeActionHelpers.cs @@ -5,13 +5,13 @@ using System.Collections.Generic; using System.Composition; using System.Diagnostics; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor.CodeActions; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.VisualStudio.LanguageServer.Protocol; using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; @@ -56,16 +56,10 @@ public Task GetFormattedNewFileContentsAsync(IProjectSnapshot projectSna document = solution.GetRequiredDocument(documentIds.First(d => d.ProjectId == context.TextDocument.Project.Id)); } - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - var convertedEdit = JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(edit, options), options).AssumeNotNull(); + var convertedEdit = JsonHelpers.ToRoslynLSP(edit).AssumeNotNull(); var edits = await ExternalHandlers.CodeActions.GetSimplifiedEditsAsync(document, convertedEdit, cancellationToken).ConfigureAwait(false); - return JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(edits, options), options); + return JsonHelpers.ToVsLSP(edits); } } diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs index 59d91ab8e2b..b5878950d4b 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/Completion/RemoteCompletionService.cs @@ -4,7 +4,6 @@ using System.Collections.Generic; using System.Diagnostics; using System.Linq; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis.ExternalAccess.Razor; @@ -18,6 +17,7 @@ using Microsoft.VisualStudio.LanguageServer.Protocol; using Response = Microsoft.CodeAnalysis.Razor.Remote.RemoteResponse; using RoslynCompletionContext = Roslyn.LanguageServer.Protocol.CompletionContext; +using RoslynCompletionList = Roslyn.LanguageServer.Protocol.CompletionList; using RoslynCompletionSetting = Roslyn.LanguageServer.Protocol.CompletionSetting; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -175,20 +175,14 @@ private async ValueTask GetCompletionAsync( } // This is, to say the least, not ideal. In future we're going to normalize on to Roslyn LSP types, and this can go. - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - if (JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(completionContext), options) is not { } roslynCompletionContext) + if (JsonHelpers.ToRoslynLSP(completionContext) is not { } roslynCompletionContext) { Debug.Fail("Unable to convert VS to Roslyn LSP completion context"); return null; } var clientCapabilities = _clientCapabilitiesService.ClientCapabilities; - if (JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(clientCapabilities.TextDocument?.Completion), options) is not { } roslynCompletionSetting) + if (JsonHelpers.ToRoslynLSP(clientCapabilities.TextDocument?.Completion) is not { } roslynCompletionSetting) { Debug.Fail("Unable to convert VS to Roslyn LSP completion setting"); return null; @@ -217,7 +211,7 @@ private async ValueTask GetCompletionAsync( }; } - var vsPlatformCompletionList = JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(roslynCompletionList), options); + var vsPlatformCompletionList = JsonHelpers.ToVsLSP(roslynCompletionList); var rewrittenResponse = await DelegatedCompletionHelper.RewriteCSharpResponseAsync( vsPlatformCompletionList, diff --git a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentSymbols/RemoteDocumentSymbolService.cs b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentSymbols/RemoteDocumentSymbolService.cs index 7dd6aae79ef..b2377bb95da 100644 --- a/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentSymbols/RemoteDocumentSymbolService.cs +++ b/src/Razor/src/Microsoft.CodeAnalysis.Remote.Razor/DocumentSymbols/RemoteDocumentSymbolService.cs @@ -1,7 +1,6 @@ // 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.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.Language; @@ -12,6 +11,7 @@ using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem; using Microsoft.VisualStudio.LanguageServer.Protocol; using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; +using RoslynSymbolSumType = Roslyn.LanguageServer.Protocol.SumType; namespace Microsoft.CodeAnalysis.Remote.Razor; @@ -49,13 +49,7 @@ protected override IRemoteDocumentSymbolService CreateService(in ServiceArgs arg var csharpDocument = codeDocument.GetCSharpDocument(); // This is, to say the least, not ideal. In future we're going to normalize on to Roslyn LSP types, and this can go. - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - var vsCSharpSymbols = JsonSerializer.Deserialize?>(JsonSerializer.SerializeToDocument(csharpSymbols), options); + var vsCSharpSymbols = JsonHelpers.ToVsLSP?, RoslynSymbolSumType>(csharpSymbols); if (vsCSharpSymbols is not { } convertedSymbols) { return null; diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsEndpoint.cs index 496124067d5..09f4cfba413 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsEndpoint.cs @@ -5,14 +5,12 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.AspNetCore.Razor.Telemetry; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; using Microsoft.CodeAnalysis.Razor.CodeActions.Models; @@ -127,18 +125,12 @@ private async Task GetCSharpCodeActionsAsync(TextDo return []; } - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - var csharpRequest = JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(request, options), options).AssumeNotNull(); + var csharpRequest = JsonHelpers.ToRoslynLSP(request).AssumeNotNull(); using var _ = _telemetryReporter.TrackLspRequest(Methods.TextDocumentCodeActionName, "Razor.ExternalAccess", TelemetryThresholds.CodeActionSubLSPTelemetryThreshold, correlationId); var csharpCodeActions = await CodeActions.GetCodeActionsAsync(generatedDocument, csharpRequest, _clientCapabilitiesService.ClientCapabilities.SupportsVisualStudioExtensions, cancellationToken).ConfigureAwait(false); - return JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(csharpCodeActions, options), options).AssumeNotNull(); + return JsonHelpers.ToVsLSP(csharpCodeActions).AssumeNotNull(); } private async Task GetHtmlCodeActionsAsync(TextDocument razorDocument, VSCodeActionParams request, Guid correlationId, CancellationToken cancellationToken) diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsResolveEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsResolveEndpoint.cs index e0d857042ce..f2bc3dec1f2 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsResolveEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostCodeActionsResolveEndpoint.cs @@ -4,13 +4,11 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Composition; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.LanguageServer.Hosting; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; using Microsoft.CodeAnalysis.Razor.CodeActions; @@ -118,19 +116,13 @@ private async Task ResolveCSharpCodeActionAsync(TextDocument razorDo return codeAction; } - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - var resourceOptions = _clientCapabilitiesService.ClientCapabilities.Workspace?.WorkspaceEdit?.ResourceOperations ?? []; - var roslynCodeAction = JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(codeAction, options), options).AssumeNotNull(); - var roslynResourceOptions = JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(resourceOptions, options), options).AssumeNotNull(); + var roslynCodeAction = JsonHelpers.ToRoslynLSP(codeAction).AssumeNotNull(); + var roslynResourceOptions = JsonHelpers.ToRoslynLSP(resourceOptions).AssumeNotNull(); var resolvedCodeAction = await CodeActions.ResolveCodeActionAsync(generatedDocument, roslynCodeAction, roslynResourceOptions, cancellationToken).ConfigureAwait(false); - return JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(resolvedCodeAction, options), options).AssumeNotNull(); + return JsonHelpers.ToVsLSP(resolvedCodeAction).AssumeNotNull(); } finally { diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentCompletionEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentCompletionEndpoint.cs index 58ca85266c3..4a568aaa9a7 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentCompletionEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentCompletionEndpoint.cs @@ -4,13 +4,11 @@ using System.Collections.Immutable; using System.Composition; using System.Linq; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.Completion; using Microsoft.CodeAnalysis.Razor.Completion.Delegation; @@ -25,6 +23,8 @@ using Response = Microsoft.CodeAnalysis.Razor.Remote.RemoteResponse; using RoslynCompletionParams = Roslyn.LanguageServer.Protocol.CompletionParams; using RoslynLspExtensions = Roslyn.LanguageServer.Protocol.RoslynLspExtensions; +using RoslynPosition = Roslyn.LanguageServer.Protocol.Position; +using RoslynCompletionContext = Roslyn.LanguageServer.Protocol.CompletionContext; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -82,7 +82,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie private async Task HandleRequestAsync(RoslynCompletionParams request, TextDocument razorDocument, CancellationToken cancellationToken) { - if (request.Context is null || ToVsLSP(request.Context) is not VSInternalCompletionContext completionContext) + if (request.Context is null || JsonHelpers.ToVsLSP(request.Context) is not VSInternalCompletionContext completionContext) { _logger.LogError("Completion request context is null"); return null; @@ -105,7 +105,7 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie solutionInfo, razorDocument.Id, completionContext, - ToVsLSP(request.Position).AssumeNotNull(), + JsonHelpers.ToVsLSP(request.Position).AssumeNotNull(), cancellationToken), cancellationToken).ConfigureAwait(false) is not { } completionPositionInfo) { @@ -218,23 +218,6 @@ public ImmutableArray GetRegistrations(VSInternalClientCapabilitie return rewrittenResponse; } - private static T? ToVsLSP(object source) where T : class - { - // This is, to say the least, not ideal. In future we're going to normalize on to Roslyn LSP types, and this can go. - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - if (JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(source), options) is not { } target) - { - return null; - } - - return target; - } - private VSInternalCompletionList? AddSnippets( VSInternalCompletionList? completionList, RazorLanguageKind languageKind, diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentPullDiagnosticsEndpoint.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentPullDiagnosticsEndpoint.cs index 4e067264491..0497e24042d 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentPullDiagnosticsEndpoint.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/CohostDocumentPullDiagnosticsEndpoint.cs @@ -6,22 +6,22 @@ using System.Collections.Immutable; using System.Composition; using System.Linq; -using System.Text.Json; using System.Threading; using System.Threading.Tasks; using Microsoft.AspNetCore.Razor; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; using Microsoft.CodeAnalysis.Razor.Logging; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Remote; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.ContainedLanguage; using Microsoft.VisualStudio.LanguageServer.Protocol; using ExternalHandlers = Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; using LspDiagnostic = Microsoft.VisualStudio.LanguageServer.Protocol.Diagnostic; +using RoslynDiagnostic = Roslyn.LanguageServer.Protocol.Diagnostic; namespace Microsoft.VisualStudio.Razor.LanguageClient.Cohost; @@ -139,13 +139,7 @@ private async Task GetCSharpDiagnosticsAsync(TextDocument razor var csharpDiagnostics = await ExternalHandlers.Diagnostics.GetDocumentDiagnosticsAsync(generatedDocument, supportsVisualStudioExtensions: true, cancellationToken).ConfigureAwait(false); // This is, to say the least, not ideal. In future we're going to normalize on to Roslyn LSP types, and this can go. - var options = new JsonSerializerOptions(); - foreach (var converter in RazorServiceDescriptorsWrapper.GetLspConverters()) - { - options.Converters.Add(converter); - } - - if (JsonSerializer.Deserialize(JsonSerializer.SerializeToDocument(csharpDiagnostics), options) is not { } convertedDiagnostics) + if (JsonHelpers.ToVsLSP>(csharpDiagnostics) is not { } convertedDiagnostics) { return []; } diff --git a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs index 4d94bc5a362..eebcdaf0062 100644 --- a/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs +++ b/src/Razor/src/Microsoft.VisualStudio.LanguageServices.Razor/LanguageClient/Cohost/RazorCohostDynamicRegistrationService.cs @@ -10,6 +10,7 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Razor.PooledObjects; using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost; +using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.VisualStudio.LanguageServer.Protocol; @@ -40,7 +41,7 @@ public async Task RegisterAsync(string clientCapabilitiesString, RazorCohostRequ return; } - var clientCapabilities = JsonSerializer.Deserialize(clientCapabilitiesString) ?? new(); + var clientCapabilities = JsonSerializer.Deserialize(clientCapabilitiesString, JsonHelpers.VsLspJsonSerializerOptions) ?? new(); _lazyRazorCohostClientCapabilitiesService.Value.SetCapabilities(clientCapabilities); diff --git a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs index 1d8a762a586..97daf2de479 100644 --- a/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs +++ b/src/Razor/test/Microsoft.AspNetCore.Razor.Test.Common.Tooling/LanguageServer/LanguageServerTestBase.cs @@ -21,11 +21,11 @@ using Microsoft.CodeAnalysis.ExternalAccess.Razor; using Microsoft.CodeAnalysis.Razor; using Microsoft.CodeAnalysis.Razor.ProjectSystem; +using Microsoft.CodeAnalysis.Razor.Protocol; using Microsoft.CodeAnalysis.Razor.Workspaces; using Microsoft.CodeAnalysis.Text; using Microsoft.CommonLanguageServerProtocol.Framework; using Microsoft.NET.Sdk.Razor.SourceGenerators; -using Microsoft.VisualStudio.LanguageServer.Protocol; using Xunit.Abstractions; namespace Microsoft.AspNetCore.Razor.Test.Common.LanguageServer; @@ -41,10 +41,7 @@ protected LanguageServerTestBase(ITestOutputHelper testOutput) { SpanMappingService = new ThrowingRazorSpanMappingService(); - SerializerOptions = new JsonSerializerOptions(); - // In its infinite wisdom, the LSP client has a public method that takes Newtonsoft.Json types, but an internal method that takes System.Text.Json types. - typeof(VSInternalExtensionUtilities).GetMethod("AddVSInternalExtensionConverters", System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.NonPublic)!.Invoke(null, [SerializerOptions]); - + SerializerOptions = JsonHelpers.VsLspJsonSerializerOptions; FilePathService = new LSPFilePathService(TestLanguageServerFeatureOptions.Instance); }