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 @@ -76,7 +76,7 @@ public static IEnumerable<CompletionResult> CompleteCommand(string commandName,
}

var helper = new PowerShellExecutionHelper(PowerShell.Create(RunspaceMode.CurrentRunspace));
return CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = helper }, moduleName, commandTypes);
return CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = helper, ExecutionContext = helper.CurrentPowerShell.GetContextFromTLS() }, moduleName, commandTypes);
}

internal static List<CompletionResult> CompleteCommand(CompletionContext context)
Expand Down Expand Up @@ -1325,7 +1325,7 @@ internal static List<CompletionResult> CompleteCommandArgument(CompletionContext
{
// For argument completion, we don't want to complete against pseudo commands that only work in the script workflow.
// The way to avoid that is to pass in a CompletionContext with RelatedAst = null
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = context.WordToComplete, Helper = context.Helper });
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = context.WordToComplete, Helper = context.Helper, ExecutionContext = context.ExecutionContext });
if (commandResults != null)
result.AddRange(commandResults);
}
Expand Down Expand Up @@ -2088,7 +2088,7 @@ private static void NativeCommandArgumentCompletion(
{
// For argument completion, we don't want to complete against pseudo commands that only work in the script workflow.
// The way to avoid that is to pass in a CompletionContext with RelatedAst = null
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = context.WordToComplete, Helper = context.Helper });
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = context.WordToComplete, Helper = context.Helper, ExecutionContext = context.ExecutionContext });
if (commandResults != null)
result.AddRange(commandResults);
}
Expand Down Expand Up @@ -2778,7 +2778,7 @@ private static void NativeCompletionGetCommand(string commandName, string module
RemoveLastNullCompletionResult(result);

// Available commands
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, moduleName);
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, moduleName);
if (commandResults != null)
result.AddRange(commandResults);

Expand All @@ -2788,7 +2788,7 @@ private static void NativeCompletionGetCommand(string commandName, string module
// ps1 files and directories. We only complete the files with .ps1 extension for Get-Command, because the -Syntax
// may only works on files with .ps1 extension
var ps1Extension = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { StringLiterals.PowerShellScriptFileExtension };
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, false, ps1Extension));
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, false, ps1Extension));
if (moduleFilesResults.Count > 0)
result.AddRange(moduleFilesResults);
}
Expand All @@ -2800,7 +2800,7 @@ private static void NativeCompletionGetCommand(string commandName, string module
RemoveLastNullCompletionResult(result);

var modules = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
var moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, true);
var moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, true);
if (moduleResults != null)
{
foreach (CompletionResult moduleResult in moduleResults)
Expand All @@ -2813,7 +2813,7 @@ private static void NativeCompletionGetCommand(string commandName, string module
}
}

moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, false);
moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, false);
if (moduleResults != null)
{
foreach (CompletionResult moduleResult in moduleResults)
Expand All @@ -2838,20 +2838,20 @@ private static void NativeCompletionGetHelpCommand(string commandName, string pa

// Available commands
const CommandTypes commandTypes = CommandTypes.Cmdlet | CommandTypes.Function | CommandTypes.Alias | CommandTypes.ExternalScript | CommandTypes.Workflow | CommandTypes.Configuration;
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, null, commandTypes);
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, null, commandTypes);
if (commandResults != null)
result.AddRange(commandResults);

// ps1 files and directories
var ps1Extension = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { StringLiterals.PowerShellScriptFileExtension };
var fileResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = context.Helper }, false, ps1Extension));
var fileResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, false, ps1Extension));
if (fileResults.Count > 0)
result.AddRange(fileResults);

if (isHelpRelated)
{
// Available topics
var helpTopicResults = CompleteHelpTopics(new CompletionContext { WordToComplete = commandName, Helper = context.Helper });
var helpTopicResults = CompleteHelpTopics(new CompletionContext { WordToComplete = commandName, Helper = context.Helper, ExecutionContext = context.ExecutionContext });
if (helpTopicResults != null)
result.AddRange(helpTopicResults);
}
Expand Down Expand Up @@ -3093,7 +3093,7 @@ private static void NativeCompletionModuleCommands(string assemblyOrModuleName,
StringLiterals.PowerShellCmdletizationFileExtension,
StringLiterals.WorkflowFileExtension
};
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper }, false, moduleExtensions));
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, false, moduleExtensions));
if (moduleFilesResults.Count > 0)
result.AddRange(moduleFilesResults);

