diff --git a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs index b5d3eb0cb42..8a010379110 100644 --- a/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs +++ b/src/System.Management.Automation/engine/CommandCompletion/CompletionCompleters.cs @@ -499,11 +499,16 @@ internal static List CompleteModuleName(CompletionContext cont nestedModulesToFilterOut = new(currentModule.NestedModules); } + var completedModules = new HashSet(StringComparer.OrdinalIgnoreCase); foreach (PSObject item in psObjects) { var moduleInfo = (PSModuleInfo)item.BaseObject; var completionText = moduleInfo.Name; - var listItemText = completionText; + if (!completedModules.Add(completionText)) + { + continue; + } + if (shortNameSearch && completionText.Contains('.') && !shortNamePattern.IsMatch(completionText.Substring(completionText.LastIndexOf('.') + 1)) @@ -526,7 +531,7 @@ internal static List CompleteModuleName(CompletionContext cont completionText = CompletionHelpers.QuoteCompletionText(completionText, quote); - result.Add(new CompletionResult(completionText, listItemText, CompletionResultType.ParameterValue, toolTip)); + result.Add(new CompletionResult(completionText, listItemText: moduleInfo.Name, CompletionResultType.ParameterValue, toolTip)); } } diff --git a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 index f30e54438b6..e088d368011 100644 --- a/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 +++ b/test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1 @@ -36,13 +36,13 @@ Describe "TabCompletion" -Tags CI { It 'Should not include duplicate command results' { $OldModulePath = $env:PSModulePath $tempDir = Join-Path -Path $TestDrive -ChildPath "TempPsModuleDir" + $ModuleDirs = @( + Join-Path $tempDir "TestModule1\1.0" + Join-Path $tempDir "TestModule1\1.1" + Join-Path $tempDir "TestModule2\1.0" + ) try { - $ModuleDirs = @( - Join-Path $tempDir "TestModule1\1.0" - Join-Path $tempDir "TestModule1\1.1" - Join-Path $tempDir "TestModule2\1.0" - ) foreach ($Dir in $ModuleDirs) { $NewDir = New-Item -Path $Dir -ItemType Directory -Force @@ -61,6 +61,36 @@ Describe "TabCompletion" -Tags CI { finally { $env:PSModulePath = $OldModulePath + Remove-Item -LiteralPath $ModuleDirs -Recurse -Force + } + } + + It 'Should not include duplicate module results' { + $OldModulePath = $env:PSModulePath + $tempDir = Join-Path -Path $TestDrive -ChildPath "TempPsModuleDir" + try + { + $ModuleDirs = @( + Join-Path $tempDir "TestModule1\1.0" + Join-Path $tempDir "TestModule1\1.1" + ) + foreach ($Dir in $ModuleDirs) + { + $NewDir = New-Item -Path $Dir -ItemType Directory -Force + $ModuleName = $NewDir.Parent.Name + Set-Content -Value 'MyTestFunction{}' -LiteralPath "$($NewDir.FullName)\$ModuleName.psm1" + New-ModuleManifest -Path "$($NewDir.FullName)\$ModuleName.psd1" -RootModule "$ModuleName.psm1" -FunctionsToExport "MyTestFunction" -ModuleVersion $NewDir.Name + } + + $env:PSModulePath += [System.IO.Path]::PathSeparator + $tempDir + $Res = TabExpansion2 -inputScript 'Import-Module -Name TestModule' + $Res.CompletionMatches.Count | Should -Be 1 + $Res.CompletionMatches[0].CompletionText | Should -Be TestModule1 + } + finally + { + $env:PSModulePath = $OldModulePath + Remove-Item -LiteralPath $ModuleDirs -Recurse -Force } }