File: LanguageServer\LanguageServerHost.cs
Web Access
Project: src\src\LanguageServer\Microsoft.CodeAnalysis.LanguageServer\Microsoft.CodeAnalysis.LanguageServer.csproj (Microsoft.CodeAnalysis.LanguageServer)
// 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 Microsoft.CodeAnalysis.LanguageServer.Handler;
using Microsoft.CodeAnalysis.LanguageServer.Logging;
using Microsoft.CommonLanguageServerProtocol.Framework;
using Microsoft.Extensions.Logging;
using Microsoft.VisualStudio.Composition;
using Roslyn.LanguageServer.Protocol;
using StreamJsonRpc;
 
namespace Microsoft.CodeAnalysis.LanguageServer.LanguageServer;
 
#pragma warning disable CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown
internal sealed class LanguageServerHost
#pragma warning restore CA1001 // The JsonRpc instance is disposed of by the AbstractLanguageServer during shutdown
{
    // TODO: replace this with a MEF part instead
    /// <summary>
    /// A static reference to the server instance.
    /// Used by components to send notifications and requests back to the client.
    /// </summary>
    internal static LanguageServerHost? Instance { get; private set; }
 
    private readonly ILogger _logger;
    private readonly AbstractLanguageServer<RequestContext> _roslynLanguageServer;
    private readonly JsonRpc _jsonRpc;
 
    public LanguageServerHost(Stream inputStream, Stream outputStream, ExportProvider exportProvider, ILogger logger, AbstractTypeRefResolver typeRefResolver)
    {
        var messageFormatter = RoslynLanguageServer.CreateJsonMessageFormatter();
 
        var handler = new HeaderDelimitedMessageHandler(outputStream, inputStream, messageFormatter);
 
        // If there is a jsonrpc disconnect or server shutdown, that is handled by the AbstractLanguageServer.  No need to do anything here.
        _jsonRpc = new JsonRpc(handler)
        {
            ExceptionStrategy = ExceptionProcessing.CommonErrorData,
        };
 
        var roslynLspFactory = exportProvider.GetExportedValue<ILanguageServerFactory>();
        var capabilitiesProvider = new ServerCapabilitiesProvider(exportProvider.GetExportedValue<ExperimentalCapabilitiesProvider>());
 
        _logger = logger;
        var lspLogger = new LspServiceLogger(_logger);
 
        var hostServices = exportProvider.GetExportedValue<HostServicesProvider>().HostServices;
        _roslynLanguageServer = roslynLspFactory.Create(
            _jsonRpc,
            messageFormatter.JsonSerializerOptions,
            capabilitiesProvider,
            WellKnownLspServerKinds.CSharpVisualBasicLspServer,
            lspLogger,
            hostServices,
            typeRefResolver);
    }
 
    public void Start()
    {
        _jsonRpc.StartListening();
 
        // Now that the server is started, update the our instance reference
        Instance = this;
    }
 
    public async Task WaitForExitAsync()
    {
        await _jsonRpc.Completion;
        await _roslynLanguageServer.WaitForExitAsync();
    }
 
    public T GetRequiredLspService<T>() where T : ILspService
    {
        return _roslynLanguageServer.GetLspServices().GetRequiredService<T>();
    }
}