File: LspServices\LspServiceMetadataView.cs
Web Access
Project: src\src\LanguageServer\Protocol\Microsoft.CodeAnalysis.LanguageServer.Protocol.csproj (Microsoft.CodeAnalysis.LanguageServer.Protocol)
// 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.Collections.Frozen;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis.PooledObjects;
using Microsoft.CommonLanguageServerProtocol.Framework;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis.LanguageServer;
 
internal sealed class LspServiceMetadataView
{
    public TypeRef TypeRef { get; }
    public FrozenSet<string> InterfaceNames { get; }
    public WellKnownLspServerKinds ServerKind { get; }
    public bool IsStateless { get; }
 
    public bool IsMethodHandler => HandlerDetails is not null;
 
    /// <summary>
    /// Returns an array of request handler method details if this services is an <see cref="IMethodHandler"/>.
    /// </summary>
    public ImmutableArray<MethodHandlerDetails>? HandlerDetails { get; }
 
    public LspServiceMetadataView(IDictionary<string, object> metadata)
    {
        var typeName = (string)metadata[nameof(AbstractExportLspServiceAttribute.TypeName)];
        var assemblyName = (string)metadata[nameof(AbstractExportLspServiceAttribute.AssemblyName)];
        var codeBase = (string?)metadata[nameof(AbstractExportLspServiceAttribute.CodeBase)];
        TypeRef = TypeRef.From(typeName, assemblyName, codeBase);
 
        var interfaceNames = (string[])metadata[nameof(AbstractExportLspServiceAttribute.InterfaceNames)];
        InterfaceNames = FrozenSet.ToFrozenSet(interfaceNames);
 
        ServerKind = (WellKnownLspServerKinds)metadata[nameof(AbstractExportLspServiceAttribute.ServerKind)];
        IsStateless = (bool)metadata[nameof(AbstractExportLspServiceAttribute.IsStateless)];
 
        var methodHandlerData = (string[]?)metadata[nameof(AbstractExportLspServiceAttribute.MethodHandlerData)];
 
        if (methodHandlerData is not null)
        {
            using var _ = ArrayBuilder<MethodHandlerDetails>.GetInstance(out var handlerDetails);
 
            var index = 0;
            while (index < methodHandlerData.Length)
            {
                var methodName = methodHandlerData[index++];
                var language = methodHandlerData[index++];
                var requestTypeRef = ReadTypeRef(methodHandlerData, ref index);
                var responseTypeRef = ReadTypeRef(methodHandlerData, ref index);
                var requestContextTypeRef = ReadTypeRef(methodHandlerData, ref index);
                Contract.ThrowIfNull(requestContextTypeRef);
 
                handlerDetails.Add(new(
                    methodName,
                    language,
                    requestTypeRef,
                    responseTypeRef,
                    requestContextTypeRef));
            }
 
            HandlerDetails = handlerDetails.ToImmutableAndClear();
        }
        else
        {
            HandlerDetails = null;
        }
 
        static TypeRef? ReadTypeRef(string?[] methodHandlerData, ref int index)
        {
            var typeName = methodHandlerData[index++];
 
            if (typeName is null)
            {
                return null;
            }
 
            var assemblyName = methodHandlerData[index++];
            Contract.ThrowIfNull(assemblyName);
 
            var codeBase = methodHandlerData[index++];
 
            return TypeRef.From(typeName, assemblyName, codeBase);
        }
    }
}