Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -708,7 +708,18 @@ private static List<CompletionResult> GetParameterCompletionResults(string param
break;
}

Diagnostics.Assert(matchedParameterName != null, "we should find matchedParameterName from the BoundArguments");
if (matchedParameterName is null)
{
// The pseudo binder has skipped a parameter
// This will happen when completing parameters for commands with dynamic parameters.
result = GetParameterCompletionResults(
parameterName,
bindingInfo.ValidParameterSetsFlags,
bindingInfo.UnboundParameters,
withColon);
return result;
}

MergedCompiledCommandParameter param = bindingInfo.BoundParameters[matchedParameterName];

WildcardPattern pattern = WildcardPattern.Get(parameterName + "*", WildcardOptions.IgnoreCase);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -982,7 +982,7 @@ internal PseudoBindingInfo DoPseudoParameterBinding(CommandAst command, Type pip
executionContext.LanguageMode = PSLanguageMode.ConstrainedLanguage;
}

_bindingEffective = PrepareCommandElements(executionContext);
_bindingEffective = PrepareCommandElements(executionContext, paramAstAtCursor);
}
finally
{
Expand Down Expand Up @@ -1189,7 +1189,7 @@ private void InitializeMembers()
_duplicateParameters.Clear();
}

private bool PrepareCommandElements(ExecutionContext context)
private bool PrepareCommandElements(ExecutionContext context, CommandParameterAst paramAtCursor)
{
int commandIndex = 0;
bool dotSource = _commandAst.InvocationOperator == TokenKind.Dot;
Expand All @@ -1216,6 +1216,13 @@ private bool PrepareCommandElements(ExecutionContext context)
// Pre-processing the arguments -- command arguments
for (commandIndex++; commandIndex < _commandElements.Count; commandIndex++)
{
if (implementsDynamicParameters && _commandElements[commandIndex] == paramAtCursor)
{
// Commands with dynamic parameters will try to bind the command elements.
// A partially complete parameter will most likely cause a binding error and negatively affect the results.
continue;
}

var parameter = _commandElements[commandIndex] as CommandParameterAst;
if (parameter != null)
{
Expand Down
13 changes: 13 additions & 0 deletions test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -992,6 +992,19 @@ class InheritedClassTest : System.Attribute
$res.CompletionMatches.CompletionText | Should -Contain '-ProgressAction'
}

It 'Should complete dynamic parameters with partial input' {
# See issue: #19498
try
{
Push-Location function:
$res = TabExpansion2 -inputScript 'Get-ChildItem -LiteralPath $PSHOME -Fi'
$res.CompletionMatches[1].CompletionText | Should -Be '-File'
}
finally
{
Pop-Location
}
}
it 'Should complete enum class members for Enums in script text' {
$res = TabExpansion2 -inputScript 'enum Test1 {Val1};([Test1]"").'
$res.CompletionMatches.CompletionText[0] | Should -Be 'value__'
Expand Down