diff --git a/src/PowerShellEditorServices/Server/PsesDebugServer.cs b/src/PowerShellEditorServices/Server/PsesDebugServer.cs index b3bf2edba..860dbc845 100644 --- a/src/PowerShellEditorServices/Server/PsesDebugServer.cs +++ b/src/PowerShellEditorServices/Server/PsesDebugServer.cs @@ -24,6 +24,8 @@ public class PsesDebugServer : IDisposable private IJsonRpcServer _jsonRpcServer; + private PowerShellContextService _powerShellContextService; + public PsesDebugServer( ILoggerFactory factory, Stream inputStream, @@ -42,8 +44,14 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider) options.Reciever = new DapReciever(); options.LoggerFactory = _loggerFactory; ILogger logger = options.LoggerFactory.CreateLogger("DebugOptionsStartup"); + + // We need to let the PowerShell Context Service know that we are in a debug session + // so that it doesn't send the powerShell/startDebugger message. + _powerShellContextService = languageServerServiceProvider.GetService(); + _powerShellContextService.IsDebugServerActive = true; + options.Services = new ServiceCollection() - .AddSingleton(languageServerServiceProvider.GetService()) + .AddSingleton(_powerShellContextService) .AddSingleton(languageServerServiceProvider.GetService()) .AddSingleton(languageServerServiceProvider.GetService()) .AddSingleton(this) @@ -85,6 +93,7 @@ public async Task StartAsync(IServiceProvider languageServerServiceProvider) public void Dispose() { + _powerShellContextService.IsDebugServerActive = false; _jsonRpcServer.Dispose(); } diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs index c8d566b12..dbde29254 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs @@ -1191,7 +1191,7 @@ private string TrimScriptListingLine(PSObject scriptLineObj, ref int prefixLengt /// public event EventHandler DebuggerStopped; - private async void OnDebuggerStopAsync(object sender, DebuggerStopEventArgs e) + internal async void OnDebuggerStopAsync(object sender, DebuggerStopEventArgs e) { bool noScriptName = false; string localScriptPath = e.InvocationInfo.ScriptName; diff --git a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs index 03cdf7fde..addf829a1 100644 --- a/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs +++ b/src/PowerShellEditorServices/Services/DebugAdapter/Handlers/ConfigurationDoneHandler.cs @@ -73,9 +73,18 @@ public Task Handle(ConfigurationDoneArguments request if (_debugService.IsDebuggerStopped) { - // If this is an interactive session and there's a pending breakpoint, - // send that information along to the debugger client - _debugEventHandlerService.TriggerDebuggerStopped(_debugService.CurrentDebuggerStoppedEventArgs); + if (_debugService.CurrentDebuggerStoppedEventArgs != null) + { + // If this is an interactive session and there's a pending breakpoint, + // send that information along to the debugger client + _debugEventHandlerService.TriggerDebuggerStopped(_debugService.CurrentDebuggerStoppedEventArgs); + } + else + { + // If this is an interactive session and there's a pending breakpoint that has not been propagated through + // the debug service, fire the debug service's OnDebuggerStop event. + _debugService.OnDebuggerStopAsync(null, _powerShellContextService.CurrentDebuggerStopEventArgs); + } } } diff --git a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs index c0effd3be..f46b5cfba 100644 --- a/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs +++ b/src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs @@ -137,6 +137,10 @@ public RunspaceDetails CurrentRunspace /// public string InitialWorkingDirectory { get; private set; } + internal bool IsDebugServerActive { get; set; } + + internal DebuggerStopEventArgs CurrentDebuggerStopEventArgs { get; private set; } + #endregion #region Constructors @@ -2296,6 +2300,15 @@ private void StartCommandLoopOnRunspaceAvailable() private void OnDebuggerStop(object sender, DebuggerStopEventArgs e) { + // We maintain the current stop event args so that we can use it in the DebugServer to fire the "stopped" event + // when the DebugServer is fully started. + CurrentDebuggerStopEventArgs = e; + + if (!IsDebugServerActive) + { + _languageServer.SendNotification("powerShell/startDebugger"); + } + if (CurrentRunspace.Context == RunspaceContext.Original) { StartCommandLoopOnRunspaceAvailable(); @@ -2361,6 +2374,9 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e) e.ResumeAction = localDebuggerStoppedTask.GetAwaiter().GetResult(); this.logger.LogTrace("Received debugger resume action " + e.ResumeAction.ToString()); + // Since we are no longer at a breakpoint, we set this to null. + CurrentDebuggerStopEventArgs = null; + // Notify listeners that the debugger has resumed this.DebuggerResumed?.Invoke(this, e.ResumeAction); @@ -2398,6 +2414,9 @@ private void OnDebuggerStop(object sender, DebuggerStopEventArgs e) this.PromptNest, this.CurrentRunspace.Runspace)) { + // Since we are no longer at a breakpoint, we set this to null. + CurrentDebuggerStopEventArgs = null; + if (this.CurrentRunspace.Context == RunspaceContext.DebuggedRunspace) { // Notify listeners that the debugger has resumed @@ -2436,8 +2455,7 @@ private void OnBreakpointUpdated(object sender, BreakpointUpdatedEventArgs e) private void ConfigureRunspaceCapabilities(RunspaceDetails runspaceDetails) { - // TODO: Bring this back - //DscBreakpointCapability.CheckForCapability(this.CurrentRunspace, this, this.logger); + DscBreakpointCapability.CheckForCapability(this.CurrentRunspace, this, this.logger); } private void PushRunspace(RunspaceDetails newRunspaceDetails)