Expand All @@ -3104,7 +3104,7 @@ private static void NativeCompletionModuleCommands(string assemblyOrModuleName,
}
}

var moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper }, loadedModulesOnly);
var moduleResults = CompleteModuleName(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, loadedModulesOnly);
if (moduleResults != null && moduleResults.Count > 0)
result.AddRange(moduleResults);

Expand All @@ -3115,7 +3115,7 @@ private static void NativeCompletionModuleCommands(string assemblyOrModuleName,
RemoveLastNullCompletionResult(result);

var moduleExtensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase) { ".dll" };
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper }, false, moduleExtensions));
var moduleFilesResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = assemblyOrModuleName, Helper = context.Helper, ExecutionContext = context.ExecutionContext }, false, moduleExtensions));
if (moduleFilesResults.Count > 0)
result.AddRange(moduleFilesResults);

Expand Down Expand Up @@ -3490,12 +3490,12 @@ private static void NativeCompletionAliasCommands(string commandName, string par
// Complete for the parameter Definition
// Available commands
const CommandTypes commandTypes = CommandTypes.Cmdlet | CommandTypes.Function | CommandTypes.ExternalScript | CommandTypes.Workflow | CommandTypes.Configuration;
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = powerShellExecutionHelper }, null, commandTypes);
var commandResults = CompleteCommand(new CompletionContext { WordToComplete = commandName, Helper = powerShellExecutionHelper, ExecutionContext = context.ExecutionContext }, null, commandTypes);
if (commandResults != null && commandResults.Count > 0)
result.AddRange(commandResults);

// The parameter Definition takes a file
var fileResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = powerShellExecutionHelper }));
var fileResults = new List<CompletionResult>(CompleteFilename(new CompletionContext { WordToComplete = commandName, Helper = powerShellExecutionHelper, ExecutionContext = context.ExecutionContext }));
if (fileResults.Count > 0)
result.AddRange(fileResults);
}
Expand Down Expand Up @@ -3597,8 +3597,7 @@ private static void NativeCompletionNewItemCommand(string itemTypeToComplete, st
return;
}

var powershell = context.Helper.CurrentPowerShell;
var executionContext = powershell.GetContextFromTLS();
var executionContext = context.ExecutionContext;

var boundArgs = GetBoundArgumentsAsHashtable(context);
var providedPath = boundArgs["Path"] as string ?? executionContext.SessionState.Path.CurrentLocation.Path;
Expand Down Expand Up @@ -4035,7 +4034,7 @@ public static IEnumerable<CompletionResult> CompleteFilename(string fileName)
}

var helper = new PowerShellExecutionHelper(PowerShell.Create(RunspaceMode.CurrentRunspace));
return CompleteFilename(new CompletionContext { WordToComplete = fileName, Helper = helper });
return CompleteFilename(new CompletionContext { WordToComplete = fileName, Helper = helper, ExecutionContext = helper.CurrentPowerShell.GetContextFromTLS() });
}

internal static IEnumerable<CompletionResult> CompleteFilename(CompletionContext context)
Expand Down Expand Up @@ -4484,7 +4483,7 @@ public static IEnumerable<CompletionResult> CompleteVariable(string variableName
}

var helper = new PowerShellExecutionHelper(PowerShell.Create(RunspaceMode.CurrentRunspace));
return CompleteVariable(new CompletionContext { WordToComplete = variableName, Helper = helper });
return CompleteVariable(new CompletionContext { WordToComplete = variableName, Helper = helper, ExecutionContext = helper.CurrentPowerShell.GetContextFromTLS() });
}

private static readonly string[] s_variableScopes = new string[] { "Global:", "Local:", "Script:", "Private:" };
Expand Down Expand Up @@ -5861,7 +5860,7 @@ public static IEnumerable<CompletionResult> CompleteType(string typeName)
: PowerShell.Create(RunspaceMode.CurrentRunspace);

