mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Fix positional argument completion (#17796)
This commit is contained in:
@@ -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 ""
|
||||
|
||||
Reference in New Issue
Block a user