From 91ab06c1dfad4608fcf399e467bddec0a2bb1e53 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 21 May 2024 15:45:36 +1000 Subject: [PATCH 1/4] Allow Razor to access LSP types through IVT --- .../Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj index 6db127bd2f722..3af6709eb8d2d 100644 --- a/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj +++ b/src/Features/LanguageServer/Protocol/Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj @@ -34,7 +34,11 @@ + + + + From ea165649212439f728cfbb954500b2fd0a6849b6 Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 21 May 2024 15:45:46 +1000 Subject: [PATCH 2/4] Future proof json formatters --- .../ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs b/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs index 81cfa6493e4cd..78104699f3f69 100644 --- a/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs +++ b/src/Tools/ExternalAccess/Razor/RazorLanguageServerFactoryWrapper.cs @@ -67,7 +67,7 @@ internal override DocumentInfo CreateDocumentInfo( internal override void AddJsonConverters(JsonSerializerOptions options) { - VSInternalExtensionUtilities.AddVSInternalExtensionConverters(options); + ProtocolConversions.AddLspSerializerOptions(options); } private class RazorCapabilitiesProvider : ICapabilitiesProvider From 13fbbc26afa670c2b07ffe022ca5263de8c714cd Mon Sep 17 00:00:00 2001 From: David Wengier Date: Tue, 21 May 2024 15:45:56 +1000 Subject: [PATCH 3/4] Expose folding ranges functionality to Razor --- .../FoldingRanges/FoldingRangesHandler.cs | 17 ++++++++++--- .../Razor/Cohost/Handlers/FoldingRanges.cs | 25 +++++++++++++++++++ 2 files changed, 38 insertions(+), 4 deletions(-) create mode 100644 src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs diff --git a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs index 27f5ede88db87..ee5b92c5343e5 100644 --- a/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs +++ b/src/Features/LanguageServer/Protocol/Handler/FoldingRanges/FoldingRangesHandler.cs @@ -14,6 +14,7 @@ using Microsoft.CodeAnalysis.Structure; using Microsoft.CodeAnalysis.Text; using Roslyn.LanguageServer.Protocol; +using Roslyn.Utilities; namespace Microsoft.CodeAnalysis.LanguageServer.Handler { @@ -35,13 +36,21 @@ public FoldingRangesHandler(IGlobalOptionService globalOptions) public TextDocumentIdentifier GetTextDocumentIdentifier(FoldingRangeParams request) => request.TextDocument; - public async Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) + public Task HandleRequestAsync(FoldingRangeParams request, RequestContext context, CancellationToken cancellationToken) { var document = context.Document; if (document is null) - return null; + return SpecializedTasks.Null(); - var options = _globalOptions.GetBlockStructureOptions(document.Project) with + return SpecializedTasks.AsNullable(GetFoldingRangesAsync(_globalOptions, document, cancellationToken)); + } + + internal static Task GetFoldingRangesAsync( + IGlobalOptionService globalOptions, + Document document, + CancellationToken cancellationToken) + { + var options = globalOptions.GetBlockStructureOptions(document.Project) with { // Need to set the block structure guide options to true since the concept does not exist in vscode // but we still want to categorize them as the correct BlockType. @@ -50,7 +59,7 @@ public FoldingRangesHandler(IGlobalOptionService globalOptions) ShowBlockStructureGuidesForCodeLevelConstructs = true }; - return await GetFoldingRangesAsync(document, options, cancellationToken).ConfigureAwait(false); + return GetFoldingRangesAsync(document, options, cancellationToken); } /// diff --git a/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs b/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs new file mode 100644 index 0000000000000..200e40c7eccd5 --- /dev/null +++ b/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs @@ -0,0 +1,25 @@ +// 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.Linq; +using System.Threading; +using System.Threading.Tasks; +using Microsoft.CodeAnalysis.LanguageServer.Handler; +using Microsoft.CodeAnalysis.Options; +using Roslyn.LanguageServer.Protocol; + +namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers +{ + internal static class FoldingRanges + { + public static Task GetFoldingRangesAsync(Document document, CancellationToken cancellationToken) + { + // We need to manually get the IGlobalOptionsService out of the Mef composition, because Razor has its own + // composition so can't import it (and its internal anyway) + var globalOptions = document.Project.Solution.Services.ExportProvider.GetExports().First().Value; + + return FoldingRangesHandler.GetFoldingRangesAsync(globalOptions, document, cancellationToken); + } + } +} From 0e2d87e0158264a842a9f0a3927cf022c80d378e Mon Sep 17 00:00:00 2001 From: David Wengier Date: Wed, 22 May 2024 08:05:51 +1000 Subject: [PATCH 4/4] PR Feedback etc. --- .../Protocol/Extensions/ProtocolConversions.cs | 2 +- .../Converters/NaturalObjectConverter.cs | 6 ++++-- .../Razor/Cohost/Handlers/FoldingRanges.cs | 17 ++++++++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs index 9b18f67090ed1..2f00c118bca7e 100644 --- a/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs +++ b/src/Features/LanguageServer/Protocol/Extensions/ProtocolConversions.cs @@ -110,7 +110,7 @@ internal static partial class ProtocolConversions public static JsonSerializerOptions AddLspSerializerOptions(this JsonSerializerOptions options) { LSP.VSInternalExtensionUtilities.AddVSInternalExtensionConverters(options); - options.Converters.Add(new NaturalObjectConverter()); + options.Converters.Add(new LSP.NaturalObjectConverter()); return options; } diff --git a/src/Features/LanguageServer/Protocol/Protocol/Converters/NaturalObjectConverter.cs b/src/Features/LanguageServer/Protocol/Protocol/Converters/NaturalObjectConverter.cs index c69b5f8bfbeb8..727c163990c39 100644 --- a/src/Features/LanguageServer/Protocol/Protocol/Converters/NaturalObjectConverter.cs +++ b/src/Features/LanguageServer/Protocol/Protocol/Converters/NaturalObjectConverter.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. @@ -7,6 +7,8 @@ using System.Text.Json; using System.Text.Json.Serialization; +namespace Roslyn.LanguageServer.Protocol; + // copied from https://github.com/dotnet/runtime/issues/98038 to match newtonsoft behavior internal class NaturalObjectConverter : JsonConverter { @@ -68,4 +70,4 @@ public override void Write(Utf8JsonWriter writer, object value, JsonSerializerOp throw new JsonException(); } } -} \ No newline at end of file +} diff --git a/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs b/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs index 200e40c7eccd5..33237859a59e4 100644 --- a/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs +++ b/src/Tools/ExternalAccess/Razor/Cohost/Handlers/FoldingRanges.cs @@ -9,17 +9,16 @@ using Microsoft.CodeAnalysis.Options; using Roslyn.LanguageServer.Protocol; -namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers +namespace Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost.Handlers; + +internal static class FoldingRanges { - internal static class FoldingRanges + public static Task GetFoldingRangesAsync(Document document, CancellationToken cancellationToken) { - public static Task GetFoldingRangesAsync(Document document, CancellationToken cancellationToken) - { - // We need to manually get the IGlobalOptionsService out of the Mef composition, because Razor has its own - // composition so can't import it (and its internal anyway) - var globalOptions = document.Project.Solution.Services.ExportProvider.GetExports().First().Value; + // We need to manually get the IGlobalOptionsService out of the Mef composition, because Razor has its own + // composition so can't import it (and its internal anyway) + var globalOptions = document.Project.Solution.Services.ExportProvider.GetExports().First().Value; - return FoldingRangesHandler.GetFoldingRangesAsync(globalOptions, document, cancellationToken); - } + return FoldingRangesHandler.GetFoldingRangesAsync(globalOptions, document, cancellationToken); } }