Fix positional argument completion (#17796)

This commit is contained in:
MartinGC94
2022-08-22 15:17:55 -07:00
committed by GitHub
parent 2bbb4a6650
commit 99c757ff3e
2 changed files with 52 additions and 16 deletions
@@ -1586,13 +1586,20 @@ namespace System.Management.Automation
(defaultParameterSetFlag & validParameterSetFlags) != 0;
MergedCompiledCommandParameter positionalParam = null;
MergedCompiledCommandParameter bestMatchParam = null;
ParameterSetSpecificMetadata bestMatchSet = null;
// Finds the parameter with the position closest to the specified position
foreach (MergedCompiledCommandParameter param in parameters)
{
bool isInParameterSet = (param.Parameter.ParameterSetFlags & validParameterSetFlags) != 0 || param.Parameter.IsInAllSets;
if (!isInParameterSet)
{
continue;
}
var parameterSetDataCollection = param.Parameter.GetMatchingParameterSetData(validParameterSetFlags);
foreach (ParameterSetSpecificMetadata parameterSetData in parameterSetDataCollection)
{
// in the first pass, we skip the remaining argument ones
@@ -1604,35 +1611,43 @@ namespace System.Management.Automation
// Check the position
int positionInParameterSet = parameterSetData.Position;
if (positionInParameterSet == int.MinValue || positionInParameterSet != position)
if (positionInParameterSet < position)
{
// The parameter is not positional, or its position is not what we want
// The parameter is not positional (position == int.MinValue), or its position is lower than what we want.
continue;
}
if (isDefaultParameterSetValid)
if (bestMatchSet is null || bestMatchSet.Position > positionInParameterSet)
{
if (parameterSetData.ParameterSetFlag == defaultParameterSetFlag)
bestMatchParam = param;
bestMatchSet = parameterSetData;
if (positionInParameterSet == position)
{
ProcessParameter(commandName, commandAst, context, result, param, boundArguments);
isProcessedAsPositional = result.Count > 0;
break;
}
else
{
positionalParam ??= param;
}
}
}
}
if (bestMatchParam is not null)
{
if (isDefaultParameterSetValid)
{
if (bestMatchSet.ParameterSetFlag == defaultParameterSetFlag)
{
ProcessParameter(commandName, commandAst, context, result, bestMatchParam, boundArguments);
isProcessedAsPositional = result.Count > 0;
}
else
{
isProcessedAsPositional = true;
ProcessParameter(commandName, commandAst, context, result, param, boundArguments);
break;
positionalParam ??= bestMatchParam;
}
}
if (isProcessedAsPositional)
break;
else
{
isProcessedAsPositional = true;
ProcessParameter(commandName, commandAst, context, result, bestMatchParam, boundArguments);
}
}
if (!isProcessedAsPositional && positionalParam != null)
@@ -766,6 +766,27 @@ ConstructorTestClass(int i, bool b)
$res.CompletionMatches.CompletionText | Should -Contain "-Path"
}
it 'Should find the closest positional parameter match' {
$TestString = @'
function Verb-Noun
{
Param
(
[Parameter(Position = 0)]
[string]
$Param1,
[Parameter(Position = 1)]
[System.Management.Automation.ActionPreference]
$Param2
)
}
Verb-Noun -Param1 Hello ^
'@
$CursorIndex = $TestString.IndexOf('^')
$res = TabExpansion2 -inputScript $TestString.Remove($CursorIndex, 1) -cursorColumn $CursorIndex
$res.CompletionMatches[0].CompletionText | Should -Be "Break"
}
Context "Script name completion" {
BeforeAll {
Setup -f 'install-powershell.ps1' -Content ""