From 021a14799c2d29943b68547ecb484095cbd2d457 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Tue, 8 Oct 2019 15:49:13 -0700 Subject: [PATCH 1/6] refactor out servicecollection additions --- .../Hosting/EditorServicesHost.cs | 8 +- .../Server/PsesDebugServer.cs | 8 +- .../Server/PsesLanguageServer.cs | 44 ++-------- .../Server/PsesServiceCollection.cs | 81 +++++++++++++++++++ 4 files changed, 92 insertions(+), 49 deletions(-) create mode 100644 src/PowerShellEditorServices/Server/PsesServiceCollection.cs diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs index fd14dd787..ba0901fc1 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs @@ -331,16 +331,14 @@ public void StartDebugService( IServiceProvider serviceProvider = useExistingSession ? _languageServer.LanguageServer.Services - : new ServiceCollection().AddSingleton( - (provider) => PowerShellContextService.Create( - _factory, - provider.GetService(), + : new ServiceCollection() + .AddPsesLanguageServices( profilePaths, _featureFlags, _enableConsoleRepl, _internalHost, _hostDetails, - _additionalModules)) + _additionalModules) .BuildServiceProvider(); await _debugServer.StartAsync(serviceProvider); diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 860dbc845..c992ff78e 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -51,13 +51,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider) _powerShellContextService.IsDebugServerActive = true; options.Services = new ServiceCollection() - .AddSingleton(_powerShellContextService) - .AddSingleton(languageServerServiceProvider.GetService()) - .AddSingleton(languageServerServiceProvider.GetService()) - .AddSingleton(this) - .AddSingleton() - .AddSingleton() - .AddSingleton(); + .AddPsesDebugServices(languageServerServiceProvider, this); options .WithInput(_inputStream) diff --git a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs index 3d6901479..caddc5e5f 100644 --- a/src/PowerShellEditorServices/Server/PsesLanguageServer.cs +++ b/src/PowerShellEditorServices/Server/PsesLanguageServer.cs @@ -65,43 +65,13 @@ public async Task StartAsync() .WithInput(input) .WithOutput(output) .WithServices(serviceCollection => serviceCollection - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton( - (provider) => - PowerShellContextService.Create( - provider.GetService(), - provider.GetService(), - _profilePaths, - _featureFlags, - _enableConsoleRepl, - _internalHost, - _hostDetails, - _additionalModules)) - .AddSingleton() - .AddSingleton() - .AddSingleton() - .AddSingleton( - (provider) => - { - var extensionService = new ExtensionService( - provider.GetService(), - provider.GetService()); - extensionService.InitializeAsync( - serviceProvider: provider, - editorOperations: provider.GetService()) - .Wait(); - return extensionService; - }) - .AddSingleton( - (provider) => - { - return AnalysisService.Create( - provider.GetService(), - provider.GetService(), - provider.GetService().CreateLogger()); - })) + .AddPsesLanguageServices( + _profilePaths, + _featureFlags, + _enableConsoleRepl, + _internalHost, + _hostDetails, + _additionalModules)) .ConfigureLogging(builder => builder .AddSerilog(Log.Logger) .SetMinimumLevel(LogLevel.Trace)) diff --git a/src/PowerShellEditorServices/Server/PsesServiceCollection.cs b/src/PowerShellEditorServices/Server/PsesServiceCollection.cs new file mode 100644 index 000000000..e444ac50a --- /dev/null +++ b/src/PowerShellEditorServices/Server/PsesServiceCollection.cs @@ -0,0 +1,81 @@ +// +// Copyright (c) Microsoft. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. +// + +using System; +using System.Collections.Generic; +using System.Management.Automation.Host; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Logging; +using Microsoft.PowerShell.EditorServices.Hosting; +using Microsoft.PowerShell.EditorServices.Services; + +namespace Microsoft.PowerShell.EditorServices.Server +{ + internal static class PsesServiceCollection + { + public static IServiceCollection AddPsesLanguageServices ( + this IServiceCollection collection, + ProfilePaths profilePaths, + HashSet featureFlags, + bool enableConsoleRepl, + PSHost internalHost, + HostDetails hostDetails, + string[] additionalModules) + { + return collection.AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton( + (provider) => + PowerShellContextService.Create( + provider.GetService(), + provider.GetService(), + profilePaths, + featureFlags, + enableConsoleRepl, + internalHost, + hostDetails, + additionalModules)) + .AddSingleton() + .AddSingleton() + .AddSingleton() + .AddSingleton( + (provider) => + { + var extensionService = new ExtensionService( + provider.GetService(), + provider.GetService()); + extensionService.InitializeAsync( + serviceProvider: provider, + editorOperations: provider.GetService()) + .Wait(); + return extensionService; + }) + .AddSingleton( + (provider) => + { + return AnalysisService.Create( + provider.GetService(), + provider.GetService(), + provider.GetService().CreateLogger()); + }); + } + + public static IServiceCollection AddPsesDebugServices ( + this IServiceCollection collection, + IServiceProvider languageServiceProvider, + PsesDebugServer psesDebugServer + ) + { + return collection.AddSingleton(languageServiceProvider.GetService()) + .AddSingleton(languageServiceProvider.GetService()) + .AddSingleton(languageServiceProvider.GetService()) + .AddSingleton(psesDebugServer) + .AddSingleton() + .AddSingleton() + .AddSingleton(); + } + } +} From e8c7ad9301bea7f01ef4cf602057aeeae8471f9d Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Fri, 11 Oct 2019 13:43:29 +0200 Subject: [PATCH 2/6] initial working TEMP debugging --- .../Hosting/EditorServicesHost.cs | 49 ++++++++++++------- .../Server/PsesDebugServer.cs | 13 ++++- .../Server/PsesServiceCollection.cs | 8 ++- .../Handlers/ConfigurationDoneHandler.cs | 24 +++++---- .../PowerShellContextService.cs | 4 +- 5 files changed, 64 insertions(+), 34 deletions(-) diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs index ba0901fc1..1a9660f6e 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs @@ -21,6 +21,7 @@ using Microsoft.PowerShell.EditorServices.Server; using Microsoft.PowerShell.EditorServices.Services; using Microsoft.PowerShell.EditorServices.Utility; +using OmniSharp.Extensions.LanguageServer.Protocol.Server; using Serilog; namespace Microsoft.PowerShell.EditorServices.Hosting @@ -292,6 +293,25 @@ public void StartDebugService( { _logger.LogInformation($"Debug NamedPipe: {config.InOutPipeName}\nDebug OutPipe: {config.OutPipeName}"); + IServiceProvider serviceProvider = null; + if (!useExistingSession) + { + serviceProvider = new ServiceCollection() + .AddLogging(builder => builder + .ClearProviders() + .AddSerilog() + .SetMinimumLevel(LogLevel.Trace)) + .AddSingleton(provider => null) + .AddPsesLanguageServices( + profilePaths, + _featureFlags, + _enableConsoleRepl, + _internalHost, + _hostDetails, + _additionalModules) + .BuildServiceProvider(); + } + switch (config.TransportType) { case EditorServiceTransportType.NamedPipe: @@ -312,7 +332,7 @@ public void StartDebugService( .ContinueWith(async task => { _logger.LogInformation("Starting debug server"); - await _debugServer.StartAsync(_languageServer.LanguageServer.Services); + await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useExistingSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); @@ -325,23 +345,11 @@ public void StartDebugService( Console.OpenStandardInput(), Console.OpenStandardOutput()); + _logger.LogInformation("Starting debug server"); Task.Run(async () => { - _logger.LogInformation("Starting debug server"); - - IServiceProvider serviceProvider = useExistingSession - ? _languageServer.LanguageServer.Services - : new ServiceCollection() - .AddPsesLanguageServices( - profilePaths, - _featureFlags, - _enableConsoleRepl, - _internalHost, - _hostDetails, - _additionalModules) - .BuildServiceProvider(); - - await _debugServer.StartAsync(serviceProvider); + + await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useExistingSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); @@ -351,7 +359,7 @@ public void StartDebugService( throw new NotSupportedException($"The transport {config.TransportType} is not supported"); } - if(!alreadySubscribedDebug) + if(!alreadySubscribedDebug && useExistingSession) { alreadySubscribedDebug = true; _debugServer.SessionEnded += (sender, eventArgs) => @@ -377,7 +385,12 @@ public void StopServices() public void WaitForCompletion() { // TODO: We need a way to know when to complete this task! - _languageServer.WaitForShutdown().Wait(); + if (_languageServer != null) + { + _languageServer.WaitForShutdown().Wait(); + return; + } + _debugServer.WaitForShutdown().Wait(); } #endregion diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index c992ff78e..bebb1f9a1 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -26,6 +26,8 @@ public class PsesDebugServer : IDisposable private PowerShellContextService _powerShellContextService; + private readonly TaskCompletionSource _serverStart; + public PsesDebugServer( ILoggerFactory factory, Stream inputStream, @@ -34,9 +36,10 @@ public PsesDebugServer( _loggerFactory = factory; _inputStream = inputStream; _outputStream = outputStream; + _serverStart = new TaskCompletionSource(); } - public async Task StartAsync(IServiceProvider languageServerServiceProvider) + public async Task StartAsync(IServiceProvider languageServerServiceProvider, bool useExistingSession) { _jsonRpcServer = await JsonRpcServer.From(options => { @@ -51,7 +54,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider) _powerShellContextService.IsDebugServerActive = true; options.Services = new ServiceCollection() - .AddPsesDebugServices(languageServerServiceProvider, this); + .AddPsesDebugServices(languageServerServiceProvider, this, useExistingSession); options .WithInput(_inputStream) @@ -89,6 +92,12 @@ public void Dispose() { _powerShellContextService.IsDebugServerActive = false; _jsonRpcServer.Dispose(); + _serverStart.SetResult(true); + } + + public async Task WaitForShutdown() + { + await _serverStart.Task; } #region Events diff --git a/src/PowerShellEditorServices/Server/PsesServiceCollection.cs b/src/PowerShellEditorServices/Server/PsesServiceCollection.cs index e444ac50a..8dc9a7467 100644 --- a/src/PowerShellEditorServices/Server/PsesServiceCollection.cs +++ b/src/PowerShellEditorServices/Server/PsesServiceCollection.cs @@ -66,7 +66,8 @@ public static IServiceCollection AddPsesLanguageServices ( public static IServiceCollection AddPsesDebugServices ( this IServiceCollection collection, IServiceProvider languageServiceProvider, - PsesDebugServer psesDebugServer + PsesDebugServer psesDebugServer, + bool useExistingSession ) { return collection.AddSingleton(languageServiceProvider.GetService()) @@ -74,7 +75,10 @@ PsesDebugServer psesDebugServer .AddSingleton(languageServiceProvider.GetService()) .AddSingleton(psesDebugServer) .AddSingleton() - .AddSingleton() + .AddSingleton(new DebugStateService + { + OwnsEditorSession = !useExistingSession + }) .AddSingleton(); } } diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs index addf829a1..379df5d1b 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs @@ -43,10 +43,22 @@ public ConfigurationDoneHandler( _workspaceService = workspaceService; } - public Task Handle(ConfigurationDoneArguments request, CancellationToken cancellationToken) + public async Task Handle(ConfigurationDoneArguments request, CancellationToken cancellationToken) { _debugService.IsClientAttached = true; + if (_debugStateService.OwnsEditorSession) + { + // If this is a debug-only session, we need to start + // the command loop manually + _powerShellContextService.ConsoleReader.StartCommandLoop(); + await Task.Delay(10000); + while (_powerShellContextService.SessionState != PowerShellContextState.Ready) + { + await Task.Delay(2000); + } + } + if (!string.IsNullOrEmpty(_debugStateService.ScriptToLaunch)) { if (_powerShellContextService.SessionState == PowerShellContextState.Ready) @@ -63,14 +75,6 @@ public Task Handle(ConfigurationDoneArguments request if (_debugStateService.IsInteractiveDebugSession) { - if (_debugStateService.OwnsEditorSession) - { - // If this is a debug-only session, we need to start - // the command loop manually - // TODO: Bring this back - //_editorSession.HostInput.StartCommandLoop(); - } - if (_debugService.IsDebuggerStopped) { if (_debugService.CurrentDebuggerStoppedEventArgs != null) @@ -88,7 +92,7 @@ public Task Handle(ConfigurationDoneArguments request } } - return Task.FromResult(new ConfigurationDoneResponse()); + return new ConfigurationDoneResponse(); } private async Task LaunchScriptAsync(string scriptToLaunch) diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index dfe550c18..a1f54a0de 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -1793,7 +1793,7 @@ private void OnExecutionStatusChanged( private void PowerShellContext_RunspaceChangedAsync(object sender, RunspaceChangedEventArgs e) { - _languageServer.SendNotification( + _languageServer?.SendNotification( "powerShell/runspaceChanged", new MinifiedRunspaceDetails(e.NewRunspace)); } @@ -1831,7 +1831,7 @@ public MinifiedRunspaceDetails(RunspaceDetails eventArgs) /// details of the execution status change private void PowerShellContext_ExecutionStatusChangedAsync(object sender, ExecutionStatusChangedEventArgs e) { - _languageServer.SendNotification( + _languageServer?.SendNotification( "powerShell/executionStatusChanged", e); } From 8024e0b1ae0ec4c45d3288e0812c1c10567b6d6f Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Sat, 12 Oct 2019 02:52:43 +0200 Subject: [PATCH 3/6] this makes me cry --- src/PowerShellEditorServices/Hosting/EditorServicesHost.cs | 5 +++++ src/PowerShellEditorServices/Server/PsesDebugServer.cs | 3 +++ .../DebugAdapter/Handlers/ConfigurationDoneHandler.cs | 5 ----- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs index 1a9660f6e..64d6054c3 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs @@ -359,6 +359,11 @@ public void StartDebugService( 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 && useExistingSession) { alreadySubscribedDebug = true; diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index bebb1f9a1..12987dd76 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -53,6 +53,9 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider, boo _powerShellContextService = languageServerServiceProvider.GetService(); _powerShellContextService.IsDebugServerActive = true; + // Needed to make sure PSReadLine's static properties are initialized in the pipeline thread. + _powerShellContextService.ExecuteScriptStringAsync("[System.Runtime.CompilerServices.RuntimeHelpers]::RunClassConstructor([Microsoft.PowerShell.PSConsoleReadLine].TypeHandle)"); + options.Services = new ServiceCollection() .AddPsesDebugServices(languageServerServiceProvider, this, useExistingSession); diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs index 379df5d1b..747a8a9b2 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs @@ -52,11 +52,6 @@ public async Task Handle(ConfigurationDoneArguments r // If this is a debug-only session, we need to start // the command loop manually _powerShellContextService.ConsoleReader.StartCommandLoop(); - await Task.Delay(10000); - while (_powerShellContextService.SessionState != PowerShellContextState.Ready) - { - await Task.Delay(2000); - } } if (!string.IsNullOrEmpty(_debugStateService.ScriptToLaunch)) From ad584c0c98fc1d629ca9b6ed68968d6a10743d26 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Sat, 12 Oct 2019 03:09:00 +0200 Subject: [PATCH 4/6] wait for completion of script --- src/PowerShellEditorServices/Server/PsesDebugServer.cs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 12987dd76..7d3ddb2d5 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -54,7 +54,9 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider, boo _powerShellContextService.IsDebugServerActive = true; // Needed to make sure PSReadLine's static properties are initialized in the pipeline thread. - _powerShellContextService.ExecuteScriptStringAsync("[System.Runtime.CompilerServices.RuntimeHelpers]::RunClassConstructor([Microsoft.PowerShell.PSConsoleReadLine].TypeHandle)"); + _powerShellContextService + .ExecuteScriptStringAsync("[System.Runtime.CompilerServices.RuntimeHelpers]::RunClassConstructor([Microsoft.PowerShell.PSConsoleReadLine].TypeHandle)") + .Wait(); options.Services = new ServiceCollection() .AddPsesDebugServices(languageServerServiceProvider, this, useExistingSession); From c3690031969d84e7bf83f1556cd26d5ba4e247c8 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Mon, 14 Oct 2019 22:21:25 +0300 Subject: [PATCH 5/6] address rob's feedback --- .../Hosting/EditorServicesHost.cs | 23 ++++++++++++------- .../Server/PsesDebugServer.cs | 12 +++++----- ....cs => PsesServiceCollectionExtensions.cs} | 8 +++---- 3 files changed, 25 insertions(+), 18 deletions(-) rename src/PowerShellEditorServices/Server/{PsesServiceCollection.cs => PsesServiceCollectionExtensions.cs} (96%) diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs index 64d6054c3..6abfb9530 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs @@ -285,16 +285,16 @@ public void StartLanguageService( /// /// The config that contains information on the communication protocol that will be used. /// The profiles that will be loaded in the session. - /// Determines if we will reuse the session that we have. + /// Determines if we will make a new session typically used for temporary console debugging. public void StartDebugService( EditorServiceTransportConfig config, ProfilePaths profilePaths, - bool useExistingSession) + bool useTempSession) { _logger.LogInformation($"Debug NamedPipe: {config.InOutPipeName}\nDebug OutPipe: {config.OutPipeName}"); IServiceProvider serviceProvider = null; - if (!useExistingSession) + if (useTempSession) { serviceProvider = new ServiceCollection() .AddLogging(builder => builder @@ -332,7 +332,7 @@ public void StartDebugService( .ContinueWith(async task => { _logger.LogInformation("Starting debug server"); - await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useExistingSession); + await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useTempSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); @@ -349,7 +349,7 @@ public void StartDebugService( Task.Run(async () => { - await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useExistingSession); + await _debugServer.StartAsync(serviceProvider ?? _languageServer.LanguageServer.Services, useTempSession); _logger.LogInformation( $"Debug service started, type = {config.TransportType}, endpoint = {config.Endpoint}"); }); @@ -364,14 +364,14 @@ public void StartDebugService( // 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 && useExistingSession) + if(!alreadySubscribedDebug && !useTempSession) { alreadySubscribedDebug = true; _debugServer.SessionEnded += (sender, eventArgs) => { _debugServer.Dispose(); alreadySubscribedDebug = false; - StartDebugService(config, profilePaths, useExistingSession); + StartDebugService(config, profilePaths, useTempSession); }; } } @@ -389,12 +389,19 @@ public void StopServices() /// public void WaitForCompletion() { - // TODO: We need a way to know when to complete this task! + // If _languageServer is not null, then we are either using: + // Stdio - that only uses a LanguageServer so we return when that has shutdown. + // NamedPipes - that uses both LanguageServer and DebugServer, but LanguageServer + // is the core of PowerShell Editor Services and if that shuts down, + // we want the whole process to shutdown. if (_languageServer != null) { _languageServer.WaitForShutdown().Wait(); return; } + + // If there is no LanguageServer, then we must be running with the DebugServiceOnly switch + // (used in Temporary console debugging) and we need to wait for the DebugServer to shutdown. _debugServer.WaitForShutdown().Wait(); } diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 7d3ddb2d5..721d2cbe6 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -26,7 +26,7 @@ public class PsesDebugServer : IDisposable private PowerShellContextService _powerShellContextService; - private readonly TaskCompletionSource _serverStart; + private readonly TaskCompletionSource _serverRunning; public PsesDebugServer( ILoggerFactory factory, @@ -36,10 +36,10 @@ public PsesDebugServer( _loggerFactory = factory; _inputStream = inputStream; _outputStream = outputStream; - _serverStart = new TaskCompletionSource(); + _serverRunning = new TaskCompletionSource(); } - public async Task StartAsync(IServiceProvider languageServerServiceProvider, bool useExistingSession) + public async Task StartAsync(IServiceProvider languageServerServiceProvider, bool useTempSession) { _jsonRpcServer = await JsonRpcServer.From(options => { @@ -59,7 +59,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider, boo .Wait(); options.Services = new ServiceCollection() - .AddPsesDebugServices(languageServerServiceProvider, this, useExistingSession); + .AddPsesDebugServices(languageServerServiceProvider, this, useTempSession); options .WithInput(_inputStream) @@ -97,12 +97,12 @@ public void Dispose() { _powerShellContextService.IsDebugServerActive = false; _jsonRpcServer.Dispose(); - _serverStart.SetResult(true); + _serverRunning.SetResult(true); } public async Task WaitForShutdown() { - await _serverStart.Task; + await _serverRunning.Task; } #region Events diff --git a/src/PowerShellEditorServices/Server/PsesServiceCollection.cs b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs similarity index 96% rename from src/PowerShellEditorServices/Server/PsesServiceCollection.cs rename to src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs index 8dc9a7467..7cfa6dce5 100644 --- a/src/PowerShellEditorServices/Server/PsesServiceCollection.cs +++ b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs @@ -1,4 +1,4 @@ -// +// // Copyright (c) Microsoft. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. // @@ -13,7 +13,7 @@ namespace Microsoft.PowerShell.EditorServices.Server { - internal static class PsesServiceCollection + internal static class PsesServiceCollectionExtensions { public static IServiceCollection AddPsesLanguageServices ( this IServiceCollection collection, @@ -67,7 +67,7 @@ public static IServiceCollection AddPsesDebugServices ( this IServiceCollection collection, IServiceProvider languageServiceProvider, PsesDebugServer psesDebugServer, - bool useExistingSession + bool useTempSession ) { return collection.AddSingleton(languageServiceProvider.GetService()) @@ -77,7 +77,7 @@ bool useExistingSession .AddSingleton() .AddSingleton(new DebugStateService { - OwnsEditorSession = !useExistingSession + OwnsEditorSession = useTempSession }) .AddSingleton(); } From 598bf16efaaf39d9d08e1dff8b276bfa9583b6e9 Mon Sep 17 00:00:00 2001 From: Tyler Leonhardt Date: Wed, 16 Oct 2019 21:55:06 +0300 Subject: [PATCH 6/6] address Patrick's feedback --- .../PowerShellEditorServices.psm1 | 4 ++-- .../Hosting/EditorServicesHost.cs | 4 ++-- src/PowerShellEditorServices/Server/PsesDebugServer.cs | 8 ++++---- .../Server/PsesServiceCollectionExtensions.cs | 5 ++--- 4 files changed, 10 insertions(+), 11 deletions(-) diff --git a/module/PowerShellEditorServices/PowerShellEditorServices.psm1 b/module/PowerShellEditorServices/PowerShellEditorServices.psm1 index b37b6ee65..5861b9420 100644 --- a/module/PowerShellEditorServices/PowerShellEditorServices.psm1 +++ b/module/PowerShellEditorServices/PowerShellEditorServices.psm1 @@ -150,12 +150,12 @@ function Start-EditorServicesHost { } if ($DebugServiceOnly.IsPresent) { - $editorServicesHost.StartDebugService($debugServiceConfig, $profilePaths, $false); + $editorServicesHost.StartDebugService($debugServiceConfig, $profilePaths, $true); } elseif($Stdio.IsPresent) { $editorServicesHost.StartLanguageService($languageServiceConfig, $profilePaths); } else { $editorServicesHost.StartLanguageService($languageServiceConfig, $profilePaths); - $editorServicesHost.StartDebugService($debugServiceConfig, $profilePaths, $true); + $editorServicesHost.StartDebugService($debugServiceConfig, $profilePaths, $false); } return $editorServicesHost diff --git a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs index 6abfb9530..68c004c0c 100644 --- a/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs +++ b/src/PowerShellEditorServices/Hosting/EditorServicesHost.cs @@ -396,13 +396,13 @@ public void WaitForCompletion() // we want the whole process to shutdown. if (_languageServer != null) { - _languageServer.WaitForShutdown().Wait(); + _languageServer.WaitForShutdown().GetAwaiter().GetResult(); return; } // If there is no LanguageServer, then we must be running with the DebugServiceOnly switch // (used in Temporary console debugging) and we need to wait for the DebugServer to shutdown. - _debugServer.WaitForShutdown().Wait(); + _debugServer.WaitForShutdown().GetAwaiter().GetResult(); } #endregion diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index 721d2cbe6..98474b0be 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -26,7 +26,7 @@ public class PsesDebugServer : IDisposable private PowerShellContextService _powerShellContextService; - private readonly TaskCompletionSource _serverRunning; + private readonly TaskCompletionSource _serverStopped; public PsesDebugServer( ILoggerFactory factory, @@ -36,7 +36,7 @@ public PsesDebugServer( _loggerFactory = factory; _inputStream = inputStream; _outputStream = outputStream; - _serverRunning = new TaskCompletionSource(); + _serverStopped = new TaskCompletionSource(); } public async Task StartAsync(IServiceProvider languageServerServiceProvider, bool useTempSession) @@ -97,12 +97,12 @@ public void Dispose() { _powerShellContextService.IsDebugServerActive = false; _jsonRpcServer.Dispose(); - _serverRunning.SetResult(true); + _serverStopped.SetResult(true); } public async Task WaitForShutdown() { - await _serverRunning.Task; + await _serverStopped.Task; } #region Events diff --git a/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs index 7cfa6dce5..cd66847b0 100644 --- a/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs +++ b/src/PowerShellEditorServices/Server/PsesServiceCollectionExtensions.cs @@ -63,12 +63,11 @@ public static IServiceCollection AddPsesLanguageServices ( }); } - public static IServiceCollection AddPsesDebugServices ( + public static IServiceCollection AddPsesDebugServices( this IServiceCollection collection, IServiceProvider languageServiceProvider, PsesDebugServer psesDebugServer, - bool useTempSession - ) + bool useTempSession) { return collection.AddSingleton(languageServiceProvider.GetService()) .AddSingleton(languageServiceProvider.GetService())