Skip to content

Commit b1808f0

Browse files
committed
Make ExecuteCommandAsync cancellable
This lets us cancel the debugger more reliably.
1 parent c9269b9 commit b1808f0

File tree

9 files changed

+36
-22
lines changed

9 files changed

+36
-22
lines changed

src/PowerShellEditorServices/Services/DebugAdapter/Handlers/LaunchAndAttachHandler.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -303,11 +303,13 @@ await _powerShellContextService.ExecuteScriptStringAsync(
303303
string debugRunspaceCmd;
304304
if (request.RunspaceName != null)
305305
{
306-
IEnumerable<int?> ids = await _powerShellContextService.ExecuteCommandAsync<int?>(new PSCommand()
306+
IEnumerable<int?> ids = await _powerShellContextService.ExecuteCommandAsync<int?>(
307+
new PSCommand()
307308
.AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace")
308309
.AddParameter("Name", request.RunspaceName)
309310
.AddCommand("Microsoft.PowerShell.Utility\\Select-Object")
310-
.AddParameter("ExpandProperty", "Id")).ConfigureAwait(false);
311+
.AddParameter("ExpandProperty", "Id"), cancellationToken: cancellationToken).ConfigureAwait(false);
312+
311313
foreach (var id in ids)
312314
{
313315
_debugStateService.RunspaceId = id;

src/PowerShellEditorServices/Services/PowerShellContext/Console/ConsoleReadLine.cs

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -208,9 +208,8 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
208208
command.AddParameter("CursorColumn", currentCursorIndex);
209209
command.AddParameter("Options", null);
210210

211-
var results = await this.powerShellContext
212-
.ExecuteCommandAsync<CommandCompletion>(command, sendOutputToHost: false, sendErrorToHost: false)
213-
.ConfigureAwait(false);
211+
var results = await this.powerShellContext.ExecuteCommandAsync<CommandCompletion>(
212+
command, sendOutputToHost: false, sendErrorToHost: false, cancellationToken).ConfigureAwait(false);
214213

215214
currentCompletion = results.FirstOrDefault();
216215
}
@@ -327,8 +326,8 @@ internal async Task<string> InvokeLegacyReadLineAsync(bool isCommandLine, Cancel
327326
PSCommand command = new PSCommand();
328327
command.AddCommand("Get-History");
329328

330-
currentHistory = await this.powerShellContext.ExecuteCommandAsync<PSObject>(command, sendOutputToHost: false, sendErrorToHost: false)
331-
.ConfigureAwait(false)
329+
currentHistory = await this.powerShellContext.ExecuteCommandAsync<PSObject>(
330+
command, sendOutputToHost: false, sendErrorToHost: false, cancellationToken).ConfigureAwait(false)
332331
as Collection<PSObject>;
333332

334333
if (currentHistory != null)

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ExpandAliasHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,8 @@ function __Expand-Alias {
6969
.AddStatement()
7070
.AddCommand("__Expand-Alias")
7171
.AddArgument(request.Text);
72-
var result = await _powerShellContextService.ExecuteCommandAsync<string>(psCommand).ConfigureAwait(false);
72+
var result = await _powerShellContextService.ExecuteCommandAsync<string>(
73+
psCommand, cancellationToken: cancellationToken).ConfigureAwait(false);
7374

7475
return new ExpandAliasResult
7576
{

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/GetCommandHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ public async Task<List<PSCommandMessage>> Handle(GetCommandParams request, Cance
5353
.AddCommand("Microsoft.PowerShell.Utility\\Sort-Object")
5454
.AddParameter("Property", "Name");
5555

56-
IEnumerable<CommandInfo> result = await _powerShellContextService.ExecuteCommandAsync<CommandInfo>(psCommand).ConfigureAwait(false);
56+
IEnumerable<CommandInfo> result = await _powerShellContextService.ExecuteCommandAsync<CommandInfo>(
57+
psCommand, cancellationToken: cancellationToken).ConfigureAwait(false);
5758

5859
var commandList = new List<PSCommandMessage>();
5960
if (result != null)

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/PSHostProcessAndRunspaceHandlers.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,8 @@ public async Task<RunspaceResponse[]> Handle(GetRunspaceParams request, Cancella
8787
var psCommand = new PSCommand().AddCommand("Microsoft.PowerShell.Utility\\Get-Runspace");
8888
var sb = new StringBuilder();
8989
// returns (not deserialized) Runspaces. For simpler code, we use PSObject and rely on dynamic later.
90-
runspaces = await _powerShellContextService.ExecuteCommandAsync<PSObject>(psCommand, sb).ConfigureAwait(false);
90+
runspaces = await _powerShellContextService.ExecuteCommandAsync<PSObject>(
91+
psCommand, sb, cancellationToken: cancellationToken).ConfigureAwait(false);
9192
}
9293

9394
var runspaceResponses = new List<RunspaceResponse>();

src/PowerShellEditorServices/Services/PowerShellContext/Handlers/ShowHelpHandler.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ public async Task<Unit> Handle(ShowHelpParams request, CancellationToken cancell
7272

7373
// TODO: Rather than print the help in the console, we should send the string back
7474
// to VSCode to display in a help pop-up (or similar)
75-
await _powerShellContextService.ExecuteCommandAsync<PSObject>(checkHelpPSCommand, sendOutputToHost: true).ConfigureAwait(false);
75+
await _powerShellContextService.ExecuteCommandAsync<PSObject>(
76+
checkHelpPSCommand, sendOutputToHost: true, cancellationToken: cancellationToken).ConfigureAwait(false);
7677
return Unit.Value;
7778
}
7879
}

src/PowerShellEditorServices/Services/PowerShellContext/PowerShellContextService.cs

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -519,9 +519,11 @@ public Task<RunspaceHandle> GetRunspaceHandleAsync(CancellationToken cancellatio
519519
public Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
520520
PSCommand psCommand,
521521
bool sendOutputToHost = false,
522-
bool sendErrorToHost = true)
522+
bool sendErrorToHost = true,
523+
CancellationToken cancellationToken = default)
523524
{
524-
return ExecuteCommandAsync<TResult>(psCommand, errorMessages: null, sendOutputToHost, sendErrorToHost);
525+
return this.ExecuteCommandAsync<TResult>(
526+
psCommand, errorMessages: null, sendOutputToHost, sendErrorToHost, cancellationToken: cancellationToken);
525527
}
526528

527529
/// <summary>
@@ -549,7 +551,8 @@ public Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
549551
StringBuilder errorMessages,
550552
bool sendOutputToHost = false,
551553
bool sendErrorToHost = true,
552-
bool addToHistory = false)
554+
bool addToHistory = false,
555+
CancellationToken cancellationToken = default)
553556
{
554557
return
555558
this.ExecuteCommandAsync<TResult>(
@@ -560,7 +563,8 @@ public Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
560563
WriteOutputToHost = sendOutputToHost,
561564
WriteErrorsToHost = sendErrorToHost,
562565
AddToHistory = addToHistory
563-
});
566+
},
567+
cancellationToken);
564568
}
565569

