Files
PowerShell/src/System.Management.Automation/engine/FunctionInfo.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

499 lines
17 KiB
C#

// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.
using System.Collections.ObjectModel;
using System.Management.Automation.Runspaces;
using System.Text;
namespace System.Management.Automation
{
/// <summary>
/// Provides information about a function that is stored in session state.
/// </summary>
public class FunctionInfo : CommandInfo, IScriptCommandInfo
{
#region ctor
/// <summary>
/// Creates an instance of the FunctionInfo class with the specified name and ScriptBlock.
/// </summary>
/// <param name="name">
/// The name of the function.
/// </param>
/// <param name="function">
/// The ScriptBlock for the function
/// </param>
/// <param name="context">
/// The execution context for the function.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="function"/> is null.
/// </exception>
internal FunctionInfo(string name, ScriptBlock function, ExecutionContext context) : this(name, function, context, null)
{
}
/// <summary>
/// Creates an instance of the FunctionInfo class with the specified name and ScriptBlock.
/// </summary>
/// <param name="name">
/// The name of the function.
/// </param>
/// <param name="function">
/// The ScriptBlock for the function
/// </param>
/// <param name="context">
/// The execution context for the function.
/// </param>
/// <param name="helpFile">
/// The name of the help file associated with the function.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="function"/> is null.
/// </exception>
internal FunctionInfo(string name, ScriptBlock function, ExecutionContext context, string helpFile) : base(name, CommandTypes.Function, context)
{
if (function == null)
{
throw PSTraceSource.NewArgumentNullException(nameof(function));
}
_scriptBlock = function;
CmdletInfo.SplitCmdletName(name, out _verb, out _noun);
this.Module = function.Module;
_helpFile = helpFile;
}
/// <summary>
/// Creates an instance of the FunctionInfo class with the specified name and ScriptBlock.
/// </summary>
/// <param name="name">
/// The name of the function.
/// </param>
/// <param name="function">
/// The ScriptBlock for the function
/// </param>
/// <param name="options">
/// The options to set on the function. Note, Constant can only be set at creation time.
/// </param>
/// <param name="context">
/// The execution context for the function.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="function"/> is null.
/// </exception>
internal FunctionInfo(string name, ScriptBlock function, ScopedItemOptions options, ExecutionContext context) : this(name, function, options, context, null)
{
}
/// <summary>
/// Creates an instance of the FunctionInfo class with the specified name and ScriptBlock.
/// </summary>
/// <param name="name">
/// The name of the function.
/// </param>
/// <param name="function">
/// The ScriptBlock for the function
/// </param>
/// <param name="options">
/// The options to set on the function. Note, Constant can only be set at creation time.
/// </param>
/// <param name="context">
/// The execution context for the function.
/// </param>
/// <param name="helpFile">
/// The name of the help file associated with the function.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="function"/> is null.
/// </exception>
internal FunctionInfo(string name, ScriptBlock function, ScopedItemOptions options, ExecutionContext context, string helpFile)
: this(name, function, context, helpFile)
{
_options = options;
}
/// <summary>
/// This is a copy constructor, used primarily for get-command.
/// </summary>
internal FunctionInfo(FunctionInfo other)
: base(other)
{
CopyFieldsFromOther(other);
}
private void CopyFieldsFromOther(FunctionInfo other)
{
_verb = other._verb;
_noun = other._noun;
_scriptBlock = other._scriptBlock;
_description = other._description;
_options = other._options;
_helpFile = other._helpFile;
}
/// <summary>
/// This is a copy constructor, used primarily for get-command.
/// </summary>
internal FunctionInfo(string name, FunctionInfo other)
: base(name, other)
{
CopyFieldsFromOther(other);
// Get the verb and noun from the name
CmdletInfo.SplitCmdletName(name, out _verb, out _noun);
}
/// <summary>
/// Create a copy of commandInfo for GetCommandCommand so that we can generate parameter
/// sets based on an argument list (so we can get the dynamic parameters.)
/// </summary>
internal override CommandInfo CreateGetCommandCopy(object[] arguments)
{
FunctionInfo copy = new FunctionInfo(this) { IsGetCommandCopy = true, Arguments = arguments };
return copy;
}
#endregion ctor
internal override HelpCategory HelpCategory
{
get { return HelpCategory.Function; }
}
/// <summary>
/// Gets the ScriptBlock which is the implementation of the function.
/// </summary>
public ScriptBlock ScriptBlock
{
get { return _scriptBlock; }
}
private ScriptBlock _scriptBlock;
/// <summary>
/// Updates a function.
/// </summary>
/// <param name="newFunction">
/// The script block that the function should represent.
/// </param>
/// <param name="force">
/// If true, the script block will be applied even if the filter is ReadOnly.
/// </param>
/// <param name="options">
/// Any options to set on the new function, null if none.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="newFunction"/> is null.
/// </exception>
internal void Update(ScriptBlock newFunction, bool force, ScopedItemOptions options)
{
Update(newFunction, force, options, null);
this.DefiningLanguageMode = newFunction.LanguageMode;
}
/// <summary/>
protected internal virtual void Update(FunctionInfo newFunction, bool force, ScopedItemOptions options, string helpFile)
{
Update(newFunction.ScriptBlock, force, options, helpFile);
}
/// <summary>
/// Updates a function.
/// </summary>
/// <param name="newFunction">
/// The script block that the function should represent.
/// </param>
/// <param name="force">
/// If true, the script block will be applied even if the filter is ReadOnly.
/// </param>
/// <param name="options">
/// Any options to set on the new function, null if none.
/// </param>
/// <param name="helpFile">
/// The helpfile for this function.
/// </param>
/// <exception cref="ArgumentNullException">
/// If <paramref name="newFunction"/> is null.
/// </exception>
internal void Update(ScriptBlock newFunction, bool force, ScopedItemOptions options, string helpFile)
{
if (newFunction == null)
{
throw PSTraceSource.NewArgumentNullException("function");
}
if ((_options & ScopedItemOptions.Constant) != 0)
{
SessionStateUnauthorizedAccessException e =
new SessionStateUnauthorizedAccessException(
Name,
SessionStateCategory.Function,
"FunctionIsConstant",
SessionStateStrings.FunctionIsConstant);
throw e;
}
if (!force && (_options & ScopedItemOptions.ReadOnly) != 0)
{
SessionStateUnauthorizedAccessException e =
new SessionStateUnauthorizedAccessException(
Name,
SessionStateCategory.Function,
"FunctionIsReadOnly",
SessionStateStrings.FunctionIsReadOnly);
throw e;
}
_scriptBlock = newFunction;
this.Module = newFunction.Module;
_commandMetadata = null;
this._parameterSets = null;
this.ExternalCommandMetadata = null;
if (options != ScopedItemOptions.Unspecified)
{
this.Options = options;
}
_helpFile = helpFile;
}
/// <summary>
/// Returns <c>true</c> if this function uses cmdlet binding mode for its parameters; otherwise returns <c>false</c>.
/// </summary>
public bool CmdletBinding
{
get
{
return this.ScriptBlock.UsesCmdletBinding;
}
}
/// <summary>
/// Gets the name of the default parameter set.
/// Returns <c>null</c> if this function doesn't use cmdlet parameter binding or if the default parameter set wasn't specified.
/// </summary>
public string DefaultParameterSet
{
get
{
return this.CmdletBinding ? this.CommandMetadata.DefaultParameterSetName : null;
}
}
/// <summary>
/// Gets the definition of the function which is the
/// ToString() of the ScriptBlock that implements the function.
/// </summary>
public override string Definition { get { return _scriptBlock.ToString(); } }
/// <summary>
/// Gets or sets the scope options for the function.
/// </summary>
/// <exception cref="SessionStateUnauthorizedAccessException">
/// If the trying to set a function that is constant or
/// if the value trying to be set is ScopedItemOptions.Constant
/// </exception>
public ScopedItemOptions Options
{
get
{
return CopiedCommand == null ? _options : ((FunctionInfo)CopiedCommand).Options;
}
set
{
if (CopiedCommand == null)
{
// Check to see if the function is constant, if so
// throw an exception because the options cannot be changed.
if ((_options & ScopedItemOptions.Constant) != 0)
{
SessionStateUnauthorizedAccessException e =
new SessionStateUnauthorizedAccessException(
Name,
SessionStateCategory.Function,
"FunctionIsConstant",
SessionStateStrings.FunctionIsConstant);
throw e;
}
// Now check to see if the caller is trying to set
// the options to constant. This is only allowed at
// variable creation
if ((value & ScopedItemOptions.Constant) != 0)
{
// user is trying to set the function to constant after
// creating the function. Do not allow this (as per spec).
SessionStateUnauthorizedAccessException e =
new SessionStateUnauthorizedAccessException(
Name,
SessionStateCategory.Function,
"FunctionCannotBeMadeConstant",
SessionStateStrings.FunctionCannotBeMadeConstant);
throw e;
}
// Ensure we are not trying to remove the AllScope option
if ((value & ScopedItemOptions.AllScope) == 0 &&
(_options & ScopedItemOptions.AllScope) != 0)
{
SessionStateUnauthorizedAccessException e =
new SessionStateUnauthorizedAccessException(
this.Name,
SessionStateCategory.Function,
"FunctionAllScopeOptionCannotBeRemoved",
SessionStateStrings.FunctionAllScopeOptionCannotBeRemoved);
throw e;
}
_options = value;
}
else
{
((FunctionInfo)CopiedCommand).Options = value;
}
}
}
private ScopedItemOptions _options = ScopedItemOptions.None;
/// <summary>
/// Gets or sets the description associated with the function.
/// </summary>
public string Description
{
get
{
return CopiedCommand == null ? _description : ((FunctionInfo)CopiedCommand).Description;
}
set
{
if (CopiedCommand == null)
{
_description = value;
}
else
{
((FunctionInfo)CopiedCommand).Description = value;
}
}
}
private string _description = null;
/// <summary>
/// Gets the verb of the function.
/// </summary>
public string Verb
{
get
{
return _verb;
}
}
private string _verb = string.Empty;
/// <summary>
/// Gets the noun of the function.
/// </summary>
public string Noun
{
get
{
return _noun;
}
}
private string _noun = string.Empty;
/// <summary>
/// Gets the help file path for the function.
/// </summary>
public string HelpFile
{
get
{
return _helpFile;
}
internal set
{
_helpFile = value;
}
}
private string _helpFile = string.Empty;
/// <summary>
/// Returns the syntax of a command.
/// </summary>
internal override string Syntax
{
get
{
StringBuilder synopsis = new StringBuilder();
foreach (CommandParameterSetInfo parameterSet in ParameterSets)
{
synopsis.AppendLine();
synopsis.AppendLine(
string.Format(
Globalization.CultureInfo.CurrentCulture,
"{0} {1}",
Name,
parameterSet.ToString()));
}
return synopsis.ToString();
}
}
/// <summary>
/// True if the command has dynamic parameters, false otherwise.
/// </summary>
internal override bool ImplementsDynamicParameters
{
get { return ScriptBlock.HasDynamicParameters; }
}
/// <summary>
/// The command metadata for the function or filter.
/// </summary>
internal override CommandMetadata CommandMetadata
{
get
{
return _commandMetadata ??
(_commandMetadata =
new CommandMetadata(this.ScriptBlock, this.Name, LocalPipeline.GetExecutionContextFromTLS()));
}
}
private CommandMetadata _commandMetadata;
/// <summary>
/// The output type(s) is specified in the script block.
/// </summary>
public override ReadOnlyCollection<PSTypeName> OutputType
{
get { return ScriptBlock.OutputType; }
}
}
}