Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cohost: Support signature help #10595

Merged
merged 21 commits into from
Jul 19, 2024
Merged
Show file tree
Hide file tree
Changes from 7 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions eng/targets/Services.props
Original file line number Diff line number Diff line change
Expand Up @@ -22,5 +22,6 @@
<ServiceHubService Include="Microsoft.VisualStudio.Razor.ClientInitialization" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteClientInitializationServiceFactory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.UriPresentation" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteUriPresentationServiceFactory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.FoldingRange" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteFoldingRangeServiceFactory" />
<ServiceHubService Include="Microsoft.VisualStudio.Razor.SignatureHelp" ClassName="Microsoft.CodeAnalysis.Remote.Razor.RemoteSignatureHelpServiceFactory" />
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ public static SemanticTokensOptions EnableSemanticTokens(this SemanticTokensOpti
return options;
}

public static void EnableSignatureHelp(this VSInternalServerCapabilities serverCapabilities)
{
serverCapabilities.SignatureHelpProvider = new SignatureHelpOptions().EnableSignatureHelp();
}

public static SignatureHelpOptions EnableSignatureHelp(this SignatureHelpOptions options)
{
options.TriggerCharacters = ["(", ",", "<"];
options.RetriggerCharacters = [">", ")"];
alexgav marked this conversation as resolved.
Show resolved Hide resolved

return options;
}

public static void EnableHoverProvider(this VSInternalServerCapabilities serverCapabilities)
{
serverCapabilities.HoverProvider = new HoverOptions()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -178,7 +178,6 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption
services.AddTransient<IOnInitialized>(sp => sp.GetRequiredService<RazorConfigurationEndpoint>());

services.AddHandlerWithCapabilities<ImplementationEndpoint>();
services.AddHandlerWithCapabilities<SignatureHelpEndpoint>();
services.AddHandlerWithCapabilities<DocumentHighlightEndpoint>();
services.AddHandlerWithCapabilities<OnAutoInsertEndpoint>();

Expand All @@ -187,6 +186,7 @@ static void AddHandlers(IServiceCollection services, LanguageServerFeatureOption

if (!featureOptions.UseRazorCohostServer)
{
services.AddHandlerWithCapabilities<SignatureHelpEndpoint>();
services.AddHandlerWithCapabilities<LinkedEditingRangeEndpoint>();
services.AddHandlerWithCapabilities<FoldingRangeEndpoint>();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
using Microsoft.CodeAnalysis.Razor.Protocol;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using LS = Microsoft.VisualStudio.LanguageServer.Protocol;
using LSP = Microsoft.VisualStudio.LanguageServer.Protocol;
davidwengier marked this conversation as resolved.
Show resolved Hide resolved

namespace Microsoft.AspNetCore.Razor.LanguageServer.SignatureHelp;

Expand All @@ -22,7 +22,7 @@ internal sealed class SignatureHelpEndpoint(
IClientConnection clientConnection,
RazorLSPOptionsMonitor optionsMonitor,
ILoggerFactory loggerProvider)
: AbstractRazorDelegatingEndpoint<SignatureHelpParams, LS.SignatureHelp?>(
: AbstractRazorDelegatingEndpoint<SignatureHelpParams, LSP.SignatureHelp?>(
languageServerFeatureOptions,
documentMappingService,
clientConnection,
Expand All @@ -33,11 +33,7 @@ internal sealed class SignatureHelpEndpoint(

public void ApplyCapabilities(VSInternalServerCapabilities serverCapabilities, VSInternalClientCapabilities clientCapabilities)
{
serverCapabilities.SignatureHelpProvider = new SignatureHelpOptions()
{
TriggerCharacters = new[] { "(", ",", "<" },
RetriggerCharacters = new[] { ">", ")" }
};
serverCapabilities.EnableSignatureHelp();
}

protected override Task<IDelegatedParams?> CreateDelegatedParamsAsync(SignatureHelpParams request, RazorRequestContext requestContext, DocumentPositionInfo positionInfo, CancellationToken cancellationToken)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

namespace Microsoft.CodeAnalysis.Razor.Remote;

/// <summary>
/// Marker interface to indicate that an OOP service should use Json for communication
/// </summary>
internal interface IRemoteJsonService
{
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Roslyn.LanguageServer.Protocol;

namespace Microsoft.CodeAnalysis.Razor.Remote;

using SignatureHelp = Roslyn.LanguageServer.Protocol.SignatureHelp;

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

Check failure on line 11 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L11

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(11,54): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'SignatureHelp' is inaccessible due to its protection level

internal interface IRemoteSignatureHelpService : IRemoteJsonService
{
ValueTask<SignatureHelp?> GetSignatureHelpAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId documentId, Position linePosition, CancellationToken cancellationToken);

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,53): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableRazorPinnedSolutionInfoWrapper' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,114): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableDocumentId' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,153): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'Position' is inaccessible due to its protection level

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,53): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableRazorPinnedSolutionInfoWrapper' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,114): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableDocumentId' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build macOS debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,153): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'Position' is inaccessible due to its protection level

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,53): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableRazorPinnedSolutionInfoWrapper' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,114): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableDocumentId' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux debug)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,153): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'Position' is inaccessible due to its protection level

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,53): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableRazorPinnedSolutionInfoWrapper' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,114): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableDocumentId' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci (Build Linux release)

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,153): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'Position' is inaccessible due to its protection level

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,53): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableRazorPinnedSolutionInfoWrapper' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,114): error CS0246: (NETCORE_ENGINEERING_TELEMETRY=Build) The type or namespace name 'JsonSerializableDocumentId' could not be found (are you missing a using directive or an assembly reference?)

