Skip to content

Commit a1f3769

Browse files
committed
replace ICompletionSource with a Func, fixes #1928
1 parent 8b66431 commit a1f3769

File tree

5 files changed

+24
-104
lines changed

5 files changed

+24
-104
lines changed

src/System.CommandLine.ApiCompatibility.Tests/ApiCompatibilityApprovalTests.System_CommandLine_api_is_not_changed.approved.txt

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
System.CommandLine
22
public abstract class Argument : Symbol, System.CommandLine.Binding.IValueDescriptor, System.CommandLine.Completions.ICompletionSource
33
public ArgumentArity Arity { get; set; }
4-
public System.Collections.Generic.ICollection<System.CommandLine.Completions.ICompletionSource> Completions { get; }
4+
public System.Collections.Generic.ICollection<System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>>> Completions { get; }
55
public System.Boolean HasDefaultValue { get; }
66
public System.String HelpName { get; set; }
77
public System.Type ValueType { get; }
@@ -109,9 +109,8 @@ System.CommandLine
109109
.ctor()
110110
.ctor(System.String message, System.Exception innerException)
111111
public static class CompletionSourceExtensions
112-
public static System.Void Add(this System.Collections.Generic.ICollection<System.CommandLine.Completions.ICompletionSource> completionSources, System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.String>> complete)
113-
public static System.Void Add(this System.Collections.Generic.ICollection<System.CommandLine.Completions.ICompletionSource> completionSources, System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>> complete)
114-
public static System.Void Add(this System.Collections.Generic.ICollection<System.CommandLine.Completions.ICompletionSource> completionSources, System.String[] completions)
112+
public static System.Void Add(this System.Collections.Generic.ICollection<System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>>> completionSources, System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.String>> complete)
113+
public static System.Void Add(this System.Collections.Generic.ICollection<System.Func<System.CommandLine.Completions.CompletionContext,System.Collections.Generic.IEnumerable<System.CommandLine.Completions.CompletionItem>>> completionSources, System.String[] completions)
115114
public static class ConsoleExtensions
116115
public static System.Void Write(this IConsole console, System.String value)
117116
public static System.Void WriteLine(this IConsole console, System.String value)

src/System.CommandLine/Argument.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ public abstract class Argument : Symbol, IValueDescriptor
1717
private Func<ArgumentResult, object?>? _defaultValueFactory;
1818
private ArgumentArity _arity;
1919
private TryConvertArgument? _convertArguments;
20-
private List<ICompletionSource>? _completions = null;
20+
private List<Func<CompletionContext, IEnumerable<CompletionItem>>>? _completions = null;
2121
private List<Action<ArgumentResult>>? _validators = null;
2222

2323
/// <summary>
@@ -74,7 +74,7 @@ internal TryConvertArgument? ConvertArguments
7474
/// <summary>
7575
/// Gets the collection of completion sources for the argument.
7676
/// </summary>
77-
public ICollection<ICompletionSource> Completions =>
77+
public ICollection<Func<CompletionContext, IEnumerable<CompletionItem>>> Completions =>
7878
_completions ??= new ()
7979
{
8080
CompletionSource.ForType(ValueType)
@@ -192,7 +192,7 @@ internal void AddAllowedValues(IReadOnlyList<string> values)
192192
public override IEnumerable<CompletionItem> GetCompletions(CompletionContext context)
193193
{
194194
return Completions
195-
.SelectMany(source => source.GetCompletions(context))
195+
.SelectMany(source => source.Invoke(context))
196196
.Distinct()
197197
.OrderBy(c => c.SortText, StringComparer.OrdinalIgnoreCase);
198198
}

src/System.CommandLine/CompletionSourceExtensions.cs

Lines changed: 4 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ public static class CompletionSourceExtensions
1818
/// <param name="completionSources">The list of completion sources to add to.</param>
1919
/// <param name="complete">The delegate to be called when calculating completions.</param>
2020
public static void Add(
21-
this ICollection<ICompletionSource> completionSources,
21+
this ICollection<Func<CompletionContext, IEnumerable<CompletionItem>>> completionSources,
2222
Func<CompletionContext, IEnumerable<string>> complete)
2323
{
2424
if (completionSources is null)
@@ -31,29 +31,7 @@ public static void Add(
3131
throw new ArgumentNullException(nameof(complete));
3232
}
3333

34-
completionSources.Add(new AnonymousCompletionSource(complete));
35-
}
36-
37-
/// <summary>
38-
/// Adds a completion source using a delegate.
39-
/// </summary>
40-
/// <param name="completionSources">The list of completion sources to add to.</param>
41-
/// <param name="complete">The function to be called when calculating completions.</param>
42-
public static void Add(
43-
this ICollection<ICompletionSource> completionSources,
44-
Func<CompletionContext, IEnumerable<CompletionItem>> complete)
45-
{
46-
if (completionSources is null)
47-
{
48-
throw new ArgumentNullException(nameof(completionSources));
49-
}
50-
51-
if (complete is null)
52-
{
53-
throw new ArgumentNullException(nameof(complete));
54-
}
55-
56-
completionSources.Add(new AnonymousCompletionSource(complete));
34+
completionSources.Add(context => complete(context).Select(value => new CompletionItem(value)));
5735
}
5836

5937
/// <summary>
@@ -62,7 +40,7 @@ public static void Add(
6240
/// <param name="completionSources">The list of completion sources to add to.</param>
6341
/// <param name="completions">A list of strings to be suggested for command line completions.</param>
6442
public static void Add(
65-
this ICollection<ICompletionSource> completionSources,
43+
this ICollection<Func<CompletionContext, IEnumerable<CompletionItem>>> completionSources,
6644
params string[] completions)
6745
{
6846
if (completionSources is null)
@@ -75,7 +53,7 @@ public static void Add(
7553
throw new ArgumentNullException(nameof(completions));
7654
}
7755

78-
completionSources.Add(new AnonymousCompletionSource(_ => completions.Select(s => new CompletionItem(s))));
56+
completionSources.Add(context => completions.Select(value => new CompletionItem(value)));
7957
}
8058
}
8159
}

