Adding `IArgumentCompleterFactory` for parameterized `ArgumentComplet… · PowerShell/PowerShell@be7d366 · GitHub
Skip to content

Commit be7d366

Browse files
authored
Adding IArgumentCompleterFactory for parameterized ArgumentCompleters (#12605)
1 parent 5d0dadf commit be7d366

3 files changed

Lines changed: 163 additions & 12 deletions

File tree

‎src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs‎

Lines changed: 9 additions & 11 deletions

‎src/System.Management.Automation/engine/CommandCompletion/ExtensibleCompletion.cs‎

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,19 +40,40 @@ public ArgumentCompleterAttribute(Type type)
4040
Type = type;
4141
}
4242

43+
/// <summary>
44+
/// Initializes a new instance of the <see cref="ArgumentCompleterAttribute"/> class.
45+
/// This constructor is used by derived attributes implementing <see cref="IArgumentCompleterFactory"/>.
46+
/// </summary>
47+
protected ArgumentCompleterAttribute()
48+
{
49+
if (this is not IArgumentCompleterFactory)
50+
{
51+
throw PSTraceSource.NewInvalidOperationException();
52+
}
53+
}
54+
4355
/// <summary>
4456
/// This constructor is used primarily via PowerShell scripts.
4557
/// </summary>
4658
/// <param name="scriptBlock"></param>
4759
public ArgumentCompleterAttribute(ScriptBlock scriptBlock)
4860
{
49-
if (scriptBlock == null)
61+
if (scriptBlock is null)
5062
{
5163
throw PSTraceSource.NewArgumentNullException(nameof(scriptBlock));
5264
}
5365

5466
ScriptBlock = scriptBlock;
5567
}
68+
69+
internal IArgumentCompleter CreateArgumentCompleter()
70+
{
71+
return Type != null
72+
? Activator.CreateInstance(Type) as IArgumentCompleter
73+
: this is IArgumentCompleterFactory factory
74+
? factory.Create()
75+
: null;
76+
}
5677
}
5778

5879
/// <summary>
@@ -85,6 +106,67 @@ IEnumerable<CompletionResult> CompleteArgument(
85106
}
86107
#nullable restore
87108

109+
/// <summary>
110+
/// Creates a new argument completer.
111+
/// </summary>
112+
/// <para>
113+
/// If an attribute that derives from <see cref="ArgumentCompleterAttribute"/> implements this interface,
114+
/// it will be used to create the <see cref="IArgumentCompleter"/>, thus giving a way to parameterize a completer.
115+
/// The derived attribute can have properties or constructor arguments that are used when creating the completer.
116+
/// </para>
117+
/// <example>
118+
/// This example shows the intended usage of <see cref="IArgumentCompleterFactory"/> to pass arguments to an argument completer.
119+
/// <code>
120+
/// public class NumberCompleterAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory {
121+
/// private readonly int _from;
122+
/// private readonly int _to;
123+
///
124+
/// public NumberCompleterAttribute(int from, int to){
125+
/// _from = from;
126+
/// _to = to;
127+
/// }
128+
///
129+
/// // use the attribute parameters to create a parameterized completer
130+
/// IArgumentCompleter Create() => new NumberCompleter(_from, _to);
131+
/// }
132+
///
133+
/// class NumberCompleter : IArgumentCompleter {
134+
/// private readonly int _from;
135+
/// private readonly int _to;
136+
///
137+
/// public NumberCompleter(int from, int to){
138+
/// _from = from;
139+
/// _to = to;
140+
/// }
141+
///
142+
/// IEnumerable{CompletionResult} CompleteArgument(string commandName, string parameterName, string wordToComplete,
143+
/// CommandAst commandAst, IDictionary fakeBoundParameters) {
144+
/// for(int i = _from; i &lt; _to; i++) {
145+
/// yield return new CompletionResult(i.ToString());
146+
/// }
147+
/// }
148+
/// }
149+
/// </code>
150+
/// </example>
151+
public interface IArgumentCompleterFactory
152+
{
153+
/// <summary>
154+
/// Creates an instance of a class implementing the <see cref="IArgumentCompleter"/> interface.
155+
/// </summary>
156+
/// <returns>An IArgumentCompleter instance.</returns>
157+
IArgumentCompleter Create();
158+
}
159+
160+
/// <summary>
161+
/// Base class for parameterized argument completer attributes.
162+
/// </summary>
163+
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
164+
public abstract class ArgumentCompleterFactoryAttribute : ArgumentCompleterAttribute, IArgumentCompleterFactory
165+
{
166+
/// <inheritdoc />
167+
public abstract IArgumentCompleter Create();
168+
}
169+
88170
/// <summary>
89171
/// </summary>
90172
[Cmdlet(VerbsLifecycle.Register, "ArgumentCompleter", HelpUri = "https://go.microsoft.com/fwlink/?LinkId=528576")]

‎test/powershell/Language/Parser/ExtensibleCompletion.Tests.ps1‎

Lines changed: 71 additions & 0 deletions

0 commit comments

Comments
 (0)