Prioritize ValidateSet completions over Enums for parameters (#15257)

This commit is contained in:
MartinGC94
2022-03-23 12:38:05 -07:00
committed by GitHub
parent b3632eda46
commit 123373e425
2 changed files with 80 additions and 68 deletions
@@ -1658,9 +1658,9 @@ namespace System.Management.Automation
/// </summary>
/// <remarks>
/// If the argument completion falls into these pre-defined cases:
/// 1. The matching parameter is of type Enum
/// 2. The matching parameter is of type SwitchParameter
/// 3. The matching parameter is declared with ValidateSetAttribute
/// 1. The matching parameter is declared with ValidateSetAttribute
/// 2. The matching parameter is of type Enum
/// 3. The matching parameter is of type SwitchParameter
/// 4. Falls into the native command argument completion
/// a null instance of CompletionResult is added to the end of the
/// "result" list, to indicate that this particular argument completion
@@ -1683,6 +1683,74 @@ namespace System.Management.Automation
parameterType = parameterType.GetElementType();
}
foreach (ValidateArgumentsAttribute att in parameter.Parameter.ValidationAttributes)
{
if (att is ValidateSetAttribute setAtt)
{
RemoveLastNullCompletionResult(result);
string wordToComplete = context.WordToComplete;
string quote = HandleDoubleAndSingleQuote(ref wordToComplete);
var pattern = WildcardPattern.Get(wordToComplete + "*", WildcardOptions.IgnoreCase);
var setList = new List<string>();
foreach (string value in setAtt.ValidValues)
{
if (value == string.Empty)
{
continue;
}
if (wordToComplete.Equals(value, StringComparison.OrdinalIgnoreCase))
{
string completionText = quote == string.Empty ? value : quote + value + quote;
fullMatch = new CompletionResult(completionText, value, CompletionResultType.ParameterValue, value);
continue;
}
if (pattern.IsMatch(value))
{
setList.Add(value);
}
}
if (fullMatch != null)
{
result.Add(fullMatch);
}
setList.Sort();
foreach (string entry in setList)
{
string realEntry = entry;
string completionText = entry;
if (quote == string.Empty)
{
if (CompletionRequiresQuotes(entry, false))
{
realEntry = CodeGeneration.EscapeSingleQuotedStringContent(entry);
completionText = "'" + realEntry + "'";
}
}
else
{
if (quote.Equals("'", StringComparison.OrdinalIgnoreCase))
{
realEntry = CodeGeneration.EscapeSingleQuotedStringContent(entry);
}
completionText = quote + realEntry + quote;
}
result.Add(new CompletionResult(completionText, entry, CompletionResultType.ParameterValue, entry));
}
result.Add(CompletionResult.Null);
return;
}
}
if (parameterType.IsEnum)
{
RemoveLastNullCompletionResult(result);
@@ -1740,71 +1808,6 @@ namespace System.Management.Automation
return;
}
foreach (ValidateArgumentsAttribute att in parameter.Parameter.ValidationAttributes)
{
if (att is ValidateSetAttribute setAtt)
{
RemoveLastNullCompletionResult(result);
string wordToComplete = context.WordToComplete;
string quote = HandleDoubleAndSingleQuote(ref wordToComplete);
var pattern = WildcardPattern.Get(wordToComplete + "*", WildcardOptions.IgnoreCase);
var setList = new List<string>();
foreach (string value in setAtt.ValidValues)
{
if (value == string.Empty) { continue; }
if (wordToComplete.Equals(value, StringComparison.OrdinalIgnoreCase))
{
string completionText = quote == string.Empty ? value : quote + value + quote;
fullMatch = new CompletionResult(completionText, value, CompletionResultType.ParameterValue, value);
continue;
}
if (pattern.IsMatch(value))
{
setList.Add(value);
}
}
if (fullMatch != null)
{
result.Add(fullMatch);
}
setList.Sort();
foreach (string entry in setList)
{
string realEntry = entry;
string completionText = entry;
if (quote == string.Empty)
{
if (CompletionRequiresQuotes(entry, false))
{
realEntry = CodeGeneration.EscapeSingleQuotedStringContent(entry);
completionText = "'" + realEntry + "'";
}
}
else
{
if (quote.Equals("'", StringComparison.OrdinalIgnoreCase))
{
realEntry = CodeGeneration.EscapeSingleQuotedStringContent(entry);
}
completionText = quote + realEntry + quote;
}
result.Add(new CompletionResult(completionText, entry, CompletionResultType.ParameterValue, entry));
}
result.Add(CompletionResult.Null);
return;
}
}
NativeCommandArgumentCompletion(commandName, parameter.Parameter, result, commandAst, context, boundArguments);
}
@@ -1001,6 +1001,15 @@ Describe "TabCompletion" -Tags CI {
$res.CompletionMatches[1].CompletionText | Should -BeExactly 'dog'
}
It "Tab completion for validateSet attribute takes precedence over enums" {
function foo { param([ValidateSet('DarkBlue','DarkCyan')][ConsoleColor]$p) }
$inputStr = "foo "
$res = TabExpansion2 -inputScript $inputStr -cursorColumn $inputStr.Length
$res.CompletionMatches | Should -HaveCount 2
$res.CompletionMatches[0].CompletionText | Should -BeExactly 'DarkBlue'
$res.CompletionMatches[1].CompletionText | Should -BeExactly 'DarkCyan'
}
It "Tab completion for ArgumentCompleter when AST is passed to CompleteInput" {
$scriptBl = {
function Test-Completion {