Skip to content

Commit 905cb0b

Browse files
adamsitnikjonsequitur
authored andcommitted
replace ICompletionSource with a Func, fixes #1928
1 parent 8b66431 commit 905cb0b

File tree

8 files changed

+35
-135
lines changed

8 files changed

+35
-135
lines changed

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

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
System.CommandLine
2-
public abstract class Argument : Symbol, System.CommandLine.Binding.IValueDescriptor, System.CommandLine.Completions.ICompletionSource
2+
public abstract class Argument : Symbol, System.CommandLine.Binding.IValueDescriptor
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; }
@@ -12,7 +12,7 @@ System.CommandLine
1212
public System.Void SetDefaultValueFactory(System.Func<System.Object> defaultValueFactory)
1313
public System.Void SetDefaultValueFactory(System.Func<System.CommandLine.Parsing.ArgumentResult,System.Object> defaultValueFactory)
1414
public System.String ToString()
15-
public class Argument<T> : Argument, IValueDescriptor<T>, System.CommandLine.Binding.IValueDescriptor, System.CommandLine.Completions.ICompletionSource
15+
public class Argument<T> : Argument, IValueDescriptor<T>, System.CommandLine.Binding.IValueDescriptor
1616
.ctor()
1717
.ctor(System.String name, System.String description = null)
1818
.ctor(System.String name, Func<T> defaultValueFactory, System.String description = null)
@@ -45,7 +45,7 @@ System.CommandLine
4545
public static TArgument LegalFilePathsOnly<TArgument>(this TArgument argument)
4646
public static ParseResult Parse(this Argument argument, System.String commandLine)
4747
public static ParseResult Parse(this Argument argument, System.String[] args)
48-
public class Command : IdentifierSymbol, System.Collections.Generic.IEnumerable<Symbol>, System.Collections.IEnumerable, System.CommandLine.Completions.ICompletionSource
48+
public class Command : IdentifierSymbol, System.Collections.Generic.IEnumerable<Symbol>, System.Collections.IEnumerable
4949
.ctor(System.String name, System.String description = null)
5050
public System.Collections.Generic.IReadOnlyList<Argument> Arguments { get; }
5151
public System.Collections.Generic.IEnumerable<Symbol> Children { 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)
@@ -145,7 +144,7 @@ System.CommandLine
145144
public System.Int32 Invoke(System.CommandLine.Invocation.InvocationContext context)
146145
public System.Threading.Tasks.Task<System.Int32> InvokeAsync(System.CommandLine.Invocation.InvocationContext context)
147146
public interface IConsole : System.CommandLine.IO.IStandardError, System.CommandLine.IO.IStandardIn, System.CommandLine.IO.IStandardOut
148-
public abstract class IdentifierSymbol : Symbol, System.CommandLine.Completions.ICompletionSource
147+
public abstract class IdentifierSymbol : Symbol
149148
public System.Collections.Generic.IReadOnlyCollection<System.String> Aliases { get; }
150149
public System.String Name { get; set; }
151150
public System.Void AddAlias(System.String alias)
@@ -188,7 +187,7 @@ System.CommandLine
188187
public System.String UnrecognizedCommandOrArgument(System.String arg)
189188
public System.String VersionOptionCannotBeCombinedWithOtherArguments(System.String optionAlias)
190189
public System.String VersionOptionDescription()
191-
public abstract class Option : IdentifierSymbol, System.CommandLine.Binding.IValueDescriptor, System.CommandLine.Completions.ICompletionSource
190+
public abstract class Option : IdentifierSymbol, System.CommandLine.Binding.IValueDescriptor
192191
public System.Boolean AllowMultipleArgumentsPerToken { get; set; }
193192
public System.String ArgumentHelpName { get; set; }
194193
public ArgumentArity Arity { get; set; }
@@ -199,7 +198,7 @@ System.CommandLine
199198
public System.Boolean HasAliasIgnoringPrefix(System.String alias)
200199
public System.Void SetDefaultValue(System.Object value)
201200
public System.Void SetDefaultValueFactory(System.Func<System.Object> defaultValueFactory)
202-
public class Option<T> : Option, IValueDescriptor<T>, System.CommandLine.Binding.IValueDescriptor, System.CommandLine.Completions.ICompletionSource
201+
public class Option<T> : Option, IValueDescriptor<T>, System.CommandLine.Binding.IValueDescriptor
203202
.ctor(System.String name, System.String description = null)
204203
.ctor(System.String[] aliases, System.String description = null)
205204
.ctor(System.String name, Func<System.CommandLine.Parsing.ArgumentResult,T> parseArgument, System.Boolean isDefault = False, System.String description = null)
@@ -239,11 +238,11 @@ System.CommandLine
239238
public T GetValue<T>(Argument<T> argument)
240239
public T GetValue<T>(Option<T> option)
241240
public System.String ToString()
242-
public class RootCommand : Command, System.Collections.Generic.IEnumerable<Symbol>, System.Collections.IEnumerable, System.CommandLine.Completions.ICompletionSource
241+
public class RootCommand : Command, System.Collections.Generic.IEnumerable<Symbol>, System.Collections.IEnumerable
243242
public static System.String ExecutableName { get; }
244243
public static System.String ExecutablePath { get; }
245244
.ctor(System.String description = )
246-
public abstract class Symbol, System.CommandLine.Completions.ICompletionSource
245+
public abstract class Symbol
247246
public System.String Description { get; set; }
248247
public System.Boolean IsHidden { get; set; }
249248
public System.String Name { get; set; }
@@ -289,8 +288,6 @@ System.CommandLine.Completions
289288
public System.Boolean Equals(System.Object obj)
290289
public System.Int32 GetHashCode()
291290
public System.String ToString()
292-
public interface ICompletionSource
293-
public System.Collections.Generic.IEnumerable<CompletionItem> GetCompletions(CompletionContext context)
294291
public class TextCompletionContext : CompletionContext
295292
public System.String CommandLineText { get; }
296293
public System.Int32 CursorPosition { get; }

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
}

src/System.CommandLine/Completions/ICompletionSource.cs

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

src/System.CommandLine/ParseResult.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -220,8 +220,8 @@ public IEnumerable<CompletionItem> GetCompletions(
220220
}
221221

222222
var completions =
223-
currentSymbol is ICompletionSource currentCompletionSource
224-
? currentCompletionSource.GetCompletions(context)
223+
currentSymbol is not null
224+
? currentSymbol.GetCompletions(context)
225225
: Array.Empty<CompletionItem>();
226226

227227
completions =

src/System.CommandLine/Symbol.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ namespace System.CommandLine
99
/// <summary>
1010
/// Defines a named symbol that resides in a hierarchy with parent and child symbols.
1111
/// </summary>
12-
public abstract class Symbol : ICompletionSource
12+
public abstract class Symbol
1313
{
1414
private string? _name;
1515
private ParentNode? _firstParent;

0 commit comments

Comments
 (0)