Check failure on line 15 in src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs

View check run for this annotation

Azure Pipelines / razor-tooling-ci

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs#L15

src/Razor/src/Microsoft.CodeAnalysis.Razor.Workspaces/Remote/IRemoteSignatureHelpService.cs(15,153): error CS0122: (NETCORE_ENGINEERING_TELEMETRY=Build) 'Position' is inaccessible due to its protection level
}
Original file line number Diff line number Diff line change
@@ -1,8 +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.Collections.Immutable;
using MessagePack.Formatters;
using Microsoft.AspNetCore.Razor.Serialization.MessagePack.Resolvers;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;

Expand All @@ -15,7 +13,7 @@ internal static class RazorServices
public static readonly RazorServiceDescriptorsWrapper Descriptors = new(
ComponentName,
featureDisplayNameProvider: feature => $"Razor {feature} Feature",
additionalFormatters: ImmutableArray<IMessagePackFormatter>.Empty,
additionalFormatters: [],
additionalResolvers: TopLevelResolvers.All,
interfaces:
[
Expand All @@ -27,4 +25,13 @@ internal static class RazorServices
(typeof(IRemoteUriPresentationService), null),
(typeof(IRemoteFoldingRangeService), null)
]);

public static readonly RazorServiceDescriptorsWrapper JsonDescriptors = new(
ComponentName, // Needs to match the above because so much of our ServiceHub infrastructure is convention based
featureDisplayNameProvider: feature => $"Razor {feature} Feature",
jsonConverters: RazorServiceDescriptorsWrapper.GetLspConverters(),
interfaces:
[
(typeof(IRemoteSignatureHelpService), null),
]);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.Language;
using Microsoft.CodeAnalysis.ExternalAccess.Razor;
using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.CodeAnalysis.Text;
using Microsoft.ServiceHub.Framework;
using Roslyn.LanguageServer.Protocol;

namespace Microsoft.CodeAnalysis.Remote.Razor;

using SignatureHelp = Roslyn.LanguageServer.Protocol.SignatureHelp;