var helper = new PowerShellExecutionHelper(powershell);
return CompleteType(new CompletionContext { WordToComplete = typeName, Helper = helper });
return CompleteType(new CompletionContext { WordToComplete = typeName, Helper = helper, ExecutionContext = helper.CurrentPowerShell.GetContextFromTLS() });
}

internal static List<CompletionResult> CompleteType(CompletionContext context, string prefix = "", string suffix = "")
Expand Down Expand Up @@ -5952,14 +5951,22 @@ private static string GetNamespaceToRemove(CompletionContext context, TypeComple
internal static List<CompletionResult> CompleteHelpTopics(CompletionContext context)
{
var results = new List<CompletionResult>();
var dirPath = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID) + "\\" + CultureInfo.CurrentCulture.Name;
var dirPath = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID) + Path.DirectorySeparatorChar + CultureInfo.CurrentCulture.Name;
var wordToComplete = context.WordToComplete + "*";
var topicPattern = WildcardPattern.Get("about_*.help.txt", WildcardOptions.IgnoreCase);
string[] files = null;
List<string> files = new List<string>();

try
{
files = Directory.GetFiles(dirPath, wordToComplete);
var wildcardPattern = WildcardPattern.Get(wordToComplete, WildcardOptions.IgnoreCase);

foreach(var file in Directory.GetFiles(dirPath))
{
if(wildcardPattern.IsMatch(Path.GetFileName(file)))
{
files.Add(file);
}
}
}
catch (Exception)
{
Expand Down
23 changes: 1 addition & 22 deletions src/System.Management.Automation/help/MUIFileSearcher.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ private static Collection<String> NormalizeSearchPaths(string target, Collection
}

// step 3: locate the file in the default PowerShell installation directory.
string defaultPSPath = GetMshDefaultInstallationPath();
string defaultPSPath = Utils.GetApplicationBase(Utils.DefaultPowerShellShellID);
if (defaultPSPath != null &&
!result.Contains(defaultPSPath) &&
Directory.Exists(defaultPSPath))
Expand All @@ -294,27 +294,6 @@ private static Collection<String> NormalizeSearchPaths(string target, Collection
return result;
}

/// <summary>
/// Helper method which returns the default monad installation path based on ShellID
/// registry key.
/// </summary>
/// <returns>string representing path.</returns>
/// <remarks>
/// If ShellID is not defined or Path property is not defined returns null.
/// </remarks>
private static string GetMshDefaultInstallationPath()
{
string returnValue = CommandDiscovery.GetShellPathFromRegistry(Utils.DefaultPowerShellShellID);

if (returnValue != null)
{
returnValue = Path.GetDirectoryName(returnValue);
}

// returnValue can be null.
return returnValue;
}

#endregion

#region Static API's
Expand Down
15 changes: 15 additions & 0 deletions test/powershell/Host/TabCompletion/TabCompletion.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,21 @@ Describe "TabCompletion" -Tags CI {
$res.CompletionMatches[0].CompletionText | Should Be 'namespace'
}

It 'Should complete about help topic' {

$aboutHelpPath = Join-Path $PSHOME (Get-Culture).Name

## If help content does not exist, tab completion will not work. So update it first.
if(-not (Test-Path (Join-Path $aboutHelpPath "about_Splatting.help.txt")))
{
Update-Help -Force -ErrorAction SilentlyContinue
}

$res = TabExpansion2 -inputScript 'get-help about_spla' -cursorColumn 'get-help about_spla'.Length
$res.CompletionMatches.Count | Should Be 1
$res.CompletionMatches[0].CompletionText | Should BeExactly 'about_Splatting'
}

Context NativeCommand {
BeforeAll {
$nativeCommand = (Get-Command -CommandType Application -TotalCount 1).Name
Expand Down
6 changes: 6 additions & 0 deletions test/powershell/engine/Help/HelpSystem.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -200,6 +200,12 @@ Describe "Validate about_help.txt under culture specific folder works" -Tags @('
$help.count | Should Be 1
$help | Should BeExactly "Hello"
}

It "Get-Help for about_Variable should return only one help object" {

$help = Get-Help about_Variables
$help.count | Should Be 1
}
}

Describe "Get-Help should find help info within help files" -Tags @('CI', 'RequireAdminOnWindows') {
Expand Down