Skip to content

Commit c25d0d2

Browse files
Merge pull request #1894 from SeeminglyScience/fix-watch-expression-errors
Fix stepping while watch expressions or interactive pipeline is running
2 parents 87cd721 + 60e37b4 commit c25d0d2

File tree

3 files changed

+32
-7
lines changed

3 files changed

+32
-7
lines changed

src/PowerShellEditorServices/Services/DebugAdapter/DebugService.cs

+16-4
Original file line numberDiff line numberDiff line change
@@ -497,10 +497,22 @@ public async Task<VariableDetails> EvaluateExpressionAsync(
497497
bool writeResultAsOutput)
498498
{
499499
PSCommand command = new PSCommand().AddScript(expressionString);
500-
IReadOnlyList<PSObject> results = await _executionService.ExecutePSCommandAsync<PSObject>(
501-
command,
502-
CancellationToken.None,
503-
new PowerShellExecutionOptions { WriteOutputToHost = writeResultAsOutput, ThrowOnError = !writeResultAsOutput }).ConfigureAwait(false);
500+
IReadOnlyList<PSObject> results;
501+
try
502+
{
503+
results = await _executionService.ExecutePSCommandAsync<PSObject>(
504+
command,
505+
CancellationToken.None,
506+
new PowerShellExecutionOptions { WriteOutputToHost = writeResultAsOutput, ThrowOnError = !writeResultAsOutput }).ConfigureAwait(false);
507+
}
508+
catch (Exception e)
509+
{
510+
// If a watch expression throws we want to show the exception.
511+
// TODO: Show the exception as an expandable object.
512+
return new VariableDetails(
513+
expressionString,
514+
$"{e.GetType().Name}: {e.Message}");
515+
}
504516

505517
// Since this method should only be getting invoked in the debugger,
506518
// we can assume that Out-String will be getting used to format results

src/PowerShellEditorServices/Services/PowerShell/Debugging/PowerShellDebugContext.cs

+15-2
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.Threading;
77
using System.Threading.Tasks;
88
using Microsoft.Extensions.Logging;
9+
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Context;
910
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Host;
1011
using Microsoft.PowerShell.EditorServices.Services.PowerShell.Utility;
1112

@@ -145,15 +146,27 @@ public void SetDebugResuming(DebuggerResumeAction debuggerResumeAction)
145146
// TODO: We need to assign cancellation tokens to each frame, because the current
146147
// logic results in a deadlock here when we try to cancel the scopes...which
147148
// includes ourself (hence running it in a separate thread).
148-
Task.Run(() => _psesHost.UnwindCallStack());
149+
_ = Task.Run(() => _psesHost.UnwindCallStack());
149150
return;
150151
}
151152

152153
// Otherwise we're continuing or stepping (i.e. resuming) so we need to cancel the
153154
// debugger REPL.
154-
if (_psesHost.CurrentFrame.IsRepl)
155+
PowerShellFrameType frameType = _psesHost.CurrentFrame.FrameType;
156+
if (frameType.HasFlag(PowerShellFrameType.Repl))
155157
{
156158
_psesHost.CancelIdleParentTask();
159+
return;
160+
}
161+
162+
// If the user is running something via the REPL like `while ($true) { sleep 1 }`
163+
// and then tries to step, we want to stop that so that execution can resume.
164+
//
165+
// This also applies to anything we're running on debugger stop like watch variables.
166+
if (frameType.HasFlag(PowerShellFrameType.Debug | PowerShellFrameType.Nested))
167+
{
168+
_psesHost.ForceSetExit();
169+
_psesHost.CancelIdleParentTask();
157170
}
158171
}
159172

src/PowerShellEditorServices/Services/PowerShell/Execution/SynchronousPowerShellTask.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -382,7 +382,7 @@ internal void MaybeAddToHistory()
382382

383383
private void CancelDebugExecution()
384384
{
385-
if (_pwsh.Runspace.RunspaceStateInfo.IsUsable())
385+
if (!_pwsh.Runspace.RunspaceStateInfo.IsUsable())
386386
{
387387
return;
388388
}

0 commit comments

Comments
 (0)