Skip to content

Commit 6d13e2a

Browse files
authored
Merge pull request #51 from santisq/50-modulecompletercs-showing-duplicated-modules
`ModuleCompleter.cs` should filter unique values
2 parents fc4efdf + 6b4362d commit 6d13e2a

File tree

8 files changed

+43
-189
lines changed

8 files changed

+43
-189
lines changed

module/PSParallelPipeline.psd1

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
RootModule = 'bin/netstandard2.0/PSParallelPipeline.dll'
1212

1313
# Version number of this module.
14-
ModuleVersion = '1.2.4'
14+
ModuleVersion = '1.2.5'
1515

1616
# Supported PSEditions
1717
# CompatiblePSEditions = @()

src/PSParallelPipeline/Commands/InvokeParallelCommand.cs

Lines changed: 11 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
using System.Management.Automation;
44
using System.Management.Automation.Runspaces;
55
using System.Threading;
6-
using PSParallelPipeline.Poly;
76

87
namespace PSParallelPipeline.Commands;
98

@@ -80,12 +79,15 @@ protected override void BeginProcessing()
8079
ScriptBlock.GetUsingParameters(this));
8180

8281
_worker = new Worker(poolSettings, workerSettings, _cts.Token);
83-
_worker.Run();
8482
}
8583

8684
protected override void ProcessRecord()
8785
{
88-
Dbg.Assert(_worker is not null);
86+
if (_worker is null)
87+
{
88+
return;
89+
}
90+
8991
InputObject.ThrowIfInputObjectIsScriptBlock(this);
9092

9193
try
@@ -103,14 +105,17 @@ protected override void ProcessRecord()
103105
}
104106
catch (OperationCanceledException exception)
105107
{
106-
CancelAndWait();
108+
_worker.WaitForCompletion();
107109
exception.WriteTimeoutError(this);
108110
}
109111
}
110112

111113
protected override void EndProcessing()
112114
{
113-
Dbg.Assert(_worker is not null);
115+
if (_worker is null)
116+
{
117+
return;
118+
}
114119

115120
try
116121
{
@@ -129,7 +134,7 @@ protected override void EndProcessing()
129134
}
130135
catch (OperationCanceledException exception)
131136
{
132-
CancelAndWait();
137+
_worker.WaitForCompletion();
133138
exception.WriteTimeoutError(this);
134139
}
135140
}

src/PSParallelPipeline/Extensions.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -209,14 +209,28 @@ private static string ResolvePath(this PSCmdlet cmdlet, string path)
209209
.InvokeReturnAsIs();
210210
}
211211

212-
internal static Task InvokePowerShellAsync(
212+
internal static Task InvokePowerShellAsync<TOut>(
213213
this PowerShell powerShell,
214-
PSDataCollection<PSObject> output)
214+
PSDataCollection<TOut> output)
215215
=> Task.Factory.FromAsync(
216-
powerShell.BeginInvoke<PSObject, PSObject>(null, output),
216+
powerShell.BeginInvoke<PSObject, TOut>(null, output),
217217
powerShell.EndInvoke);
218218

219219
internal static ConfiguredTaskAwaitable NoContext(this Task task) => task.ConfigureAwait(false);
220220

221221
internal static ConfiguredTaskAwaitable<T> NoContext<T>(this Task<T> task) => task.ConfigureAwait(false);
222+
223+
public static IEnumerable<TSource> DistinctBy<TSource, TKey>(
224+
this IEnumerable<TSource> source,
225+
Func<TSource, TKey> keySelector)
226+
{
227+
HashSet<TKey> seenKeys = [];
228+
foreach (TSource element in source)
229+
{
230+
if (seenKeys.Add(keySelector(element)))
231+
{
232+
yield return element;
233+
}
234+
}
235+
}
222236
}
Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections;
33
using System.Collections.Generic;
4+
using System.Linq;
45
using System.Management.Automation;
56
using System.Management.Automation.Language;
67

@@ -15,17 +16,16 @@ public IEnumerable<CompletionResult> CompleteArgument(
1516
CommandAst commandAst,
1617
IDictionary fakeBoundParameters)
1718
{
18-
using PowerShell ps = PowerShell
19+
using PowerShell powershell = PowerShell
1920
.Create(RunspaceMode.CurrentRunspace)
2021
.AddCommand("Get-Module")
2122
.AddParameter("ListAvailable");
2223

23-
foreach (PSModuleInfo module in ps.Invoke<PSModuleInfo>())
24-
{
25-
if (module.Name.StartsWith(wordToComplete, StringComparison.InvariantCultureIgnoreCase))
26-
{
27-
yield return new CompletionResult(module.Name);
28-
}
29-
}
24+
return powershell
25+
.Invoke<PSModuleInfo>()
26+
.DistinctBy(e => e.Name)
27+
.Where(e => e.Name.StartsWith(wordToComplete, StringComparison.InvariantCultureIgnoreCase))
28+
.OrderBy(e => e.Name)
29+
.Select(e => new CompletionResult(e.Name));
3030
}
3131
}

src/PSParallelPipeline/PSTask.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -114,13 +114,13 @@ private PSTask AddUsingStatements(Dictionary<string, object?> usingParams)
114114

115115
private void CompleteTask()
116116
{
117+
_powershell.Dispose();
117118
if (_canceled)
118119
{
119120
_runspace?.Dispose();
120121
return;
121122
}
122123

123-
_powershell.Dispose();
124124
if (_runspace is not null)
125125
{
126126
_pool.PushRunspace(_runspace);
@@ -129,7 +129,7 @@ private void CompleteTask()
129129

130130
internal void Cancel()
131131
{
132-
_powershell.Dispose();
132+
_powershell.BeginStop(null, null);
133133
_canceled = true;
134134
}
135135
}

src/PSParallelPipeline/Poly/Dbg.cs

Lines changed: 0 additions & 11 deletions
This file was deleted.

src/PSParallelPipeline/Poly/Nullable.cs

Lines changed: 0 additions & 150 deletions
This file was deleted.

src/PSParallelPipeline/Worker.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ namespace PSParallelPipeline;
88

99
internal sealed class Worker
1010
{
11-
private Task? _worker;
11+
private readonly Task _worker;
1212

1313
private readonly TaskSettings _taskSettings;
1414

@@ -31,9 +31,10 @@ internal Worker(
3131
_taskSettings = taskSettings;
3232
_streams = new PSOutputStreams(_output);
3333
_pool = new RunspacePool(poolSettings, _streams, _token);
34+
_worker = Task.Run(Start, cancellationToken: _token);
3435
}
3536

36-
internal void WaitForCompletion() => _worker?.GetAwaiter().GetResult();
37+
internal void WaitForCompletion() => _worker.GetAwaiter().GetResult();
3738

3839
internal void Enqueue(object? input) => _input.Add(input, _token);
3940

@@ -43,8 +44,6 @@ internal Worker(
4344

4445
internal IEnumerable<PSOutputData> GetConsumingEnumerable() => _output.GetConsumingEnumerable(_token);
4546

46-
internal void Run() => _worker = Task.Run(Start, cancellationToken: _token);
47-
4847
private async Task Start()
4948
{
5049
List<Task> tasks = new(_pool.MaxRunspaces);
@@ -55,10 +54,7 @@ private async Task Start()
5554
{
5655
if (tasks.Count == tasks.Capacity)
5756
{
58-
Task task = await Task
59-
.WhenAny(tasks)
60-
.NoContext();
61-
57+
Task task = await Task.WhenAny(tasks).NoContext();
6258
tasks.Remove(task);
6359
await task.NoContext();
6460
}

0 commit comments

Comments
 (0)