internal sealed class RemoteSignatureHelpService(
IServiceBroker serviceBroker,
DocumentSnapshotFactory documentSnapshotFactory,
IFilePathService filePathService,
IRazorDocumentMappingService documentMappingService)
: RazorDocumentServiceBase(serviceBroker, documentSnapshotFactory), IRemoteSignatureHelpService
{
private readonly IFilePathService _filePathService = filePathService;
private readonly IRazorDocumentMappingService _documentMappingService = documentMappingService;

public ValueTask<SignatureHelp?> GetSignatureHelpAsync(JsonSerializableRazorPinnedSolutionInfoWrapper solutionInfo, JsonSerializableDocumentId documentId, Position position, CancellationToken cancellationToken)
=> RunServiceAsync(
solutionInfo,
documentId,
context => GetSignatureHelpsAsync(context, position, cancellationToken),
cancellationToken);

private async ValueTask<SignatureHelp?> GetSignatureHelpsAsync(RemoteDocumentContext context, Position position, CancellationToken cancellationToken)
{
var codeDocument = await context.GetCodeDocumentAsync(cancellationToken).ConfigureAwait(false);
var linePosition = new LinePosition(position.Line, position.Character);
var absoluteIndex = linePosition.GetRequiredAbsoluteIndex(codeDocument.Source.Text, logger: null);

var generatedDocument = await context.GetGeneratedDocumentAsync(_filePathService, cancellationToken).ConfigureAwait(false);

if (_documentMappingService.TryMapToGeneratedDocumentPosition(codeDocument.GetCSharpDocument(), absoluteIndex, out var mappedPosition, out _))
{
return await ExternalAccess.Razor.Cohost.Handlers.SignatureHelp.GetSignatureHelpAsync(generatedDocument, mappedPosition, supportsVisualStudioExtensions: true, cancellationToken).ConfigureAwait(false);
davidwengier marked this conversation as resolved.
Show resolved Hide resolved
}

return null;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis.Razor.DocumentMapping;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.CodeAnalysis.Razor.Workspaces;
using Microsoft.CodeAnalysis.Remote.Razor.ProjectSystem;
using Microsoft.ServiceHub.Framework;
using Microsoft.VisualStudio.Composition;

namespace Microsoft.CodeAnalysis.Remote.Razor;

internal sealed class RemoteSignatureHelpServiceFactory : RazorServiceFactoryBase<IRemoteSignatureHelpService>
{
// WARNING: We must always have a parameterless constructor in order to be properly handled by ServiceHub.
public RemoteSignatureHelpServiceFactory()
: base(RazorServices.JsonDescriptors)
{
}

protected override IRemoteSignatureHelpService CreateService(IServiceBroker serviceBroker, ExportProvider exportProvider)
{
var documentSnapshotFactory = exportProvider.GetExportedValue<DocumentSnapshotFactory>();
var filePathService = exportProvider.GetExportedValue<IFilePathService>();
var documentMappingService = exportProvider.GetExportedValue<IRazorDocumentMappingService>();
return new RemoteSignatureHelpService(serviceBroker, documentSnapshotFactory, filePathService, documentMappingService);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT license. See License.txt in the project root for license information.

using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor;
using Microsoft.AspNetCore.Razor.LanguageServer.Hosting;
using Microsoft.CodeAnalysis.ExternalAccess.Razor.Cohost;
using Microsoft.CodeAnalysis.Razor.Logging;
using Microsoft.CodeAnalysis.Razor.Remote;
using Microsoft.VisualStudio.LanguageServer.ContainedLanguage;
using Microsoft.VisualStudio.LanguageServer.Protocol;
using Microsoft.VisualStudio.Razor.LanguageClient;
using Microsoft.VisualStudio.Razor.LanguageClient.Cohost;
using Microsoft.VisualStudio.Razor.LanguageClient.Extensions;
using Microsoft.VisualStudio.Razor.Settings;
using RLSP = Roslyn.LanguageServer.Protocol;

namespace Microsoft.VisualStudio.LanguageServices.Razor.LanguageClient.Cohost;

#pragma warning disable RS0030 // Do not use banned APIs
[Shared]
[CohostEndpoint(Methods.TextDocumentSignatureHelpName)]
[Export(typeof(IDynamicRegistrationProvider))]
[ExportCohostStatelessLspService(typeof(CohostSignatureHelpEndpoint))]
[method: ImportingConstructor]
#pragma warning restore RS0030 // Do not use banned APIs
internal class CohostSignatureHelpEndpoint(
IRemoteServiceProvider remoteServiceProvider,
IClientSettingsManager clientSettingsManager,
IHtmlDocumentSynchronizer htmlDocumentSynchronizer,
LSPRequestInvoker requestInvoker,
ILoggerFactory loggerFactory)
: AbstractRazorCohostDocumentRequestHandler<SignatureHelpParams, SumType<SignatureHelp, RLSP.SignatureHelp>?>, IDynamicRegistrationProvider
{
private readonly IRemoteServiceProvider _remoteServiceProvider = remoteServiceProvider;
private readonly IClientSettingsManager _clientSettingsManager = clientSettingsManager;
private readonly IHtmlDocumentSynchronizer _htmlDocumentSynchronizer = htmlDocumentSynchronizer;
private readonly LSPRequestInvoker _requestInvoker = requestInvoker;
private readonly ILogger _logger = loggerFactory.GetOrCreateLogger<CohostFoldingRangeEndpoint>();

protected override bool MutatesSolutionState => false;

protected override bool RequiresLSPSolution => true;

public Registration? GetRegistration(VSInternalClientCapabilities clientCapabilities, DocumentFilter[] filter, RazorCohostRequestContext requestContext)
{
if (clientCapabilities.TextDocument?.SignatureHelp?.DynamicRegistration == true)
{
return new Registration()
{
Method = Methods.TextDocumentSignatureHelpName,
RegisterOptions = new SignatureHelpRegistrationOptions()
{
DocumentSelector = filter
}.EnableSignatureHelp()
};
}

return null;
}

protected override RazorTextDocumentIdentifier? GetRazorTextDocumentIdentifier(SignatureHelpParams request)
=> new RazorTextDocumentIdentifier(request.TextDocument.Uri, (request.TextDocument as VSTextDocumentIdentifier)?.ProjectContext?.Id);

// NOTE: The use of SumType here is a little odd, but it allows us to return Roslyn LSP types from the Roslyn call, and VS LSP types from the Html
// call. It works because both sets of types are attributed the right way, so the Json ends up looking the same and the client doesn't
// care. Ideally eventually we will be able to move all of this to just Roslyn LSP types, but we might have to wait for Web Tools
protected async override Task<SumType<SignatureHelp, RLSP.SignatureHelp>?> HandleRequestAsync(SignatureHelpParams request, RazorCohostRequestContext context, CancellationToken cancellationToken)
{
// Return nothing if "Parameter Information" option is disabled unless signature help is invoked explicitly via command as opposed to typing or content change
if (request.Context is { TriggerKind: not SignatureHelpTriggerKind.Invoked } &&
!_clientSettingsManager.GetClientSettings().ClientCompletionSettings.AutoListParams)
{
return null;
}

var razorDocument = context.TextDocument.AssumeNotNull();

var data = await _remoteServiceProvider.TryInvokeAsync<IRemoteSignatureHelpService, RLSP.SignatureHelp?>(
razorDocument.Project.Solution,
(service, solutionInfo, cancellationToken) => service.GetSignatureHelpAsync(solutionInfo, razorDocument.Id, new RLSP.Position(request.Position.Line, request.Position.Character), cancellationToken),
cancellationToken).ConfigureAwait(false);
davidwengier marked this conversation as resolved.
Show resolved Hide resolved

// If we got a response back, then either Razor or C# wants to do something with this, so we're good to go
if (data is { } signatureHelp)
{
return signatureHelp;
}

// If we didn't get anything from Razor or Roslyn, lets ask Html what they want to do
var htmlDocument = await _htmlDocumentSynchronizer.TryGetSynchronizedHtmlDocumentAsync(razorDocument, cancellationToken).ConfigureAwait(false);
if (htmlDocument is null)
{
return null;
}

request.TextDocument = request.TextDocument.WithUri(htmlDocument.Uri);

var result = await _requestInvoker.ReinvokeRequestOnServerAsync<SignatureHelpParams, SignatureHelp?>(
htmlDocument.Buffer,
Methods.TextDocumentSignatureHelpName,
RazorLSPConstants.HtmlLanguageServerName,
request,
cancellationToken).ConfigureAwait(false);

return result?.Response;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,9 @@ internal sealed class RemoteServiceProvider(
[CallerMemberName] string? callerMemberName = null)
where TService : class
{
var client = await TryGetClientAsync(cancellationToken).ConfigureAwait(false);
var client = typeof(IRemoteJsonService).IsAssignableFrom(typeof(TService))
? await TryGetJsonClientAsync(cancellationToken).ConfigureAwait(false)
: await TryGetClientAsync(cancellationToken).ConfigureAwait(false);
if (client is null)
{
_logger.LogError($"Couldn't get remote client for {typeof(TService).Name} service");
Expand Down Expand Up @@ -97,6 +99,24 @@ internal sealed class RemoteServiceProvider(
return remoteClient;
}

private async Task<RazorRemoteHostClient?> TryGetJsonClientAsync(CancellationToken cancellationToken)
{
// Even if we're getting a service that wants to use Json, we still have to initialize the OOP client
// so we get the regular (MessagePack) client too.
if (!_fullyInitialized)
{
_ = await TryGetClientAsync(cancellationToken).ConfigureAwait(false);
}

var workspace = _workspaceProvider.GetWorkspace();

return await RazorRemoteHostClient.TryGetClientAsync(
workspace.Services,
RazorServices.JsonDescriptors,
RazorRemoteServiceCallbackDispatcherRegistry.Empty,
cancellationToken).ConfigureAwait(false);
}

private async Task InitializeRemoteClientAsync(RazorRemoteHostClient remoteClient, CancellationToken cancellationToken)
{
if (_fullyInitialized)
Expand Down
Loading