/// <summary> /// Starts the language service with the specified config. /// </summary> /// <param name="config">The config that contains information on the communication protocol that will be used.</param> /// <param name="profilePaths">The profiles that will be loaded in the session.</param> public void StartLanguageService( EditorServiceTransportConfig config, ProfilePaths profilePaths) { _logger.LogInformation($"LSP NamedPipe: {config.InOutPipeName}\nLSP OutPipe: {config.OutPipeName}"); switch (config.TransportType) { case EditorServiceTransportType.NamedPipe: _languageServer = new NamedPipePsesLanguageServer( _factory, LogLevel.Trace, _enableConsoleRepl, _useLegacyReadLine, _featureFlags, _hostDetails, _additionalModules, _internalHost, profilePaths, config.InOutPipeName ?? config.InPipeName, config.OutPipeName); break; case EditorServiceTransportType.Stdio: _languageServer = new StdioPsesLanguageServer( _factory, LogLevel.Trace, _featureFlags, _hostDetails, _additionalModules, _internalHost, profilePaths); break; } _logger.LogInformation("Starting language server"); Task.Run(_languageServer.StartAsync); _logger.LogInformation( string.Format( "Language service started, type = {0}, endpoint = {1}", config.TransportType, config.Endpoint)); }
/// <summary> /// Starts the debug service with the specified config. /// </summary> /// <param name="config">The config that contains information on the communication protocol that will be used.</param> /// <param name="profilePaths">The profiles that will be loaded in the session.</param> /// <param name="useTempSession">Determines if we will make a new session typically used for temporary console debugging.</param> public void StartDebugService( EditorServiceTransportConfig config, ProfilePaths profilePaths, bool useTempSession) { _logger.LogInformation($"Debug NamedPipe: {config.InOutPipeName}\nDebug OutPipe: {config.OutPipeName}"); IServiceProvider serviceProvider = null; if (useTempSession) { serviceProvider = new ServiceCollection() .AddLogging(builder => builder .ClearProviders() .AddSerilog() .SetMinimumLevel(LogLevel.Trace)) .AddSingleton <ILanguageServer>(provider => null) .AddPsesLanguageServices( profilePaths, _featureFlags, _enableConsoleRepl, _useLegacyReadLine, _internalHost, _hostDetails, _additionalModules) .BuildServiceProvider(); } switch (config.TransportType) { case EditorServiceTransportType.NamedPipe: NamedPipeServerStream inNamedPipe = CreateNamedPipe( config.InOutPipeName ?? config.InPipeName, config.OutPipeName, out NamedPipeServerStream outNamedPipe); _debugServer = new PsesDebugServer( _factory, inNamedPipe, outNamedPipe ?? inNamedPipe); Task[] tasks = outNamedPipe != null ? new[] { inNamedPipe.WaitForConnectionAsync(), outNamedPipe.WaitForConnectionAsync() } : new[] { inNamedPipe.WaitForConnectionAsync() }; Task.WhenAll(tasks) .ContinueWith(async task => { _logger.LogInformation("Starting debug server"); await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useTempSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); break; case EditorServiceTransportType.Stdio: _debugServer = new PsesDebugServer( _factory, Console.OpenStandardInput(), Console.OpenStandardOutput()); _logger.LogInformation("Starting debug server"); Task.Run(async() => { await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useTempSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); break; default: throw new NotSupportedException($"The transport {config.TransportType} is not supported"); } // If the instance of PSES is being used for debugging only, then we don't want to allow automatic restarting // because the user can simply spin up a new PSES if they need to. // This design decision was done since this "debug-only PSES" is used in the "Temporary Integrated Console debugging" // feature which does not want PSES to be restarted so that the user can see the output of the last debug // session. if (!alreadySubscribedDebug && !useTempSession) { alreadySubscribedDebug = true; _debugServer.SessionEnded += (sender, eventArgs) => { _debugServer.Dispose(); alreadySubscribedDebug = false; StartDebugService(config, profilePaths, useTempSession); }; } }