src/System.CommandLine/Completions/AnonymousCompletionSource.cs

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

src/System.CommandLine/Completions/CompletionSource.cs

Lines changed: 14 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9,67 +9,38 @@
99
namespace System.CommandLine.Completions
1010
{
1111
/// <summary>
12-
/// Provides extension methods supporting <see cref="ICompletionSource"/> and command line tab completion.
12+
/// Provides extension methods supporting command line tab completion.
1313
/// </summary>
1414
internal static class CompletionSource
1515
{
16-
private static readonly ConcurrentDictionary<Type, ICompletionSource> _completionSourcesByType = new();
16+
private static readonly ConcurrentDictionary<Type, Func<CompletionContext, IEnumerable<CompletionItem>>> _completionSourcesByType = new();
1717

1818
/// <summary>
1919
/// Gets a completion source that provides completions for a type (e.g. enum) with well-known values.
2020
/// </summary>
21-
internal static ICompletionSource ForType(Type type)
21+
internal static Func<CompletionContext, IEnumerable<CompletionItem>> ForType(Type type)
2222
{
23-
return _completionSourcesByType.GetOrAdd(type, t => new CompletionSourceForType(t));
23+
return _completionSourcesByType.GetOrAdd(type, t => GetCompletionSourceForType(t));
2424
}
2525

26-
internal static ICompletionSource Empty { get; } = new AnonymousCompletionSource(static _ => Array.Empty<CompletionItem>());
27-
28-
private class CompletionSourceForType : ICompletionSource
26+
private static Func<CompletionContext, IEnumerable<CompletionItem>> GetCompletionSourceForType(Type type)
2927
{
30-
private readonly Type _type;
31-
private ICompletionSource? _innerCompletionSource;
28+
Type actualType = type.TryGetNullableType(out var nullableType) ? nullableType : type;
3229

33-
public CompletionSourceForType(Type type)
30+
if (actualType.IsEnum)
3431
{
35-
_type = type;
32+
return _ => Enum.GetNames(actualType).Select(n => new CompletionItem(n));
3633
}
37-
38-
public IEnumerable<CompletionItem> GetCompletions(CompletionContext context)
34+
else if (actualType == typeof(bool))
3935
{
40-
if (_innerCompletionSource is null)
36+
return static _ => new CompletionItem[]
4137
{
42-
_innerCompletionSource = CreateForType(_type);
43-
}
44-
45-
return _innerCompletionSource.GetCompletions(context);
38+
new(bool.TrueString),
39+
new(bool.FalseString)
40+
};
4641
}
4742

48-
private static ICompletionSource CreateForType(Type type)
49-
{
50-
if (type.TryGetNullableType(out var nullableType))
51-
{
52-
return CreateForType(nullableType);
53-
}
54-
55-
if (type.IsEnum)
56-
{
57-
return new AnonymousCompletionSource(_ => GetEnumNames());
58-
59-
IEnumerable<CompletionItem> GetEnumNames() => Enum.GetNames(type).Select(n => new CompletionItem(n));
60-
}
61-
62-
if (type == typeof(bool))
63-
{
64-
return new AnonymousCompletionSource(static _ => new CompletionItem[]
65-
{
66-
new(bool.TrueString),
67-
new(bool.FalseString)
68-
});
69-
}
70-
71-
return Empty;
72-
}
43+
return static _ => Array.Empty<CompletionItem>();
7344
}
7445
}
7546
}

0 commit comments

Comments
 (0)