File: MessageInterception\GenericInterceptionMiddleLayer.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.Threading;
using System.Threading.Tasks;
using Microsoft.VisualStudio.LanguageServer.Client;
 
namespace Microsoft.VisualStudio.LanguageServer.ContainedLanguage.MessageInterception;
 
/// <summary>
/// Receives notification messages from the server and invokes any applicable message interception layers.
/// </summary>
public class GenericInterceptionMiddleLayer<TJsonToken> : ILanguageClientMiddleLayer2<TJsonToken>
{
    private readonly InterceptorManager _interceptorManager;
    private readonly string _contentType;
 
    /// <summary>
    /// Create the middle layer
    /// </summary>
    /// <param name="interceptorManager">Interception manager</param>
    /// <param name="contentType">The content type name of the language for the ILanguageClient using this middle layer</param>
    public GenericInterceptionMiddleLayer(InterceptorManager interceptorManager, string contentType)
    {
        _interceptorManager = interceptorManager ?? throw new ArgumentNullException(nameof(interceptorManager));
        _contentType = !string.IsNullOrEmpty(contentType) ? contentType : throw new ArgumentException("Cannot be empty", nameof(contentType));
    }
 
    public bool CanHandle(string methodName)
    {
        return _interceptorManager.HasInterceptor(methodName, _contentType);
    }
 
    public async Task HandleNotificationAsync(string methodName, TJsonToken methodParam, Func<TJsonToken, Task> sendNotification)
    {
        var payload = methodParam;
        if (CanHandle(methodName))
        {
            payload = await _interceptorManager.ProcessGenericInterceptorsAsync(methodName, methodParam, _contentType, CancellationToken.None);
        }
 
        if (payload is not null &&
            !EqualityComparer<TJsonToken>.Default.Equals(payload, default!))
        {
            // this completes the handshake to give the payload back to the client.
            await sendNotification(payload);
        }
    }
 
    public async Task<TJsonToken?> HandleRequestAsync(string methodName, TJsonToken methodParam, Func<TJsonToken, Task<TJsonToken?>> sendRequest)
    {
        // First send the request through.
        // We don't yet have a scenario where the request needs to be intercepted, but if one does come up, we may need to redesign the interception handshake
        // to handle both request and response interception.
        var response = await sendRequest(methodParam);
 
        if (response is not null &&
            !EqualityComparer<TJsonToken>.Default.Equals(response, default!) &&
            CanHandle(methodName))
        {
            response = await _interceptorManager.ProcessGenericInterceptorsAsync(methodName, response, _contentType, CancellationToken.None);
        }
 
        return response;
    }
}