mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Use parameter HelpMessage for tool tip in parameter completion (#25108)
Use the help message on the parameter in the completion tool tip to provide better completion help. This can be utilized by other tools to provide more context for a parameter outside of the current type and parameter name which is quite minimal.
This commit is contained in:
@@ -670,6 +670,11 @@ namespace System.Management.Automation
|
||||
{
|
||||
Diagnostics.Assert(bindingInfo.InfoType.Equals(PseudoBindingInfoType.PseudoBindingSucceed), "The pseudo binding should succeed");
|
||||
List<CompletionResult> result = new List<CompletionResult>();
|
||||
Assembly commandAssembly = null;
|
||||
if (bindingInfo.CommandInfo is CmdletInfo cmdletInfo)
|
||||
{
|
||||
commandAssembly = cmdletInfo.CommandMetadata.CommandType.Assembly;
|
||||
}
|
||||
|
||||
if (parameterName == string.Empty)
|
||||
{
|
||||
@@ -677,7 +682,8 @@ namespace System.Management.Automation
|
||||
parameterName,
|
||||
bindingInfo.ValidParameterSetsFlags,
|
||||
bindingInfo.UnboundParameters,
|
||||
withColon);
|
||||
withColon,
|
||||
commandAssembly);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -699,7 +705,8 @@ namespace System.Management.Automation
|
||||
parameterName,
|
||||
bindingInfo.ValidParameterSetsFlags,
|
||||
bindingInfo.UnboundParameters,
|
||||
withColon);
|
||||
withColon,
|
||||
commandAssembly);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -714,7 +721,8 @@ namespace System.Management.Automation
|
||||
parameterName,
|
||||
bindingInfo.ValidParameterSetsFlags,
|
||||
bindingInfo.BoundParameters.Values,
|
||||
withColon);
|
||||
withColon,
|
||||
commandAssembly);
|
||||
}
|
||||
|
||||
return result;
|
||||
@@ -778,7 +786,8 @@ namespace System.Management.Automation
|
||||
parameterName,
|
||||
bindingInfo.ValidParameterSetsFlags,
|
||||
bindingInfo.UnboundParameters,
|
||||
withColon);
|
||||
withColon,
|
||||
commandAssembly);
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -786,11 +795,25 @@ namespace System.Management.Automation
|
||||
|
||||
WildcardPattern pattern = WildcardPattern.Get(parameterName + "*", WildcardOptions.IgnoreCase);
|
||||
string parameterType = "[" + ToStringCodeMethods.Type(param.Parameter.Type, dropNamespaces: true) + "] ";
|
||||
|
||||
string helpMessage = string.Empty;
|
||||
if (param.Parameter.CompiledAttributes is not null)
|
||||
{
|
||||
foreach (Attribute attr in param.Parameter.CompiledAttributes)
|
||||
{
|
||||
if (attr is ParameterAttribute pattr && TryGetParameterHelpMessage(pattr, commandAssembly, out string attrHelpMessage))
|
||||
{
|
||||
helpMessage = $" - {attrHelpMessage}";
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string colonSuffix = withColon ? ":" : string.Empty;
|
||||
if (pattern.IsMatch(matchedParameterName))
|
||||
{
|
||||
string completionText = "-" + matchedParameterName + colonSuffix;
|
||||
string tooltip = parameterType + matchedParameterName;
|
||||
string completionText = $"-{matchedParameterName}{colonSuffix}";
|
||||
string tooltip = $"{parameterType}{matchedParameterName}{helpMessage}";
|
||||
result.Add(new CompletionResult(completionText, matchedParameterName, CompletionResultType.ParameterName, tooltip));
|
||||
}
|
||||
else
|
||||
@@ -804,7 +827,7 @@ namespace System.Management.Automation
|
||||
$"-{alias}{colonSuffix}",
|
||||
alias,
|
||||
CompletionResultType.ParameterName,
|
||||
parameterType + alias));
|
||||
$"{parameterType}{alias}{helpMessage}"));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -812,6 +835,44 @@ namespace System.Management.Automation
|
||||
return result;
|
||||
}
|
||||
|
||||
#nullable enable
|
||||
/// <summary>
|
||||
/// Try and get the help message text for the parameter attribute.
|
||||
/// </summary>
|
||||
/// <param name="attr">The attribute to check for the help message.</param>
|
||||
/// <param name="assembly">The assembly to lookup resources messages, this should be the assembly the cmdlet is defined in.</param>
|
||||
/// <param name="message">The help message if it was found otherwise null.</param>
|
||||
/// <returns>True if the help message was set or false if not.></returns>
|
||||
private static bool TryGetParameterHelpMessage(
|
||||
ParameterAttribute attr,
|
||||
Assembly? assembly,
|
||||
[NotNullWhen(true)] out string? message)
|
||||
{
|
||||
message = null;
|
||||
|
||||
if (attr.HelpMessage is not null)
|
||||
{
|
||||
message = attr.HelpMessage;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (assembly is null || attr.HelpMessageBaseName is null || attr.HelpMessageResourceId is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
message = ResourceManagerCache.GetResourceString(assembly, attr.HelpMessageBaseName, attr.HelpMessageResourceId);
|
||||
return message is not null;
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
#nullable disable
|
||||
|
||||
/// <summary>
|
||||
/// Get the parameter completion results by using the given valid parameter sets and available parameters.
|
||||
/// </summary>
|
||||
@@ -819,12 +880,14 @@ namespace System.Management.Automation
|
||||
/// <param name="validParameterSetFlags"></param>
|
||||
/// <param name="parameters"></param>
|
||||
/// <param name="withColon"></param>
|
||||
/// <param name="commandAssembly">Optional assembly used to lookup parameter help messages.</param>
|
||||
/// <returns></returns>
|
||||
private static List<CompletionResult> GetParameterCompletionResults(
|
||||
string parameterName,
|
||||
uint validParameterSetFlags,
|
||||
IEnumerable<MergedCompiledCommandParameter> parameters,
|
||||
bool withColon)
|
||||
bool withColon,
|
||||
Assembly commandAssembly = null)
|
||||
{
|
||||
var result = new List<CompletionResult>();
|
||||
var commonParamResult = new List<CompletionResult>();
|
||||
@@ -840,6 +903,7 @@ namespace System.Management.Automation
|
||||
|
||||
string name = param.Parameter.Name;
|
||||
string type = "[" + ToStringCodeMethods.Type(param.Parameter.Type, dropNamespaces: true) + "] ";
|
||||
string helpMessage = null;
|
||||
bool isCommonParameter = Cmdlet.CommonParameters.Contains(name, StringComparer.OrdinalIgnoreCase);
|
||||
List<CompletionResult> listInUse = isCommonParameter ? commonParamResult : result;
|
||||
|
||||
@@ -855,20 +919,27 @@ namespace System.Management.Automation
|
||||
{
|
||||
foreach (var attr in compiledAttributes)
|
||||
{
|
||||
var pattr = attr as ParameterAttribute;
|
||||
if (pattr != null && pattr.DontShow)
|
||||
if (attr is ParameterAttribute pattr)
|
||||
{
|
||||
showToUser = false;
|
||||
addCommonParameters = false;
|
||||
break;
|
||||
if (pattr.DontShow)
|
||||
{
|
||||
showToUser = false;
|
||||
addCommonParameters = false;
|
||||
break;
|
||||
}
|
||||
|
||||
if (helpMessage is null && TryGetParameterHelpMessage(pattr, commandAssembly, out string attrHelpMessage))
|
||||
{
|
||||
helpMessage = $" - {attrHelpMessage}";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (showToUser)
|
||||
{
|
||||
string completionText = "-" + name + colonSuffix;
|
||||
string tooltip = type + name;
|
||||
string completionText = $"-{name}{colonSuffix}";
|
||||
string tooltip = $"{type}{name}{helpMessage}";
|
||||
listInUse.Add(new CompletionResult(completionText, name, CompletionResultType.ParameterName,
|
||||
tooltip));
|
||||
}
|
||||
|
||||
@@ -1125,6 +1125,163 @@ param([ValidatePattern(
|
||||
$res.CompletionMatches[1].CompletionText | Should -BeExactly '$DemoVar2'
|
||||
}
|
||||
|
||||
It 'Should include parameter help message in tool tip - SingleMatch <SingleMatch>' -TestCases @(
|
||||
@{ SingleMatch = $true }
|
||||
@{ SingleMatch = $false }
|
||||
) {
|
||||
param ($SingleMatch)
|
||||
|
||||
Function Test-Function {
|
||||
param (
|
||||
[Parameter(HelpMessage = 'Some help message')]
|
||||
$ParamWithHelp,
|
||||
|
||||
$ParamWithoutHelp
|
||||
)
|
||||
}
|
||||
|
||||
$expected = '[Object] ParamWithHelp - Some help message'
|
||||
|
||||
if ($SingleMatch) {
|
||||
$Script = 'Test-Function -ParamWithHelp'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches
|
||||
}
|
||||
else {
|
||||
$Script = 'Test-Function -'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches | Where-Object CompletionText -eq '-ParamWithHelp'
|
||||
}
|
||||
|
||||
$res.Count | Should -Be 1
|
||||
$res.CompletionText | Should -BeExactly '-ParamWithHelp'
|
||||
$res.ToolTip | Should -BeExactly $expected
|
||||
}
|
||||
|
||||
It 'Should include parameter help resource message in tool tip - SingleMatch <SingleMatch>' -TestCases @(
|
||||
@{ SingleMatch = $true }
|
||||
@{ SingleMatch = $false }
|
||||
) {
|
||||
param ($SingleMatch)
|
||||
|
||||
$expected = '`[string`] Activity - *'
|
||||
|
||||
if ($SingleMatch) {
|
||||
$Script = 'Write-Progress -Activity'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches
|
||||
}
|
||||
else {
|
||||
$Script = 'Write-Progress -'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches | Where-Object CompletionText -eq '-Activity'
|
||||
}
|
||||
|
||||
$res.Count | Should -Be 1
|
||||
$res.CompletionText | Should -BeExactly '-Activity'
|
||||
$res.ToolTip | Should -BeLikeExactly $expected
|
||||
}
|
||||
|
||||
It 'Should skip empty parameter HelpMessage with multiple parameters - SingleMatch <SingleMatch>' -TestCases @(
|
||||
@{ SingleMatch = $true }
|
||||
@{ SingleMatch = $false }
|
||||
) {
|
||||
param ($SingleMatch)
|
||||
|
||||
Function Test-Function {
|
||||
[CmdletBinding(DefaultParameterSetName = 'SetWithoutHelp')]
|
||||
param (
|
||||
[Parameter(ParameterSetName = 'SetWithHelp', HelpMessage = 'Help Message')]
|
||||
[Parameter(ParameterSetName = 'SetWithoutHelp')]
|
||||
[string]
|
||||
$ParamWithHelp,
|
||||
|
||||
[Parameter(ParameterSetName = 'SetWithHelp')]
|
||||
[switch]
|
||||
$ParamWithoutHelp
|
||||
)
|
||||
}
|
||||
|
||||
$expected = '[string] ParamWithHelp - Help Message'
|
||||
|
||||
if ($SingleMatch) {
|
||||
$Script = 'Test-Function -ParamWithHelp'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches
|
||||
}
|
||||
else {
|
||||
$Script = 'Test-Function -'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches | Where-Object CompletionText -eq '-ParamWithHelp'
|
||||
}
|
||||
|
||||
$res.Count | Should -Be 1
|
||||
$res.CompletionText | Should -BeExactly '-ParamWithHelp'
|
||||
$res.ToolTip | Should -BeExactly $expected
|
||||
}
|
||||
|
||||
It 'Should retrieve help message from dynamic parameter' {
|
||||
Function Test-Function {
|
||||
[CmdletBinding()]
|
||||
param ()
|
||||
dynamicparam {
|
||||
$attr = [System.Management.Automation.ParameterAttribute]@{
|
||||
HelpMessage = "Howdy partner"
|
||||
}
|
||||
$attrCollection = [System.Collections.ObjectModel.Collection[System.Attribute]]::new()
|
||||
$attrCollection.Add($attr)
|
||||
|
||||
$dynParam = [System.Management.Automation.RuntimeDefinedParameter]::new('DynamicParam', [string], $attrCollection)
|
||||
|
||||
$paramDictionary = [System.Management.Automation.RuntimeDefinedParameterDictionary]::new()
|
||||
$paramDictionary.Add('DynamicParam', $dynParam)
|
||||
$paramDictionary
|
||||
}
|
||||
|
||||
end {}
|
||||
}
|
||||
|
||||
$expected = '[string] DynamicParam - Howdy partner'
|
||||
$Script = 'Test-Function -'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches | Where-Object CompletionText -eq '-DynamicParam'
|
||||
$res.Count | Should -Be 1
|
||||
$res.CompletionText | Should -BeExactly '-DynamicParam'
|
||||
$res.ToolTip | Should -BeExactly $expected
|
||||
}
|
||||
|
||||
It 'Should have type and name for parameter without help message' {
|
||||
Function Test-Function {
|
||||
param (
|
||||
[Parameter()]
|
||||
$WithParamAttribute,
|
||||
|
||||
$WithoutParamAttribute
|
||||
)
|
||||
}
|
||||
|
||||
$Script = 'Test-Function -'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches |
|
||||
Where-Object CompletionText -in '-WithParamAttribute', '-WithoutParamAttribute' |
|
||||
Sort-Object CompletionText
|
||||
$res.Count | Should -Be 2
|
||||
|
||||
$res.CompletionText[0] | Should -BeExactly '-WithoutParamAttribute'
|
||||
$res.ToolTip[0] | Should -BeExactly '[Object] WithoutParamAttribute'
|
||||
|
||||
$res.CompletionText[1] | Should -BeExactly '-WithParamAttribute'
|
||||
$res.ToolTip[1] | Should -BeExactly '[Object] WithParamAttribute'
|
||||
}
|
||||
|
||||
It 'Should ignore errors when faling to get HelpMessage resource' {
|
||||
Function Test-Function {
|
||||
param (
|
||||
[Parameter(HelpMessageBaseName="invalid", HelpMessageResourceId="SomeId")]
|
||||
$InvalidHelpParam
|
||||
)
|
||||
}
|
||||
|
||||
$expected = '[Object] InvalidHelpParam'
|
||||
$Script = 'Test-Function -InvalidHelpParam'
|
||||
$res = (TabExpansion2 -inputScript $Script).CompletionMatches
|
||||
$res.Count | Should -Be 1
|
||||
$res.CompletionText | Should -BeExactly '-InvalidHelpParam'
|
||||
$res.ToolTip | Should -BeExactly $expected
|
||||
}
|
||||
|
||||
Context 'Start-Process -Verb parameter completion' {
|
||||
BeforeAll {
|
||||
function GetProcessInfoVerbs([string]$path, [switch]$singleQuote, [switch]$doubleQuote) {
|
||||
|
||||
Reference in New Issue
Block a user