File: DefaultLSPRequestInvoker.cs
Web Access
Project: src\src\Razor\src\Razor\src\Microsoft.VisualStudio.LanguageServer.ContainedLanguage\Microsoft.VisualStudio.LanguageServer.ContainedLanguage.csproj (Microsoft.VisualStudio.LanguageServer.ContainedLanguage)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Composition;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Razor.PooledObjects;
using Microsoft.VisualStudio.LanguageServer.Client;
using Microsoft.VisualStudio.Text;
using Newtonsoft.Json.Linq;
 
namespace Microsoft.VisualStudio.LanguageServer.ContainedLanguage;
 
[Shared]
[Export(typeof(LSPRequestInvoker))]
internal class DefaultLSPRequestInvoker : LSPRequestInvoker
{
    private readonly ILanguageServiceBroker2 _languageServiceBroker;
 
    [ImportingConstructor]
    public DefaultLSPRequestInvoker(ILanguageServiceBroker2 languageServiceBroker)
    {
        if (languageServiceBroker is null)
        {
            throw new ArgumentNullException(nameof(languageServiceBroker));
        }
 
        _languageServiceBroker = languageServiceBroker;
    }
 
    [Obsolete]
    public override Task<IEnumerable<ReinvokeResponse<TOut>>> ReinvokeRequestOnMultipleServersAsync<TIn, TOut>(string method, string contentType, TIn parameters, CancellationToken cancellationToken)
    {
        return RequestMultipleServerCoreAsync<TIn, TOut>(method, parameters, cancellationToken);
    }
 
    [Obsolete]
    public override Task<IEnumerable<ReinvokeResponse<TOut>>> ReinvokeRequestOnMultipleServersAsync<TIn, TOut>(string method, string contentType, Func<JToken, bool> capabilitiesFilter, TIn parameters, CancellationToken cancellationToken)
    {
        return RequestMultipleServerCoreAsync<TIn, TOut>(method, parameters, cancellationToken);
    }
 
    public override async Task<ReinvokeResponse<TOut>> ReinvokeRequestOnServerAsync<TIn, TOut>(
        string method,
        string languageServerName,
        TIn parameters,
        CancellationToken cancellationToken)
    {
        if (string.IsNullOrEmpty(method))
        {
            throw new ArgumentException("message", nameof(method));
        }
 
        var response = await _languageServiceBroker.RequestAsync(
            new GeneralRequest<TIn, TOut> { LanguageServerName = languageServerName, Method = method, Request = parameters },
            cancellationToken);
 
        // No callers actually use the languageClient when handling the response.
        var result = response is not null ? new ReinvokeResponse<TOut>(languageClient: null!, response) : default;
        return result;
    }
 
    [Obsolete]
    public override Task<ReinvokeResponse<TOut>> ReinvokeRequestOnServerAsync<TIn, TOut>(
        string method,
        string languageServerName,
        Func<JToken, bool> capabilitiesFilter,
        TIn parameters,
        CancellationToken cancellationToken)
    {
        return ReinvokeRequestOnServerAsync<TIn, TOut>(method, languageServerName, parameters, cancellationToken);
    }
 
    public override async Task<ReinvocationResponse<TOut>?> ReinvokeRequestOnServerAsync<TIn, TOut>(ITextBuffer textBuffer, string method, string languageServerName, TIn parameters, CancellationToken cancellationToken)
    {
        var response = await _languageServiceBroker.RequestAsync(
            new DocumentRequest<TIn, TOut>()
            {
                TextBuffer = textBuffer,
                LanguageServerName = languageServerName,
                ParameterFactory = _ => parameters,
                Method = method,
            },
            cancellationToken);
 
        if (response is null)
        {
            return null;
        }
 
        var reinvocationResponse = new ReinvocationResponse<TOut>(languageServerName, response);
        return reinvocationResponse;
    }
 
    [Obsolete]
    public override Task<ReinvocationResponse<TOut>?> ReinvokeRequestOnServerAsync<TIn, TOut>(
        ITextBuffer textBuffer,
        string method,
        string languageServerName,
        Func<JToken, bool> capabilitiesFilter,
        TIn parameters,
        CancellationToken cancellationToken)
    {
        return ReinvokeRequestOnServerAsync<TIn, TOut>(textBuffer, method, languageServerName, parameters, cancellationToken);
    }
 
    private async Task<IEnumerable<ReinvokeResponse<TOut>>> RequestMultipleServerCoreAsync<TIn, TOut>(string method, TIn parameters, CancellationToken cancellationToken)
        where TIn : notnull
    {
        if (string.IsNullOrEmpty(method))
        {
            throw new ArgumentException("message", nameof(method));
        }
 
        var reinvokeResponses = _languageServiceBroker.RequestAllAsync(
            new GeneralRequest<TIn, TOut>() { LanguageServerName = null, Method = method, Request = parameters },
            cancellationToken).ConfigureAwait(false);
 
        using var responses = new PooledArrayBuilder<ReinvokeResponse<TOut>>();
        await foreach (var reinvokeResponse in reinvokeResponses)
        {
            // No callers actually use the languageClient when handling the response.
            responses.Add(new ReinvokeResponse<TOut>(languageClient: null!, reinvokeResponse.response!));
        }
 
        return responses.ToArray();
    }
 
    [Obsolete("New callers should use a method that doesn't have a capabilities filter")]
    public override IAsyncEnumerable<ReinvocationResponse<TOut>> ReinvokeRequestOnMultipleServersAsync<TIn, TOut>(
        ITextBuffer textBuffer,
        string method,
        Func<JToken, bool> capabilitiesFilter,
        TIn parameters,
        CancellationToken cancellationToken)
    {
        return ReinvokeRequestOnMultipleServersAsync<TIn, TOut>(textBuffer, method, parameters, cancellationToken);
    }
 
    public override async IAsyncEnumerable<ReinvocationResponse<TOut>> ReinvokeRequestOnMultipleServersAsync<TIn, TOut>(
        ITextBuffer textBuffer,
        string method,
        TIn parameters,
        [EnumeratorCancellation] CancellationToken cancellationToken)
    {
        var requests = _languageServiceBroker.RequestAllAsync(
            new DocumentRequest<TIn, TOut> { ParameterFactory = _ => parameters, Method = method, TextBuffer = textBuffer },
            cancellationToken);
 
        await foreach (var response in requests)
        {
            yield return new ReinvocationResponse<TOut>(response.client, response.response);
        }
    }
}