566570

@@ -581,7 +585,8 @@ public Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
581585
public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
582586
PSCommand psCommand,
583587
StringBuilder errorMessages,
584-
ExecutionOptions executionOptions)
588+
ExecutionOptions executionOptions,
589+
CancellationToken cancellationToken = default)
585590
{
586591
Validate.IsNotNull(nameof(psCommand), psCommand);
587592
Validate.IsNotNull(nameof(executionOptions), executionOptions);
@@ -759,8 +764,10 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
759764
return shell.Invoke<TResult>(null, invocationSettings);
760765
}
761766

762-
// May need a cancellation token here
763-
return await Task.Run<IEnumerable<TResult>>(() => shell.Invoke<TResult>(input: null, invocationSettings), CancellationToken.None).ConfigureAwait(false);
767+
// This is the primary reason that ExecuteCommandAsync takes a CancellationToken
768+
return await Task.Run<IEnumerable<TResult>>(
769+
() => shell.Invoke<TResult>(input: null, invocationSettings), cancellationToken)
770+
.ConfigureAwait(false);
764771
}
765772
finally
766773
{
@@ -872,7 +879,7 @@ public async Task<IEnumerable<TResult>> ExecuteCommandAsync<TResult>(
872879
// will exist already so we need to create one and then use it
873880
if (runspaceHandle == null)
874881
{
875-
runspaceHandle = await this.GetRunspaceHandleAsync().ConfigureAwait(false);
882+
runspaceHandle = await this.GetRunspaceHandleAsync(cancellationToken).ConfigureAwait(false);
876883
}
877884

878885
sessionDetails = this.GetSessionDetailsInRunspace(runspaceHandle.Runspace);
@@ -1938,7 +1945,7 @@ private void PowerShellContext_ExecutionStatusChangedAsync(object sender, Execut
19381945

19391946
private IEnumerable<TResult> ExecuteCommandInDebugger<TResult>(PSCommand psCommand, bool sendOutputToHost)
19401947
{
1941-
this.logger.LogTrace($"Attempting to execute command(s)a in the debugger: {GetStringForPSCommand(psCommand)}");
1948+
this.logger.LogTrace($"Attempting to execute command(s) in the debugger: {GetStringForPSCommand(psCommand)}");
19421949

19431950
IEnumerable<TResult> output =
19441951
this.versionSpecificOperations.ExecuteCommandInDebugger<TResult>(

src/PowerShellEditorServices/Services/PowerShellContext/Session/Host/EditorServicesPSHostUserInterface.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,8 @@ private async Task WritePromptStringToHostAsync(CancellationToken cancellationTo
731731

732732
cancellationToken.ThrowIfCancellationRequested();
733733
string promptString =
734-
(await this.powerShellContext.ExecuteCommandAsync<PSObject>(promptCommand, false, false).ConfigureAwait(false))
734+
(await this.powerShellContext.ExecuteCommandAsync<PSObject>(
735+
promptCommand, false, false, cancellationToken).ConfigureAwait(false))
735736
.Select(pso => pso.BaseObject)
736737
.OfType<string>()
737738
.FirstOrDefault() ?? "PS> ";

src/PowerShellEditorServices/Services/PowerShellContext/Session/PSReadLinePromptContext.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,8 @@ public async Task<string> InvokeReadLineAsync(bool isCommandLine, CancellationTo
143143
IEnumerable<string> readLineResults = await _powerShellContext.ExecuteCommandAsync<string>(
144144
readLineCommand,
145145
errorMessages: null,
146-
s_psrlExecutionOptions).ConfigureAwait(false);
146+
s_psrlExecutionOptions,
147+
cancellationToken).ConfigureAwait(false);
147148

148149
string line = readLineResults.FirstOrDefault();
149150

0 commit comments

Comments
 (0)