Files
PowerShell/src/System.Management.Automation/engine/ProxyCommand.cs
T
xtqqczze 9212aac0fa Use nameof operator (#12716)
# PR Summary

Using *Roslynator Command Line Tool version 0.1.0.4*

* Fix RCS1015:
  * `"argument"` → `nameof(argument)`
  * `enum.ToString()` → `nameof(enum)`

[RCS1015.log](https://github.com/PowerShell/PowerShell/files/4646102/RCS1015.log)


## PR Context

<!-- Provide a little reasoning as to why this Pull Request helps and why you have opened it. -->

## PR Checklist

- [x] [PR has a meaningful title](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
    - Use the present tense and imperative mood when describing your changes
- [x] [Summarized changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
- [x] [Make sure all `.h`, `.cpp`, `.cs`, `.ps1` and `.psm1` files have the correct copyright header](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
- [x] This PR is ready to merge and is not [Work in Progress](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---work-in-progress).
    - If the PR is work in progress, please add the prefix `WIP:` or `[ WIP ]` to the beginning of the title (the `WIP` bot will keep its status check at `Pending` while the prefix is present) and remove the prefix when the PR is ready.
- **[Breaking changes](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#making-breaking-changes)**
    - [x] None
    - **OR**
    - [ ] [Experimental feature(s) needed](https://github.com/MicrosoftDocs/PowerShell-Docs/blob/staging/reference/6/Microsoft.PowerShell.Core/About/about_Experimental_Features.md)
        - [ ] Experimental feature name(s): <!-- Experimental feature name(s) here -->
- **User-facing changes**
    - [x] Not Applicable
    - **OR**
    - [ ] [Documentation needed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#pull-request---submission)
        - [ ] Issue filed: <!-- Number/link of that issue here -->
- **Testing - New and feature**
    - [x] N/A or can only be tested interactively
    - **OR**
    - [ ] [Make sure you've added a new test if existing tests do not effectively test the code changed](https://github.com/PowerShell/PowerShell/blob/master/.github/CONTRIBUTING.md#before-submitting)
- **Tooling**
    - [x] I have considered the user experience from a tooling perspective and don't believe tooling will be impacted.
    - **OR**
    - [ ] I have considered the user experience from a tooling perspective and enumerated concerns in the summary. This may include:
        - Impact on [PowerShell Editor Services](https://github.com/PowerShell/PowerShellEditorServices) which is used in the [PowerShell extension](https://github.com/PowerShell/vscode-powershell) for VSCode (which runs in a different PS Host).
        - Impact on Completions (both in the console and in editors) - one of PowerShell's most powerful features.
        - Impact on [PSScriptAnalyzer](https://github.com/PowerShell/PSScriptAnalyzer) (which provides linting & formatting in the editor extensions).
        - Impact on [EditorSyntax](https://github.com/PowerShell/EditorSyntax) (which provides syntax highlighting with in VSCode, GitHub, and many other editors).
2020-05-19 18:57:52 +00:00

483 lines
18 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace System.Management.Automation
{
/// <summary>
/// A ProxyCommand class used to represent a Command constructed Dynamically.
/// </summary>
public sealed class ProxyCommand
{
#region Private Constructor
/// <summary>
/// Private Constructor to restrict inheritance.
/// </summary>
private ProxyCommand()
{
}
#endregion
#region Public Static Methods
/// <summary>
/// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.
/// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing Command ScriptBlock.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string Create(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetProxyCommand(string.Empty, true);
}
/// <summary>
/// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.
/// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <param name="helpComment">
/// The string to be used as the help comment.
/// </param>
/// <returns>
/// A string representing Command ScriptBlock.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string Create(CommandMetadata commandMetadata, string helpComment)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetProxyCommand(helpComment, true);
}
/// <summary>
/// This method constructs a string representing the command specified by <paramref name="commandMetadata"/>.
/// The returned string is a ScriptBlock which can be used to configure a Cmdlet/Function in a Runspace.
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <param name="helpComment">
/// The string to be used as the help comment.
/// </param>
/// <param name="generateDynamicParameters">
/// A boolean that determines whether the generated proxy command should include the functionality required
/// to proxy dynamic parameters of the underlying command.
/// </param>
/// <returns>
/// A string representing Command ScriptBlock.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string Create(CommandMetadata commandMetadata, string helpComment, bool generateDynamicParameters)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetProxyCommand(helpComment, generateDynamicParameters);
}
/// <summary>
/// This method constructs a string representing the CmdletBinding attribute of the command
/// specified by <paramref name="commandMetadata"/>.
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the CmdletBinding attribute of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string GetCmdletBindingAttribute(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetDecl();
}
/// <summary>
/// This method constructs a string representing the param block of the command
/// specified by <paramref name="commandMetadata"/>. The returned string only contains the
/// parameters, it is not enclosed in "param()".
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the parameters of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
[SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly")]
public static string GetParamBlock(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetParamBlock();
}
/// <summary>
/// This method constructs a string representing the begin block of the command
/// specified by <paramref name="commandMetadata"/>. The returned string only contains the
/// script, it is not enclosed in "begin { }".
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the begin block of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string GetBegin(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetBeginBlock();
}
/// <summary>
/// This method constructs a string representing the process block of the command
/// specified by <paramref name="commandMetadata"/>. The returned string only contains the
/// script, it is not enclosed in "process { }".
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the process block of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string GetProcess(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetProcessBlock();
}
/// <summary>
/// This method constructs a string representing the dynamic parameter block of the command
/// specified by <paramref name="commandMetadata"/>. The returned string only contains the
/// script, it is not enclosed in "dynamicparam { }".
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the dynamic parameter block of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string GetDynamicParam(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetDynamicParamBlock();
}
/// <summary>
/// This method constructs a string representing the end block of the command
/// specified by <paramref name="commandMetadata"/>. The returned string only contains the
/// script, it is not enclosed in "end { }".
/// </summary>
/// <param name="commandMetadata">
/// An instance of CommandMetadata representing a command.
/// </param>
/// <returns>
/// A string representing the end block of the command.
/// </returns>
/// <exception cref="ArgumentNullException">
/// commandMetadata is null.
/// </exception>
public static string GetEnd(CommandMetadata commandMetadata)
{
if (commandMetadata == null)
{
throw PSTraceSource.NewArgumentNullException("commandMetaData");
}
return commandMetadata.GetEndBlock();
}
private static T GetProperty<T>(PSObject obj, string property) where T : class
{
T result = null;
if (obj != null && obj.Properties[property] != null)
{
result = obj.Properties[property].Value as T;
}
return result;
}
private static string GetObjText(object obj)
{
string text = null;
PSObject psobj = obj as PSObject;
if (psobj != null)
{
text = GetProperty<string>(psobj, "Text");
}
return text ?? obj.ToString();
}
private static void AppendContent(StringBuilder sb, string section, object obj)
{
if (obj != null)
{
string text = GetObjText(obj);
if (!string.IsNullOrEmpty(text))
{
sb.Append("\n");
sb.Append(section);
sb.Append("\n\n");
sb.Append(text);
sb.Append("\n");
}
}
}
private static void AppendContent(StringBuilder sb, string section, PSObject[] array)
{
if (array != null)
{
bool first = true;
foreach (PSObject obj in array)
{
string text = GetObjText(obj);
if (!string.IsNullOrEmpty(text))
{
if (first)
{
first = false;
sb.Append("\n\n");
sb.Append(section);
sb.Append("\n\n");
}
sb.Append(text);
sb.Append("\n");
}
}
if (!first)
{
sb.Append("\n");
}
}
}
private static void AppendType(StringBuilder sb, string section, PSObject parent)
{
PSObject type = GetProperty<PSObject>(parent, "type");
PSObject name = GetProperty<PSObject>(type, "name");
if (name != null)
{
sb.Append("\n\n");
sb.Append(section);
sb.Append("\n\n");
sb.Append(GetObjText(name));
sb.Append("\n");
}
else
{
PSObject uri = GetProperty<PSObject>(type, "uri");
if (uri != null)
{
sb.Append("\n\n");
sb.Append(section);
sb.Append("\n\n");
sb.Append(GetObjText(uri));
sb.Append("\n");
}
}
}
/// <summary>
/// Construct the text that can be used in a multi-line comment for get-help.
/// </summary>
/// <param name="help">A custom PSObject created by Get-Help.</param>
/// <returns>A string that can be used as the help comment for script for the input HelpInfo object.</returns>
/// <exception cref="System.ArgumentNullException">When the help argument is null.</exception>
/// <exception cref="System.InvalidOperationException">When the help argument is not recognized as a HelpInfo object.</exception>
public static string GetHelpComments(PSObject help)
{
if (help == null)
{
throw new ArgumentNullException(nameof(help));
}
bool isHelpObject = false;
foreach (string typeName in help.InternalTypeNames)
{
if (typeName.Contains("HelpInfo"))
{
isHelpObject = true;
break;
}
}
if (!isHelpObject)
{
string error = ProxyCommandStrings.HelpInfoObjectRequired;
throw new InvalidOperationException(error);
}
StringBuilder sb = new StringBuilder();
AppendContent(sb, ".SYNOPSIS", GetProperty<string>(help, "Synopsis"));
AppendContent(sb, ".DESCRIPTION", GetProperty<PSObject[]>(help, "Description"));
PSObject parameters = GetProperty<PSObject>(help, "Parameters");
PSObject[] parameter = GetProperty<PSObject[]>(parameters, "Parameter");
if (parameter != null)
{
foreach (PSObject param in parameter)
{
PSObject name = GetProperty<PSObject>(param, "Name");
PSObject[] description = GetProperty<PSObject[]>(param, "Description");
sb.Append("\n.PARAMETER ");
sb.Append(name);
sb.Append("\n\n");
foreach (PSObject obj in description)
{
string text = GetProperty<string>(obj, "Text") ?? obj.ToString();
if (!string.IsNullOrEmpty(text))
{
sb.Append(text);
sb.Append("\n");
}
}
}
}
PSObject examples = GetProperty<PSObject>(help, "examples");
PSObject[] example = GetProperty<PSObject[]>(examples, "example");
if (example != null)
{
foreach (PSObject ex in example)
{
StringBuilder exsb = new StringBuilder();
PSObject[] introduction = GetProperty<PSObject[]>(ex, "introduction");
if (introduction != null)
{
foreach (PSObject intro in introduction)
{
if (intro != null)
{
exsb.Append(GetObjText(intro));
}
}
}
PSObject code = GetProperty<PSObject>(ex, "code");
if (code != null)
{
exsb.Append(code.ToString());
}
PSObject[] remarks = GetProperty<PSObject[]>(ex, "remarks");
if (remarks != null)
{
exsb.Append("\n");
foreach (PSObject remark in remarks)
{
string remarkText = GetProperty<string>(remark, "text");
exsb.Append(remarkText.ToString());
}
}
if (exsb.Length > 0)
{
sb.Append("\n\n.EXAMPLE\n\n");
sb.Append(exsb.ToString());
}
}
}
PSObject alertSet = GetProperty<PSObject>(help, "alertSet");
AppendContent(sb, ".NOTES", GetProperty<PSObject[]>(alertSet, "alert"));
PSObject inputtypes = GetProperty<PSObject>(help, "inputTypes");
PSObject inputtype = GetProperty<PSObject>(inputtypes, "inputType");
AppendType(sb, ".INPUTS", inputtype);
PSObject returnValues = GetProperty<PSObject>(help, "returnValues");
PSObject returnValue = GetProperty<PSObject>(returnValues, "returnValue");
AppendType(sb, ".OUTPUTS", returnValue);
PSObject relatedLinks = GetProperty<PSObject>(help, "relatedLinks");
PSObject[] navigationLink = GetProperty<PSObject[]>(relatedLinks, "navigationLink");
if (navigationLink != null)
{
foreach (PSObject link in navigationLink)
{
// Most likely only one of these will append anything, but it
// isn't wrong to append them both.
AppendContent(sb, ".LINK", GetProperty<PSObject>(link, "uri"));
AppendContent(sb, ".LINK", GetProperty<PSObject>(link, "linkText"));
}
}
AppendContent(sb, ".COMPONENT", GetProperty<PSObject>(help, "Component"));
AppendContent(sb, ".ROLE", GetProperty<PSObject>(help, "Role"));
AppendContent(sb, ".FUNCTIONALITY", GetProperty<PSObject>(help, "Functionality"));
return sb.ToString();
}
#endregion
}
}