diff --git a/eng/Directory.Packages.props b/eng/Directory.Packages.props
index 39a0493e4ff24..422156efd5e75 100644
--- a/eng/Directory.Packages.props
+++ b/eng/Directory.Packages.props
@@ -57,7 +57,7 @@
Visual Studio
-->
-
+
@@ -100,7 +100,7 @@
-
+
@@ -139,7 +139,7 @@
-
+
diff --git a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs
index 0038d5fbfe21b..8eccf1e6e410c 100644
--- a/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs
+++ b/src/EditorFeatures/Core/LanguageServer/AbstractInProcLanguageClient.cs
@@ -6,6 +6,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.IO;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Editor.Shared.Utilities;
@@ -19,8 +20,6 @@
using Microsoft.VisualStudio.LanguageServer.Client;
using Microsoft.VisualStudio.Threading;
using Nerdbank.Streams;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using Roslyn.LanguageServer.Protocol;
using StreamJsonRpc;
@@ -35,7 +34,9 @@ internal abstract partial class AbstractInProcLanguageClient(
AbstractLanguageClientMiddleLayer? middleLayer = null) : ILanguageClient, ILanguageServerFactory, ICapabilitiesProvider, ILanguageClientCustomMessage2
{
private readonly IThreadingContext _threadingContext = threadingContext;
+#pragma warning disable CS0618 // Type or member is obsolete - blocked on Razor switching to new APIs for STJ - https://github.com/dotnet/roslyn/issues/73317
private readonly ILanguageClientMiddleLayer? _middleLayer = middleLayer;
+#pragma warning restore CS0618 // Type or member is obsolete
private readonly ILspServiceLoggerFactory _lspLoggerFactory = lspLoggerFactory;
private readonly ExportProvider _exportProvider = exportProvider;
@@ -200,10 +201,9 @@ internal async Task> CreateAsync> CreateAsync> CreateAsync Create(
JsonRpc jsonRpc,
- JsonSerializer jsonSerializer,
+ JsonSerializerOptions options,
ICapabilitiesProvider capabilitiesProvider,
WellKnownLspServerKinds serverKind,
AbstractLspLogger logger,
@@ -236,7 +236,7 @@ public virtual AbstractLanguageServer Create(
var server = new RoslynLanguageServer(
LspServiceProvider,
jsonRpc,
- jsonSerializer,
+ options,
capabilitiesProvider,
logger,
hostServices,
diff --git a/src/EditorFeatures/Core/LanguageServer/AbstractLanguageClientMiddleLayer.cs b/src/EditorFeatures/Core/LanguageServer/AbstractLanguageClientMiddleLayer.cs
index e7c26c5b245b0..1ecbf95264cf7 100644
--- a/src/EditorFeatures/Core/LanguageServer/AbstractLanguageClientMiddleLayer.cs
+++ b/src/EditorFeatures/Core/LanguageServer/AbstractLanguageClientMiddleLayer.cs
@@ -1,4 +1,4 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
@@ -9,11 +9,13 @@
namespace Microsoft.CodeAnalysis.Editor.Implementation.LanguageClient;
+#pragma warning disable CS0618 // Type or member is obsolete - blocked on Razor switching to new APIs for STJ - https://github.com/dotnet/roslyn/issues/73317
internal abstract class AbstractLanguageClientMiddleLayer : ILanguageClientMiddleLayer
+#pragma warning restore CS0618 // Type or member is obsolete
{
public abstract bool CanHandle(string methodName);
public abstract Task HandleNotificationAsync(string methodName, JToken methodParam, Func sendNotification);
public abstract Task HandleRequestAsync(string methodName, JToken methodParam, Func> sendRequest);
-}
\ No newline at end of file
+}
diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.InitializationOptions.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.InitializationOptions.cs
index a817940d49017..8998fcec76edd 100644
--- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.InitializationOptions.cs
+++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.InitializationOptions.cs
@@ -7,6 +7,7 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.Options;
+using StreamJsonRpc;
using LSP = Roslyn.LanguageServer.Protocol;
namespace Roslyn.Test.Utilities
@@ -22,10 +23,12 @@ internal readonly record struct InitializationOptions()
internal LSP.ClientCapabilities ClientCapabilities { get; init; } = new LSP.ClientCapabilities();
internal WellKnownLspServerKinds ServerKind { get; init; } = WellKnownLspServerKinds.AlwaysActiveVSLspServer;
internal Action? OptionUpdater { get; init; } = null;
+ internal bool CallInitialize { get; init; } = true;
internal bool CallInitialized { get; init; } = true;
internal object? ClientTarget { get; init; } = null;
internal string? Locale { get; init; } = null;
internal IEnumerable? AdditionalAnalyzers { get; init; } = null;
+ internal IJsonRpcMessageFormatter? ClientMessageFormatter { get; init; } = null;
}
}
}
diff --git a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
index b4b32bd2383e1..1fa9da38fb528 100644
--- a/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
+++ b/src/EditorFeatures/TestUtilities/LanguageServer/AbstractLanguageServerProtocolTests.cs
@@ -7,6 +7,8 @@
using System.Collections.Immutable;
using System.IO;
using System.Linq;
+using System.Text.Json;
+using System.Text.Json.Serialization.Metadata;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
@@ -26,13 +28,11 @@
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.Extensions;
using Microsoft.CodeAnalysis.Shared.TestHooks;
-using Microsoft.CodeAnalysis.SolutionCrawler;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Microsoft.CommonLanguageServerProtocol.Framework;
using Nerdbank.Streams;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
+using Roslyn.LanguageServer.Protocol;
using Roslyn.Utilities;
using StreamJsonRpc;
using Xunit;
@@ -44,6 +44,8 @@ namespace Roslyn.Test.Utilities
[UseExportProvider]
public abstract partial class AbstractLanguageServerProtocolTests
{
+ private static readonly SystemTextJsonFormatter s_messageFormatter = RoslynLanguageServer.CreateJsonMessageFormatter();
+
private protected readonly AbstractLspLogger TestOutputLspLogger;
protected AbstractLanguageServerProtocolTests(ITestOutputHelper? testOutputHelper)
{
@@ -124,8 +126,8 @@ private protected static LSP.ClientCapabilities GetCapabilities(bool isVS)
/// the actual object to be converted to JSON.
public static void AssertJsonEquals(T1 expected, T2 actual)
{
- var expectedStr = JsonConvert.SerializeObject(expected);
- var actualStr = JsonConvert.SerializeObject(actual);
+ var expectedStr = JsonSerializer.Serialize(expected, s_messageFormatter.JsonSerializerOptions);
+ var actualStr = JsonSerializer.Serialize(actual, s_messageFormatter.JsonSerializerOptions);
AssertEqualIgnoringWhitespace(expectedStr, actualStr);
}
@@ -269,7 +271,7 @@ private protected static LSP.CompletionParams CreateCompletionParams(
SortText = sortText,
InsertTextFormat = LSP.InsertTextFormat.Plaintext,
Kind = kind,
- Data = JObject.FromObject(new CompletionResolveData(resultId, ProtocolConversions.DocumentToTextDocumentIdentifier(document))),
+ Data = JsonSerializer.SerializeToElement(new CompletionResolveData(resultId, ProtocolConversions.DocumentToTextDocumentIdentifier(document)), s_messageFormatter.JsonSerializerOptions),
Preselect = preselect,
VsResolveTextEditOnCommit = vsResolveTextEditOnCommit,
LabelDetails = labelDetails
@@ -512,13 +514,6 @@ private static LSP.DidCloseTextDocumentParams CreateDidCloseTextDocumentParams(U
}
};
- internal static JsonMessageFormatter CreateJsonMessageFormatter()
- {
- var messageFormatter = new JsonMessageFormatter();
- LSP.VSInternalExtensionUtilities.AddVSInternalExtensionConverters(messageFormatter.JsonSerializer);
- return messageFormatter;
- }
-
internal sealed class TestLspServer : IAsyncDisposable
{
public readonly EditorTestWorkspace TestWorkspace;
@@ -536,7 +531,8 @@ private TestLspServer(
LSP.ClientCapabilities clientCapabilities,
RoslynLanguageServer target,
Stream clientStream,
- object? clientTarget = null)
+ object? clientTarget = null,
+ IJsonRpcMessageFormatter? clientMessageFormatter = null)
{
TestWorkspace = testWorkspace;
ClientCapabilities = clientCapabilities;
@@ -545,7 +541,9 @@ private TestLspServer(
LanguageServer = target;
- _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, CreateJsonMessageFormatter()), clientTarget)
+ clientMessageFormatter ??= RoslynLanguageServer.CreateJsonMessageFormatter();
+
+ _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, clientMessageFormatter), clientTarget)
{
ExceptionStrategy = ExceptionProcessing.ISerializable,
};
@@ -571,13 +569,16 @@ internal static async Task CreateAsync(EditorTestWorkspace testWo
var (clientStream, serverStream) = FullDuplexStream.CreatePair();
var languageServer = CreateLanguageServer(serverStream, serverStream, testWorkspace, initializationOptions.ServerKind, logger);
- var server = new TestLspServer(testWorkspace, locations, initializationOptions.ClientCapabilities, languageServer, clientStream, initializationOptions.ClientTarget);
+ var server = new TestLspServer(testWorkspace, locations, initializationOptions.ClientCapabilities, languageServer, clientStream, initializationOptions.ClientTarget, initializationOptions.ClientMessageFormatter);
- await server.ExecuteRequestAsync(LSP.Methods.InitializeName, new LSP.InitializeParams
+ if (initializationOptions.CallInitialize)
{
- Capabilities = initializationOptions.ClientCapabilities,
- Locale = initializationOptions.Locale,
- }, CancellationToken.None);
+ await server.ExecuteRequestAsync(LSP.Methods.InitializeName, new LSP.InitializeParams
+ {
+ Capabilities = initializationOptions.ClientCapabilities,
+ Locale = initializationOptions.Locale,
+ }, CancellationToken.None);
+ }
if (initializationOptions.CallInitialized)
{
@@ -607,13 +608,13 @@ private static RoslynLanguageServer CreateLanguageServer(Stream inputStream, Str
var capabilitiesProvider = workspace.ExportProvider.GetExportedValue();
var factory = workspace.ExportProvider.GetExportedValue();
- var jsonMessageFormatter = CreateJsonMessageFormatter();
+ var jsonMessageFormatter = RoslynLanguageServer.CreateJsonMessageFormatter();
var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(outputStream, inputStream, jsonMessageFormatter))
{
ExceptionStrategy = ExceptionProcessing.ISerializable,
};
- var languageServer = (RoslynLanguageServer)factory.Create(jsonRpc, jsonMessageFormatter.JsonSerializer, capabilitiesProvider, serverKind, logger, workspace.Services.HostServices);
+ var languageServer = (RoslynLanguageServer)factory.Create(jsonRpc, jsonMessageFormatter.JsonSerializerOptions, capabilitiesProvider, serverKind, logger, workspace.Services.HostServices);
jsonRpc.StartListening();
return languageServer;
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/LspFileChangeWatcherTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/LspFileChangeWatcherTests.cs
index 4be80e009e63a..a87b6604e47f6 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/LspFileChangeWatcherTests.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/LspFileChangeWatcherTests.cs
@@ -3,12 +3,11 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Concurrent;
+using System.Text.Json;
using Microsoft.CodeAnalysis.LanguageServer.HostWorkspace.FileWatching;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.LanguageServer.Protocol;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using StreamJsonRpc;
using Xunit.Abstractions;
using FileSystemWatcher = Roslyn.LanguageServer.Protocol.FileSystemWatcher;
@@ -115,8 +114,8 @@ private static async Task WaitForFileWatcherAsync(TestLspServer testLspServer)
private static FileSystemWatcher GetSingleFileWatcher(DynamicCapabilitiesRpcTarget dynamicCapabilities)
{
- var registrationJson = Assert.IsType(Assert.Single(dynamicCapabilities.Registrations).Value.RegisterOptions);
- var registration = registrationJson.ToObject()!;
+ var registrationJson = Assert.IsType(Assert.Single(dynamicCapabilities.Registrations).Value.RegisterOptions);
+ var registration = JsonSerializer.Deserialize(registrationJson, ProtocolConversions.LspJsonSerializerOptions)!;
return Assert.Single(registration.Watchers);
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs
index 49c5e48bb623f..504c980a16409 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer.UnitTests/Utilities/AbstractLanguageServerHostTests.cs
@@ -52,7 +52,8 @@ private TestLspServer(ExportProvider exportProvider, ILogger logger)
var (clientStream, serverStream) = FullDuplexStream.CreatePair();
LanguageServerHost = new LanguageServerHost(serverStream, serverStream, exportProvider, logger);
- _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, new JsonMessageFormatter()))
+ var messageFormatter = LanguageServerHost.CreateJsonMessageFormatter();
+ _clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientStream, clientStream, messageFormatter))
{
AllowModificationWhileListening = true,
ExceptionStrategy = ExceptionProcessing.ISerializable,
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerConnectHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerConnectHandler.cs
index 8c6d5c693539c..a0f0dbbca8ecc 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerConnectHandler.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/BrokeredServices/ServiceBrokerConnectHandler.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Composition;
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CommonLanguageServerProtocol.Framework;
@@ -32,10 +32,9 @@ Task INotificationHandler.HandleNotification
return _serviceBrokerFactory.CreateAndConnectAsync(request.PipeName);
}
- [DataContract]
private class NotificationParams
{
- [DataMember(Name = "pipeName")]
+ [JsonPropertyName("pipeName")]
public required string PipeName { get; set; }
}
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileWatching/LspContractTypes.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileWatching/LspContractTypes.cs
index 89a3613e08fe5..6cc5edc44e4f2 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileWatching/LspContractTypes.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/FileWatching/LspContractTypes.cs
@@ -3,44 +3,40 @@
// See the LICENSE file in the project root for more information.
using System.Runtime.Serialization;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
namespace Roslyn.LanguageServer.Protocol;
-[DataContract]
internal class DidChangeWatchedFilesRegistrationOptions
{
- [DataMember(Name = "watchers")]
+ [JsonPropertyName("watchers")]
public required FileSystemWatcher[] Watchers { get; set; }
}
-[DataContract]
internal class FileSystemWatcher
{
- [DataMember(Name = "globPattern")]
+ [JsonPropertyName("globPattern")]
public required RelativePattern GlobPattern { get; set; }
- [DataMember(Name = "kind")]
+ [JsonPropertyName("kind")]
public WatchKind? Kind { get; set; }
}
-[DataContract]
internal class RelativePattern
{
- [DataMember(Name = "baseUri")]
+ [JsonPropertyName("baseUri")]
[JsonConverter(typeof(DocumentUriConverter))]
public required Uri BaseUri { get; set; }
- [DataMember(Name = "pattern")]
+ [JsonPropertyName("pattern")]
public required string Pattern { get; set; }
}
// The LSP specification has a spelling error in the protocol, but Microsoft.VisualStudio.LanguageServer.Protocol
// didn't carry that error along. This corrects that.
-[DataContract]
internal class UnregistrationParamsWithMisspelling
{
- [DataMember(Name = "unregisterations")]
+ [JsonPropertyName("unregisterations")]
public required Unregistration[] Unregistrations { get; set; }
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenProjectsHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenProjectsHandler.cs
index 1e506c5030387..615c0863e5239 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenProjectsHandler.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenProjectsHandler.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Composition;
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CommonLanguageServerProtocol.Framework;
@@ -32,10 +32,9 @@ Task INotificationHandler.HandleNotification
return _projectSystem.OpenProjectsAsync(request.Projects.SelectAsArray(p => p.LocalPath));
}
- [DataContract]
private class NotificationParams
{
- [DataMember(Name = "projects")]
+ [JsonPropertyName("projects")]
public required Uri[] Projects { get; set; }
}
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenSolutionHandler.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenSolutionHandler.cs
index da7bf9f0c814b..198c329b2ad96 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenSolutionHandler.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/OpenSolutionHandler.cs
@@ -1,9 +1,9 @@
-// Licensed to the .NET Foundation under one or more agreements.
+// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
using System.Composition;
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CommonLanguageServerProtocol.Framework;
@@ -31,10 +31,9 @@ Task INotificationHandler.HandleNotification
return _projectSystem.OpenSolutionAsync(request.Solution.LocalPath);
}
- [DataContract]
private class NotificationParams
{
- [DataMember(Name = "solution")]
+ [JsonPropertyName("solution")]
public required Uri Solution { get; set; }
}
-}
\ No newline at end of file
+}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectDependencyHelper.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectDependencyHelper.cs
index 94509a2ab2ba7..ac0659d8c0df4 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectDependencyHelper.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectDependencyHelper.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Collections.Immutable;
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
using Microsoft.CodeAnalysis.MSBuild;
using Microsoft.CodeAnalysis.PooledObjects;
@@ -134,7 +134,6 @@ internal static async Task RestoreProjectsAsync(ImmutableArray projectPa
await languageServerManager.SendRequestAsync(ProjectNeedsRestoreName, unresolvedParams, cancellationToken);
}
- [DataContract]
private record UnresolvedDependenciesParams(
- [property: DataMember(Name = "projectFilePaths")] string[] ProjectFilePaths);
+ [property: JsonPropertyName("projectFilePaths")] string[] ProjectFilePaths);
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryEvent.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryEvent.cs
index 97c89c8ff79f8..63f16c646f97a 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryEvent.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/ProjectTelemetry/ProjectLoadTelemetryEvent.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace.ProjectTelemetry;
@@ -12,17 +12,16 @@ namespace Microsoft.CodeAnalysis.LanguageServer.HostWorkspace.ProjectTelemetry;
/// except for SdkVersion, which is unused by the client in the O# version.
///
-[DataContract]
internal record ProjectLoadTelemetryEvent(
// The project guid (if it came from a solution), or a hash representing the file path and contents.
- [property: DataMember(Name = "ProjectId")] string ProjectId,
- [property: DataMember(Name = "SessionId")] string SessionId,
- [property: DataMember(Name = "OutputKind")] int OutputKind,
- [property: DataMember(Name = "ProjectCapabilities")] IEnumerable ProjectCapabilities,
- [property: DataMember(Name = "TargetFrameworks")] IEnumerable TargetFrameworks,
- [property: DataMember(Name = "References")] IEnumerable References,
- [property: DataMember(Name = "FileExtensions")] IEnumerable FileExtensions,
- [property: DataMember(Name = "FileCounts")] IEnumerable FileCounts,
- [property: DataMember(Name = "SdkStyleProject")] bool SdkStyleProject)
+ [property: JsonPropertyName("ProjectId")] string ProjectId,
+ [property: JsonPropertyName("SessionId")] string SessionId,
+ [property: JsonPropertyName("OutputKind")] int OutputKind,
+ [property: JsonPropertyName("ProjectCapabilities")] IEnumerable ProjectCapabilities,
+ [property: JsonPropertyName("TargetFrameworks")] IEnumerable TargetFrameworks,
+ [property: JsonPropertyName("References")] IEnumerable References,
+ [property: JsonPropertyName("FileExtensions")] IEnumerable FileExtensions,
+ [property: JsonPropertyName("FileCounts")] IEnumerable FileCounts,
+ [property: JsonPropertyName("SdkStyleProject")] bool SdkStyleProject)
{
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs
index fd5f36244b1f9..beae910355125 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/HostWorkspace/RazorDynamicFileInfoProvider.cs
@@ -3,7 +3,7 @@
// See the LICENSE file in the project root for more information.
using System.Composition;
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Host.Mef;
using Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
@@ -18,26 +18,23 @@ internal class RazorDynamicFileInfoProvider : IDynamicFileInfoProvider
{
private const string ProvideRazorDynamicFileInfoMethodName = "razor/provideDynamicFileInfo";
- [DataContract]
private class ProvideDynamicFileParams
{
- [DataMember(Name = "razorFiles")]
+ [JsonPropertyName("razorFiles")]
public required Uri[] RazorFiles { get; set; }
}
- [DataContract]
private class ProvideDynamicFileResponse
{
- [DataMember(Name = "generatedFiles")]
+ [JsonPropertyName("generatedFiles")]
public required Uri[] GeneratedFiles { get; set; }
}
private const string RemoveRazorDynamicFileInfoMethodName = "razor/removeDynamicFileInfo";
- [DataContract]
private class RemoveDynamicFileParams
{
- [DataMember(Name = "razorFiles")]
+ [JsonPropertyName("razorFiles")]
public required Uri[] RazorFiles { get; set; }
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/ProjectDebugConfiguration.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/ProjectDebugConfiguration.cs
index 82e2ab5fa530c..158a7f99d7604 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/ProjectDebugConfiguration.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/ProjectDebugConfiguration.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DebugConfiguration;
-[DataContract]
internal class ProjectDebugConfiguration
{
public ProjectDebugConfiguration(string projectPath, string outputPath, string projectName, bool targetsDotnetCore, bool isExe, string? solutionPath)
@@ -20,21 +18,21 @@ public ProjectDebugConfiguration(string projectPath, string outputPath, string p
SolutionPath = solutionPath;
}
- [JsonProperty(PropertyName = "projectPath")]
+ [JsonPropertyName("projectPath")]
public string ProjectPath { get; }
- [JsonProperty(PropertyName = "outputPath")]
+ [JsonPropertyName("outputPath")]
public string OutputPath { get; }
- [JsonProperty(PropertyName = "projectName")]
+ [JsonPropertyName("projectName")]
public string ProjectName { get; }
- [JsonProperty(PropertyName = "targetsDotnetCore")]
+ [JsonPropertyName("targetsDotnetCore")]
public bool TargetsDotnetCore { get; }
- [JsonProperty(PropertyName = "isExe")]
+ [JsonPropertyName("isExe")]
public bool IsExe { get; }
- [JsonProperty(PropertyName = "solutionPath")]
+ [JsonPropertyName("solutionPath")]
public string? SolutionPath { get; }
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationParams.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationParams.cs
index 1d3b795be6ba1..ac806d4fe897b 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationParams.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/DebugConfiguration/WorkspaceDebugConfigurationParams.cs
@@ -2,12 +2,10 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
using Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler.DebugConfiguration;
-[DataContract]
internal record WorkspaceDebugConfigurationParams(
- [JsonProperty(PropertyName = "workspacePath"), JsonConverter(typeof(DocumentUriConverter))] Uri WorkspacePath);
+ [property: JsonPropertyName("workspacePath"), JsonConverter(typeof(DocumentUriConverter))] Uri WorkspacePath);
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestoreParams.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestoreParams.cs
index 44bf12762fc65..2717d9c21f953 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestoreParams.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestoreParams.cs
@@ -2,19 +2,17 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
-using Newtonsoft.Json;
+using System.Text.Json.Serialization;
using Roslyn.LanguageServer.Protocol;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler;
-[DataContract]
internal sealed record RestoreParams(
// An empty set of project file paths means restore all projects in the workspace.
- [property: DataMember(Name = "projectFilePaths")] string[] ProjectFilePaths
+ [property: JsonPropertyName("projectFilePaths")] string[] ProjectFilePaths
) : IPartialResultParams
{
- [DataMember(Name = Methods.PartialResultTokenName)]
- [JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
+ [JsonPropertyName(Methods.PartialResultTokenName)]
+ [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
public IProgress? PartialResultToken { get; set; }
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestorePartialResult.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestorePartialResult.cs
index 40731e53c9d9d..52a26da7932ca 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestorePartialResult.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/Handler/Restore/RestorePartialResult.cs
@@ -2,12 +2,11 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
namespace Microsoft.CodeAnalysis.LanguageServer.Handler;
-[DataContract]
internal sealed record RestorePartialResult(
- [property: DataMember(Name = "stage")] string Stage,
- [property: DataMember(Name = "message")] string Message
+ [property: JsonPropertyName("stage")] string Stage,
+ [property: JsonPropertyName("message")] string Message
);
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs
index 013a155b73eb5..d0cca0eb209bc 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/LanguageServer/LanguageServerHost.cs
@@ -7,6 +7,7 @@
using Microsoft.CommonLanguageServerProtocol.Framework;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.Composition;
+using Roslyn.LanguageServer.Protocol;
using StreamJsonRpc;
namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
@@ -28,7 +29,8 @@ internal sealed class LanguageServerHost
public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, ILogger logger)
{
- var messageFormatter = new JsonMessageFormatter();
+ var messageFormatter = CreateJsonMessageFormatter();
+
var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, messageFormatter);
// If there is a jsonrpc disconnect or server shutdown, that is handled by the AbstractLanguageServer. No need to do anything here.
@@ -44,7 +46,15 @@ public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvide
var lspLogger = new LspServiceLogger(_logger);
var hostServices = exportProvider.GetExportedValue().HostServices;
- _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, messageFormatter.JsonSerializer, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices);
+ _roslynLanguageServer = roslynLspFactory.Create(_jsonRpc, messageFormatter.JsonSerializerOptions, capabilitiesProvider, WellKnownLspServerKinds.CSharpVisualBasicLspServer, lspLogger, hostServices);
+ }
+
+ internal static SystemTextJsonFormatter CreateJsonMessageFormatter()
+ {
+ var messageFormatter = new SystemTextJsonFormatter();
+ messageFormatter.JsonSerializerOptions.AddVSCodeInternalExtensionConverters();
+ messageFormatter.JsonSerializerOptions.Converters.Add(new NaturalObjectConverter());
+ return messageFormatter;
}
public void Start()
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs
index b9b7ea2f7a8b8..f223114d93364 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Logging/ShowToastNotification.cs
@@ -2,7 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
using Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
using Roslyn.Utilities;
using LSP = Roslyn.LanguageServer.Protocol;
@@ -33,9 +33,8 @@ public static async Task ShowToastNotificationAsync(LSP.MessageType messageType,
await languageServerManager.SendNotificationAsync(ShowToastNotificationName, toastParams, cancellationToken);
}
- [DataContract]
private record ShowToastNotificationParams(
- [property: DataMember(Name = "messageType")] LSP.MessageType MessageType,
- [property: DataMember(Name = "message")] string Message,
- [property: DataMember(Name = "commands")] LSP.Command[] Commands);
+ [property: JsonPropertyName("messageType")] LSP.MessageType MessageType,
+ [property: JsonPropertyName("message")] string Message,
+ [property: JsonPropertyName("commands")] LSP.Command[] Commands);
}
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/NamedPipeInformation.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/NamedPipeInformation.cs
index 650febe23b4a6..e09710a795c5f 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/NamedPipeInformation.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/NamedPipeInformation.cs
@@ -2,10 +2,9 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
-using System.Runtime.Serialization;
+using System.Text.Json.Serialization;
namespace Microsoft.CodeAnalysis.LanguageServer;
-[DataContract]
internal record NamedPipeInformation(
- [property: DataMember(Name = "pipeName")] string PipeName);
+ [property: JsonPropertyName("pipeName")] string PipeName);
diff --git a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs
index 5b9b44969f8ab..6baf739265c61 100644
--- a/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs
+++ b/src/Features/LanguageServer/Microsoft.CodeAnalysis.LanguageServer/Program.cs
@@ -8,6 +8,7 @@
using System.IO.Pipes;
using System.Runtime.InteropServices;
using System.Runtime.Loader;
+using System.Text.Json;
using Microsoft.CodeAnalysis.Contracts.Telemetry;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.LanguageServer.BrokeredServices;
@@ -18,7 +19,6 @@
using Microsoft.CodeAnalysis.LanguageServer.StarredSuggestions;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Console;
-using Newtonsoft.Json;
using Roslyn.Utilities;
// Setting the title can fail if the process is run without a window, such
@@ -120,7 +120,7 @@ static async Task RunAsync(ServerConfiguration serverConfiguration, Cancellation
PipeOptions.CurrentUserOnly | PipeOptions.Asynchronous);
// Send the named pipe connection info to the client
- Console.WriteLine(JsonConvert.SerializeObject(new NamedPipeInformation(clientPipeName)));
+ Console.WriteLine(JsonSerializer.Serialize(new NamedPipeInformation(clientPipeName)));
// Wait for connection from client
await pipeServer.WaitForConnectionAsync(cancellationToken);
diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.Example/ExampleLanguageServer.cs b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.Example/ExampleLanguageServer.cs
index 4d6774ecd3ab3..db1d59015f096 100644
--- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.Example/ExampleLanguageServer.cs
+++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.Example/ExampleLanguageServer.cs
@@ -3,19 +3,19 @@
// See the LICENSE file in the project root for more information.
using System;
+using System.Text.Json;
using Microsoft.CommonLanguageServerProtocol.Framework.Handlers;
using Microsoft.Extensions.DependencyInjection;
-using Newtonsoft.Json;
using Roslyn.LanguageServer.Protocol;
using StreamJsonRpc;
namespace Microsoft.CommonLanguageServerProtocol.Framework.Example;
-internal class ExampleLanguageServer : AbstractLanguageServer
+internal class ExampleLanguageServer : SystemTextJsonLanguageServer
{
private readonly Action? _addExtraHandlers;
- public ExampleLanguageServer(JsonRpc jsonRpc, JsonSerializer jsonSerializer, ILspLogger logger, Action? addExtraHandlers) : base(jsonRpc, jsonSerializer, logger)
+ public ExampleLanguageServer(JsonRpc jsonRpc, JsonSerializerOptions options, ILspLogger logger, Action? addExtraHandlers) : base(jsonRpc, options, logger)
{
_addExtraHandlers = addExtraHandlers;
// This spins up the queue and ensure the LSP is ready to start receiving requests
diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/RequestExecutionQueueTests.cs b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/RequestExecutionQueueTests.cs
index 1766f5eeebebc..2a6010a8d4630 100644
--- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/RequestExecutionQueueTests.cs
+++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/RequestExecutionQueueTests.cs
@@ -14,7 +14,7 @@ namespace Microsoft.CommonLanguageServerProtocol.Framework.UnitTests;
public class RequestExecutionQueueTests
{
- private class MockServer : AbstractLanguageServer
+ private class MockServer : NewtonsoftLanguageServer
{
public MockServer() : base(new JsonRpc(new HeaderDelimitedMessageHandler(FullDuplexStream.CreatePair().Item1)), JsonSerializer.CreateDefault(), NoOpLspLogger.Instance)
{
diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/TestExampleLanguageServer.cs b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/TestExampleLanguageServer.cs
index 8754366f4f30a..f0ae9582cf262 100644
--- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/TestExampleLanguageServer.cs
+++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework.UnitTests/TestExampleLanguageServer.cs
@@ -4,12 +4,12 @@
using System;
using System.IO;
+using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CommonLanguageServerProtocol.Framework.Example;
using Microsoft.Extensions.DependencyInjection;
using Nerdbank.Streams;
-using Newtonsoft.Json;
using Roslyn.LanguageServer.Protocol;
using StreamJsonRpc;
@@ -19,8 +19,8 @@ internal class TestExampleLanguageServer : ExampleLanguageServer
{
private readonly JsonRpc _clientRpc;
- public TestExampleLanguageServer(Stream clientSteam, JsonRpc jsonRpc, JsonSerializer jsonSerializer, ILspLogger logger, Action? addExtraHandlers)
- : base(jsonRpc, jsonSerializer, logger, addExtraHandlers)
+ public TestExampleLanguageServer(Stream clientSteam, JsonRpc jsonRpc, JsonSerializerOptions options, ILspLogger logger, Action? addExtraHandlers)
+ : base(jsonRpc, options, logger, addExtraHandlers)
{
_clientRpc = new JsonRpc(new HeaderDelimitedMessageHandler(clientSteam, clientSteam, CreateJsonMessageFormatter()))
{
@@ -102,10 +102,10 @@ internal async Task WaitForExit()
return await _exiting.Task;
}
- private static JsonMessageFormatter CreateJsonMessageFormatter()
+ private static SystemTextJsonFormatter CreateJsonMessageFormatter()
{
- var messageFormatter = new JsonMessageFormatter();
- messageFormatter.JsonSerializer.AddVSInternalExtensionConverters();
+ var messageFormatter = new SystemTextJsonFormatter();
+ messageFormatter.JsonSerializerOptions.AddVSCodeInternalExtensionConverters();
return messageFormatter;
}
@@ -121,7 +121,7 @@ internal static TestExampleLanguageServer CreateBadLanguageServer(ILspLogger log
serviceCollection.AddSingleton();
};
- var server = new TestExampleLanguageServer(clientStream, jsonRpc, messageFormatter.JsonSerializer, logger, extraHandlers);
+ var server = new TestExampleLanguageServer(clientStream, jsonRpc, messageFormatter.JsonSerializerOptions, logger, extraHandlers);
jsonRpc.StartListening();
server.InitializeTest();
@@ -135,7 +135,7 @@ internal static TestExampleLanguageServer CreateLanguageServer(ILspLogger logger
var messageFormatter = CreateJsonMessageFormatter();
var jsonRpc = new JsonRpc(new HeaderDelimitedMessageHandler(serverStream, serverStream, messageFormatter));
- var server = new TestExampleLanguageServer(clientStream, jsonRpc, messageFormatter.JsonSerializer, logger, addExtraHandlers: null);
+ var server = new TestExampleLanguageServer(clientStream, jsonRpc, messageFormatter.JsonSerializerOptions, logger, addExtraHandlers: null);
jsonRpc.StartListening();
server.InitializeTest();
diff --git a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractLanguageServer.cs b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractLanguageServer.cs
index 8dddabcf31dbe..2a3ca52c14099 100644
--- a/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractLanguageServer.cs
+++ b/src/Features/LanguageServer/Microsoft.CommonLanguageServerProtocol.Framework/AbstractLanguageServer.cs
@@ -12,8 +12,6 @@
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
-using Newtonsoft.Json;
-using Newtonsoft.Json.Linq;
using StreamJsonRpc;
namespace Microsoft.CommonLanguageServerProtocol.Framework;
@@ -23,8 +21,6 @@ internal abstract class AbstractLanguageServer
private readonly JsonRpc _jsonRpc;
protected readonly ILspLogger Logger;
- protected readonly JsonSerializer _jsonSerializer;
-
///
/// These are lazy to allow implementations to define custom variables that are used by
/// or
@@ -58,12 +54,10 @@ internal abstract class AbstractLanguageServer
protected AbstractLanguageServer(
JsonRpc jsonRpc,
- JsonSerializer jsonSerializer,
ILspLogger logger)
{
Logger = logger;
_jsonRpc = jsonRpc;
- _jsonSerializer = jsonSerializer;
_jsonRpc.AddLocalRpcTarget(this);
_jsonRpc.Disconnected += JsonRpc_Disconnected;
@@ -102,7 +96,6 @@ protected virtual AbstractHandlerProvider HandlerProvider
protected virtual void SetupRequestDispatcher(AbstractHandlerProvider handlerProvider)
{
- var entryPointMethodInfo = typeof(DelegatingEntryPoint).GetMethod(nameof(DelegatingEntryPoint.ExecuteRequestAsync))!;
// Get unique set of methods from the handler provider for the default language.
foreach (var methodGroup in handlerProvider
.GetRegisteredMethods()
@@ -127,13 +120,16 @@ protected virtual void SetupRequestDispatcher(AbstractHandlerProvider handlerPro
throw new InvalidOperationException($"Language specific handlers for {methodGroup.Key} have mis-matched number of returns:{Environment.NewLine}{string.Join(Environment.NewLine, methodGroup)}");
}
- var delegatingEntryPoint = new DelegatingEntryPoint(methodGroup.Key, this, methodGroup);
+ var delegatingEntryPoint = CreateDelegatingEntryPoint(methodGroup.Key, methodGroup);
var methodAttribute = new JsonRpcMethodAttribute(methodGroup.Key)
{
UseSingleObjectParameterDeserialization = true,
};
- _jsonRpc.AddLocalRpcMethod(entryPointMethodInfo, delegatingEntryPoint, methodAttribute);
+ // We verified above that parameters match, set flag if this request has parameters or is parameterless so we can set the entrypoint correctly.
+ var hasParameters = methodGroup.First().RequestType != null;
+ var entryPoint = delegatingEntryPoint.GetEntryPoint(hasParameters);
+ _jsonRpc.AddLocalRpcMethod(entryPoint, delegatingEntryPoint, methodAttribute);
}
static bool AllTypesMatch(IEnumerable types)
@@ -178,24 +174,18 @@ protected IRequestExecutionQueue GetRequestExecutionQueue()
return _queue.Value;
}
- protected virtual string GetLanguageForRequest(string methodName, JToken? parameters)
- {
- Logger.LogInformation($"Using default language handler for {methodName}");
- return LanguageServerConstants.DefaultLanguageName;
- }
+ protected abstract DelegatingEntryPoint CreateDelegatingEntryPoint(string method, IGrouping handlersForMethod);
- private sealed class DelegatingEntryPoint
+ protected abstract class DelegatingEntryPoint
{
- private readonly string _method;
- private readonly Lazy> _languageEntryPoint;
- private readonly AbstractLanguageServer _target;
+ protected readonly string _method;
+ protected readonly Lazy> _languageEntryPoint;
private static readonly MethodInfo s_queueExecuteAsyncMethod = typeof(RequestExecutionQueue).GetMethod(nameof(RequestExecutionQueue.ExecuteAsync))!;
- public DelegatingEntryPoint(string method, AbstractLanguageServer target, IGrouping handlersForMethod)
+ public DelegatingEntryPoint(string method, IGrouping handlersForMethod)
{
_method = method;
- _target = target;
_languageEntryPoint = new Lazy>(() =>
{
var handlerEntryPoints = new Dictionary();
@@ -211,61 +201,40 @@ public DelegatingEntryPoint(string method, AbstractLanguageServer
- /// StreamJsonRpc entry point for all handler methods.
- /// The optional parameters allow StreamJsonRpc to call into the same method for any kind of request / notification (with any number of params or response).
- ///
- public async Task ExecuteRequestAsync(JToken? request = null, CancellationToken cancellationToken = default)
- {
- var queue = _target.GetRequestExecutionQueue();
- var lspServices = _target.GetLspServices();
-
- // Retrieve the language of the request so we know how to deserialize it.
- var language = _target.GetLanguageForRequest(_method, request);
+ public abstract MethodInfo GetEntryPoint(bool hasParameter);
- // Find the correct request and response types for the given request and language.
+ protected (MethodInfo MethodInfo, RequestHandlerMetadata Metadata) GetMethodInfo(string language)
+ {
if (!_languageEntryPoint.Value.TryGetValue(language, out var requestInfo)
&& !_languageEntryPoint.Value.TryGetValue(LanguageServerConstants.DefaultLanguageName, out requestInfo))
{
throw new InvalidOperationException($"No default or language specific handler was found for {_method} and document with language {language}");
}
- // Deserialize the request parameters (if any).
- var requestObject = DeserializeRequest(request, requestInfo.Metadata, _target._jsonSerializer);
+ return requestInfo;
+ }
- var task = requestInfo.MethodInfo.Invoke(queue, [requestObject, _method, language, lspServices, cancellationToken]) as Task
+ protected async Task