Skip to content

Commit

Permalink
Merge pull request #74280 from davidwengier/RemoteSTJServices
Browse files Browse the repository at this point in the history
Allow services to use System.Text.Json for OOP comms in Razor
  • Loading branch information
davidwengier authored Jul 15, 2024
2 parents 140ea50 + e8a490a commit 70a4dc0
Show file tree
Hide file tree
Showing 6 changed files with 88 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.ExternalAccess.Razor" />
<!-- Restricted IVT is direct for protocol types only -->
<RestrictedInternalsVisibleTo Include="Microsoft.CodeAnalysis.Remote.Razor" Namespace="Roslyn.LanguageServer.Protocol" Partner="Razor" Key="$(RazorKey)" />
<RestrictedInternalsVisibleTo Include="Microsoft.CodeAnalysis.Razor.Workspaces" Namespace="Roslyn.LanguageServer.Protocol" Partner="Razor" Key="$(RazorKey)" />
<RestrictedInternalsVisibleTo Include="Microsoft.VisualStudio.LanguageServices.Razor" Namespace="Roslyn.LanguageServer.Protocol" Partner="Razor" Key="$(RazorKey)" />
<InternalsVisibleTo Include="Microsoft.CodeAnalysis.ExternalAccess.Xaml" />
<!-- Restricted IVT is direct for protocol types only -->
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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;
using System.Text.Json.Serialization;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
/// <summary>
/// Represents a DocumentId that can be used by Razor for OOP services that communicate via System.Text.Json
/// </summary>
internal readonly record struct JsonSerializableDocumentId(
[property: JsonPropertyName("projectId")] Guid ProjectId,
[property: JsonPropertyName("id")] Guid Id)
{
public static implicit operator JsonSerializableDocumentId(DocumentId documentId)
{
return new JsonSerializableDocumentId(documentId.ProjectId.Id, documentId.Id);
}

public static implicit operator DocumentId(JsonSerializableDocumentId serializableDocumentId)
{
return DocumentId.CreateFromSerialized(CodeAnalysis.ProjectId.CreateFromSerialized(serializableDocumentId.ProjectId), serializableDocumentId.Id);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
// 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;
using System.Text.Json.Serialization;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
/// <summary>
/// A wrapper for a solution that can be used by Razor for OOP services that communicate via System.Text.Json
/// </summary>
internal readonly record struct JsonSerializableRazorPinnedSolutionInfoWrapper(
[property: JsonPropertyName("data1")] long Data1,
[property: JsonPropertyName("data2")] long Data2)
{
public static implicit operator JsonSerializableRazorPinnedSolutionInfoWrapper(RazorPinnedSolutionInfoWrapper info)
{
return new JsonSerializableRazorPinnedSolutionInfoWrapper(info.UnderlyingObject.Data1, info.UnderlyingObject.Data2);
}

public static implicit operator RazorPinnedSolutionInfoWrapper(JsonSerializableRazorPinnedSolutionInfoWrapper serializableDocumentId)
{
return new RazorPinnedSolutionInfoWrapper(new Checksum(serializableDocumentId.Data1, serializableDocumentId.Data2));
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,10 +3,12 @@
// See the LICENSE file in the project root for more information.

using System.Runtime.Serialization;
using Microsoft.CodeAnalysis.Remote;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
/// <summary>
/// A wrapper for a solution that can be used by Razor for OOP services that communicate via MessagePack
/// </summary>
[DataContract]
internal readonly struct RazorPinnedSolutionInfoWrapper
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,13 @@
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Runtime;
using System.Text.Json;
using System.Text.Json.Serialization;
using MessagePack;
using MessagePack.Formatters;
using Microsoft.CodeAnalysis.LanguageServer;
using Microsoft.CodeAnalysis.Remote;
using Microsoft.ServiceHub.Framework;
using Newtonsoft.Json;

namespace Microsoft.CodeAnalysis.ExternalAccess.Razor
{
Expand All @@ -30,7 +31,7 @@ public RazorServiceDescriptorsWrapper(
=> UnderlyingObject = new ServiceDescriptors(componentName, featureDisplayNameProvider, new RemoteSerializationOptions(additionalFormatters, additionalResolvers), interfaces);

/// <summary>
/// Creates a service descriptor set for services using JSON serialization.
/// Creates a service descriptor set for services using System.Text.Json serialization.
/// </summary>
public RazorServiceDescriptorsWrapper(
string componentName,
Expand All @@ -45,10 +46,11 @@ public RazorServiceDescriptorsWrapper(
public ServiceJsonRpcDescriptor GetDescriptorForServiceFactory(Type serviceInterface)
=> UnderlyingObject.GetServiceDescriptorForServiceFactory(serviceInterface);

public MessagePackSerializerOptions MessagePackOptions
=> UnderlyingObject.Options.MessagePackOptions;

public ImmutableArray<JsonConverter> JsonConverters
=> UnderlyingObject.Options.JsonConverters;
public static ImmutableArray<JsonConverter> GetLspConverters()
{
var options = new JsonSerializerOptions();
ProtocolConversions.AddLspSerializerOptions(options);
return options.Converters.ToImmutableArray();
}
}
}
21 changes: 20 additions & 1 deletion src/Workspaces/Remote/Core/RemoteSerializationOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,21 @@ public RemoteSerializationOptions(ImmutableArray<IMessagePackFormatter> addition
public RemoteSerializationOptions(ImmutableArray<JsonConverter> jsonConverters)
=> _options = jsonConverters;

public RemoteSerializationOptions(ImmutableArray<System.Text.Json.Serialization.JsonConverter> jsonConverters)
=> _options = jsonConverters;

public MessagePackSerializerOptions MessagePackOptions => (MessagePackSerializerOptions)_options;
public ImmutableArray<JsonConverter> JsonConverters => (ImmutableArray<JsonConverter>)_options;
public ImmutableArray<System.Text.Json.Serialization.JsonConverter> SystemTextJsonConverters => (ImmutableArray<System.Text.Json.Serialization.JsonConverter>)_options;

public ServiceJsonRpcDescriptor.Formatters Formatter
=> _options is MessagePackSerializerOptions ? ServiceJsonRpcDescriptor.Formatters.MessagePack : ServiceJsonRpcDescriptor.Formatters.UTF8;
=> _options switch
{
MessagePackSerializerOptions => ServiceJsonRpcDescriptor.Formatters.MessagePack,
ImmutableArray<JsonConverter> => ServiceJsonRpcDescriptor.Formatters.UTF8,
ImmutableArray<System.Text.Json.Serialization.JsonConverter> => ServiceJsonRpcDescriptor.Formatters.UTF8SystemTextJson,
_ => throw new InvalidOperationException()
};

public ServiceJsonRpcDescriptor.MessageDelimiters MessageDelimiters
=> _options is MessagePackSerializerOptions
Expand All @@ -58,6 +68,15 @@ internal IJsonRpcMessageFormatter ConfigureFormatter(IJsonRpcMessageFormatter fo
// See https://github.com/neuecc/messagepack-csharp.
messagePackFormatter.SetMessagePackSerializerOptions(MessagePackOptions);
}
else if (formatter is SystemTextJsonFormatter stjFormatter)
{
var converters = stjFormatter.JsonSerializerOptions.Converters;

foreach (var converter in SystemTextJsonConverters)
{
converters.Add(converter);
}
}
else
{
var converters = ((JsonMessageFormatter)formatter).JsonSerializer.Converters;
Expand Down

0 comments on commit 70a4dc0

Please sign in to comment.