mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
https://github.com/DotNetAnalyzers/StyleCopAnalyzers/blob/master/documentation/SA1504.md
904 lines
29 KiB
C#
904 lines
29 KiB
C#
// Copyright (c) Microsoft Corporation.
|
|
// Licensed under the MIT License.
|
|
|
|
using System.Collections.Generic;
|
|
using System.Collections.ObjectModel;
|
|
using System.Management.Automation.Language;
|
|
using System.Management.Automation.Runspaces;
|
|
using System.Runtime.CompilerServices;
|
|
|
|
namespace System.Management.Automation
|
|
{
|
|
/// <summary>
|
|
/// Represents a variable in the PowerShell language.
|
|
/// </summary>
|
|
public class PSVariable : IHasSessionStateEntryVisibility
|
|
{
|
|
#region Ctor
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
public PSVariable(string name)
|
|
: this(name, null, ScopedItemOptions.None, (Collection<Attribute>)null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name, and value.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value of the variable.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
public PSVariable(string name, object value)
|
|
: this(name, value, ScopedItemOptions.None, (Collection<Attribute>)null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name, value, and options.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value of the variable.
|
|
/// </param>
|
|
/// <param name="options">
|
|
/// The constraints of the variable. Note, variables can only be made constant
|
|
/// in the constructor.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
public PSVariable(string name, object value, ScopedItemOptions options)
|
|
: this(name, value, options, (Collection<Attribute>)null)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name, value, options, and description.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value of the variable.
|
|
/// </param>
|
|
/// <param name="options">
|
|
/// The constraints of the variable. Note, variables can only be made constant
|
|
/// in the constructor.
|
|
/// </param>
|
|
/// <param name="description">
|
|
/// The description for the variable.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
internal PSVariable(string name, object value, ScopedItemOptions options, string description)
|
|
: this(name, value, options, (Collection<Attribute>)null)
|
|
{
|
|
_description = description;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name, value, options, and description.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value of the variable.
|
|
/// </param>
|
|
/// <param name="options">
|
|
/// The constraints of the variable. Note, variables can only be made constant
|
|
/// in the constructor.
|
|
/// </param>
|
|
/// <param name="attributes">
|
|
/// The attributes for the variable. ValidateArgumentsAttribute and derived types
|
|
/// will be used to validate a value before setting it.
|
|
/// </param>
|
|
/// <param name="description">
|
|
/// The description for the variable.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
internal PSVariable(
|
|
string name,
|
|
object value,
|
|
ScopedItemOptions options,
|
|
Collection<Attribute> attributes,
|
|
string description)
|
|
: this(name, value, options, attributes)
|
|
{
|
|
_description = description;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Constructs a variable with the given name, value, options, and attributes.
|
|
/// </summary>
|
|
/// <param name="name">
|
|
/// The name of the variable.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value of the variable.
|
|
/// </param>
|
|
/// <param name="options">
|
|
/// The constraints of the variable. Note, variables can only be made constant
|
|
/// in the constructor.
|
|
/// </param>
|
|
/// <param name="attributes">
|
|
/// The attributes for the variable. ValidateArgumentsAttribute and derived types
|
|
/// will be used to validate a value before setting it.
|
|
/// </param>
|
|
/// <exception cref="ArgumentException">
|
|
/// If <paramref name="name"/> is null or empty.
|
|
/// </exception>
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// If the validation metadata identified in <paramref name="attributes"/>
|
|
/// throws an exception.
|
|
/// </exception>
|
|
public PSVariable(
|
|
string name,
|
|
object value,
|
|
ScopedItemOptions options,
|
|
Collection<Attribute> attributes)
|
|
{
|
|
if (string.IsNullOrEmpty(name))
|
|
{
|
|
throw PSTraceSource.NewArgumentException(nameof(name));
|
|
}
|
|
|
|
Name = name;
|
|
|
|
_attributes = new PSVariableAttributeCollection(this);
|
|
|
|
// Note, it is OK to set the value before setting the attributes
|
|
// because each attribute will be validated as it is set.
|
|
|
|
SetValueRawImpl(value, true);
|
|
|
|
if (attributes != null)
|
|
{
|
|
foreach (Attribute attribute in attributes)
|
|
{
|
|
_attributes.Add(attribute);
|
|
}
|
|
}
|
|
|
|
// Set the options after setting the initial value.
|
|
_options = options;
|
|
|
|
if (IsAllScope)
|
|
{
|
|
Language.VariableAnalysis.NoteAllScopeVariable(name);
|
|
}
|
|
}
|
|
|
|
// Should be protected, but that makes it public which we don't want.
|
|
// The dummy parameter is to make the signature distinct from the public constructor taking a string.
|
|
// This constructor exists to avoid calling SetValueRaw, which when overridden, might not work because
|
|
// the derived class isn't fully constructed yet.
|
|
internal PSVariable(string name, bool dummy)
|
|
{
|
|
Name = name;
|
|
}
|
|
|
|
#endregion ctor
|
|
|
|
/// <summary>
|
|
/// Gets the name of the variable.
|
|
/// </summary>
|
|
public string Name { get; } = string.Empty;
|
|
|
|
/// <summary>
|
|
/// Gets or sets the description of the variable.
|
|
/// </summary>
|
|
public virtual string Description
|
|
{
|
|
get
|
|
{
|
|
return _description;
|
|
}
|
|
|
|
set
|
|
{
|
|
_description = value;
|
|
}
|
|
}
|
|
|
|
private string _description = string.Empty;
|
|
|
|
internal void DebuggerCheckVariableRead()
|
|
{
|
|
var context = SessionState != null
|
|
? SessionState.ExecutionContext
|
|
: LocalPipeline.GetExecutionContextFromTLS();
|
|
if (context != null && context._debuggingMode > 0)
|
|
{
|
|
context.Debugger.CheckVariableRead(Name);
|
|
}
|
|
}
|
|
|
|
internal void DebuggerCheckVariableWrite()
|
|
{
|
|
var context = SessionState != null
|
|
? SessionState.ExecutionContext
|
|
: LocalPipeline.GetExecutionContextFromTLS();
|
|
if (context != null && context._debuggingMode > 0)
|
|
{
|
|
context.Debugger.CheckVariableWrite(Name);
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the value of the variable.
|
|
/// </summary>
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
/// If the variable is read-only or constant upon call to set.
|
|
/// </exception>
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// <paramref name="value"/> is not valid according to one or more
|
|
/// of the attributes of this shell variable.
|
|
/// </exception>
|
|
public virtual object Value
|
|
{
|
|
get
|
|
{
|
|
DebuggerCheckVariableRead();
|
|
return _value;
|
|
}
|
|
|
|
set
|
|
{
|
|
SetValue(value);
|
|
}
|
|
}
|
|
|
|
private object _value;
|
|
|
|
/// <summary>
|
|
/// If true, then this variable is visible outside the runspace.
|
|
/// </summary>
|
|
public SessionStateEntryVisibility Visibility { get; set; } = SessionStateEntryVisibility.Public;
|
|
|
|
/// <summary>
|
|
/// The module where this variable was defined.
|
|
/// </summary>
|
|
public PSModuleInfo Module { get; private set; }
|
|
|
|
internal void SetModule(PSModuleInfo module)
|
|
{
|
|
Module = module;
|
|
}
|
|
|
|
/// <summary>
|
|
/// The name of the module that defined this variable.
|
|
/// </summary>
|
|
public string ModuleName
|
|
{
|
|
get
|
|
{
|
|
if (Module != null)
|
|
return Module.Name;
|
|
return string.Empty;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets or sets the scope options on the variable.
|
|
/// </summary>
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
/// Upon set, if the variable is constant or if <paramref name="value"/>
|
|
/// contains the constant flag.
|
|
/// </exception>
|
|
public virtual ScopedItemOptions Options
|
|
{
|
|
get
|
|
{
|
|
return _options;
|
|
}
|
|
|
|
set
|
|
{
|
|
SetOptions(value, false);
|
|
}
|
|
}
|
|
|
|
internal void SetOptions(ScopedItemOptions newOptions, bool force)
|
|
{
|
|
// Check to see if the variable is constant or readonly, if so
|
|
// throw an exception because the options cannot be changed.
|
|
|
|
if (IsConstant || (!force && IsReadOnly))
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Variable,
|
|
"VariableNotWritable",
|
|
SessionStateStrings.VariableNotWritable);
|
|
|
|
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 ((newOptions & ScopedItemOptions.Constant) != 0)
|
|
{
|
|
// user is trying to set the variable to constant after
|
|
// creating the variable. Do not allow this (as per spec).
|
|
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Variable,
|
|
"VariableCannotBeMadeConstant",
|
|
SessionStateStrings.VariableCannotBeMadeConstant);
|
|
|
|
throw e;
|
|
}
|
|
|
|
// Now check to see if the caller is trying to
|
|
// remove the AllScope option. This is not allowed
|
|
// at any time.
|
|
|
|
if (IsAllScope && ((newOptions & ScopedItemOptions.AllScope) == 0))
|
|
{
|
|
// user is trying to remove the AllScope option from the variable.
|
|
// Do not allow this (as per spec).
|
|
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Variable,
|
|
"VariableAllScopeOptionCannotBeRemoved",
|
|
SessionStateStrings.VariableAllScopeOptionCannotBeRemoved);
|
|
|
|
throw e;
|
|
}
|
|
|
|
_options = newOptions;
|
|
}
|
|
|
|
private ScopedItemOptions _options = ScopedItemOptions.None;
|
|
|
|
/// <summary>
|
|
/// Gets the collection that contains the attributes for the variable.
|
|
/// </summary>
|
|
/// <remarks>
|
|
/// To add or remove attributes, get the collection and then add or remove
|
|
/// attributes to that collection.
|
|
/// </remarks>
|
|
public Collection<Attribute> Attributes
|
|
{
|
|
get { return _attributes ??= new PSVariableAttributeCollection(this); }
|
|
}
|
|
|
|
private PSVariableAttributeCollection _attributes;
|
|
|
|
/// <summary>
|
|
/// Checks if the given value meets the validation attribute constraints on the PSVariable.
|
|
/// </summary>
|
|
/// <param name="value">
|
|
/// value which needs to be checked
|
|
/// </param>
|
|
/// <remarks>
|
|
/// If <paramref name="value"/> is null or if no attributes are set, then
|
|
/// the value is deemed valid.
|
|
/// </remarks>
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// If the validation metadata throws an exception.
|
|
/// </exception>
|
|
public virtual bool IsValidValue(object value)
|
|
{
|
|
return IsValidValue(_attributes, value);
|
|
}
|
|
|
|
internal static bool IsValidValue(IEnumerable<Attribute> attributes, object value)
|
|
{
|
|
if (attributes != null)
|
|
{
|
|
foreach (Attribute attribute in attributes)
|
|
{
|
|
if (!IsValidValue(value, attribute))
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Determines if the value is valid for the specified attribute.
|
|
/// </summary>
|
|
/// <param name="value">
|
|
/// The variable value to validate.
|
|
/// </param>
|
|
/// <param name="attribute">
|
|
/// The attribute to use to validate that value.
|
|
/// </param>
|
|
/// <returns>
|
|
/// True if the value is valid with respect to the attribute, or false otherwise.
|
|
/// </returns>
|
|
internal static bool IsValidValue(object value, Attribute attribute)
|
|
{
|
|
bool result = true;
|
|
|
|
ValidateArgumentsAttribute validationAttribute = attribute as ValidateArgumentsAttribute;
|
|
if (validationAttribute != null)
|
|
{
|
|
try
|
|
{
|
|
// Get an EngineIntrinsics instance using the context of the thread.
|
|
|
|
ExecutionContext context = Runspaces.LocalPipeline.GetExecutionContextFromTLS();
|
|
EngineIntrinsics engine = null;
|
|
|
|
if (context != null)
|
|
{
|
|
engine = context.EngineIntrinsics;
|
|
}
|
|
|
|
validationAttribute.InternalValidate(value, engine);
|
|
}
|
|
catch (ValidationMetadataException)
|
|
{
|
|
result = false;
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Runs all ArgumentTransformationAttributes that are specified in the Attributes
|
|
/// collection on the given value in the order that they are in the collection.
|
|
/// </summary>
|
|
/// <param name="attributes">
|
|
/// The attributes to use to transform the value.
|
|
/// </param>
|
|
/// <param name="value">
|
|
/// The value to be transformed.
|
|
/// </param>
|
|
/// <returns>
|
|
/// The transformed value.
|
|
/// </returns>
|
|
/// <exception cref="ArgumentTransformationMetadataException">
|
|
/// If the argument transformation fails.
|
|
/// </exception>
|
|
internal static object TransformValue(IEnumerable<Attribute> attributes, object value)
|
|
{
|
|
Diagnostics.Assert(attributes != null, "caller to verify attributes is not null");
|
|
|
|
object result = value;
|
|
|
|
// Get an EngineIntrinsics instance using the context of the thread.
|
|
|
|
ExecutionContext context = Runspaces.LocalPipeline.GetExecutionContextFromTLS();
|
|
EngineIntrinsics engine = null;
|
|
|
|
if (context != null)
|
|
{
|
|
engine = context.EngineIntrinsics;
|
|
}
|
|
|
|
foreach (Attribute attribute in attributes)
|
|
{
|
|
ArgumentTransformationAttribute transformationAttribute =
|
|
attribute as ArgumentTransformationAttribute;
|
|
if (transformationAttribute != null)
|
|
{
|
|
result = transformationAttribute.TransformInternal(engine, result);
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Parameter binding does the checking and conversions as specified by the
|
|
/// attributes, so repeating that process is slow and wrong. This function
|
|
/// applies the attributes without repeating the checks.
|
|
/// </summary>
|
|
/// <param name="attributes">The list of attributes to add.</param>
|
|
internal void AddParameterAttributesNoChecks(Collection<Attribute> attributes)
|
|
{
|
|
foreach (Attribute attribute in attributes)
|
|
{
|
|
_attributes.AddAttributeNoCheck(attribute);
|
|
}
|
|
}
|
|
|
|
#region internal members
|
|
|
|
/// <summary>
|
|
/// Returns true if the PSVariable is constant (only visible in the
|
|
/// current scope), false otherwise.
|
|
/// </summary>
|
|
internal bool IsConstant
|
|
{
|
|
get
|
|
{
|
|
return (_options & ScopedItemOptions.Constant) != 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the PSVariable is readonly (only visible in the
|
|
/// current scope), false otherwise.
|
|
/// </summary>
|
|
internal bool IsReadOnly
|
|
{
|
|
get
|
|
{
|
|
return (_options & ScopedItemOptions.ReadOnly) != 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the PSVariable is private (only visible in the
|
|
/// current scope), false otherwise.
|
|
/// </summary>
|
|
internal bool IsPrivate
|
|
{
|
|
get
|
|
{
|
|
return (_options & ScopedItemOptions.Private) != 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Returns true if the PSVariable is propagated to all scopes
|
|
/// when the scope is created.
|
|
/// </summary>
|
|
internal bool IsAllScope
|
|
{
|
|
get
|
|
{
|
|
return (_options & ScopedItemOptions.AllScope) != 0;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Indicates that the variable has been removed from session state
|
|
/// and should no longer be considered valid. This is necessary because
|
|
/// we surface variable references and can consequently not maintain
|
|
/// transparent integrity.
|
|
/// </summary>
|
|
internal bool WasRemoved
|
|
{
|
|
get
|
|
{
|
|
return _wasRemoved;
|
|
}
|
|
|
|
set
|
|
{
|
|
_wasRemoved = value;
|
|
// If set to true, clean up the variable...
|
|
if (value)
|
|
{
|
|
_options = ScopedItemOptions.None;
|
|
_value = null;
|
|
_wasRemoved = true;
|
|
_attributes = null;
|
|
}
|
|
}
|
|
}
|
|
|
|
private bool _wasRemoved;
|
|
|
|
internal SessionStateInternal SessionState { get; set; }
|
|
|
|
#endregion internal members
|
|
|
|
/// <summary>
|
|
/// Verifies the constraints and attributes before setting the value.
|
|
/// </summary>
|
|
/// <param name="value">
|
|
/// The value to be set.
|
|
/// </param>
|
|
/// <exception cref="SessionStateUnauthorizedAccessException">
|
|
/// If the variable is read-only or constant.
|
|
/// </exception>
|
|
/// <exception cref="ValidationMetadataException">
|
|
/// If the validation metadata throws an exception or the value doesn't
|
|
/// pass the validation metadata.
|
|
/// </exception>
|
|
private void SetValue(object value)
|
|
{
|
|
// Check to see if the variable is writable
|
|
|
|
if ((_options & (ScopedItemOptions.ReadOnly | ScopedItemOptions.Constant)) != ScopedItemOptions.None)
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Variable,
|
|
"VariableNotWritable",
|
|
SessionStateStrings.VariableNotWritable);
|
|
|
|
throw e;
|
|
}
|
|
|
|
// Now perform all ArgumentTransformations that are needed
|
|
object transformedValue = value;
|
|
if (_attributes != null && _attributes.Count > 0)
|
|
{
|
|
transformedValue = TransformValue(_attributes, value);
|
|
|
|
// Next check to make sure the value is valid
|
|
|
|
if (!IsValidValue(transformedValue))
|
|
{
|
|
ValidationMetadataException e = new ValidationMetadataException(
|
|
"ValidateSetFailure",
|
|
null,
|
|
Metadata.InvalidValueFailure,
|
|
Name,
|
|
((transformedValue != null) ? transformedValue.ToString() : "$null"));
|
|
|
|
throw e;
|
|
}
|
|
}
|
|
|
|
if (transformedValue != null)
|
|
{
|
|
transformedValue = CopyMutableValues(transformedValue);
|
|
}
|
|
|
|
// Set the value before triggering any write breakpoints
|
|
_value = transformedValue;
|
|
|
|
DebuggerCheckVariableWrite();
|
|
}
|
|
|
|
private void SetValueRawImpl(object newValue, bool preserveValueTypeSemantics)
|
|
{
|
|
if (preserveValueTypeSemantics)
|
|
{
|
|
newValue = CopyMutableValues(newValue);
|
|
}
|
|
|
|
_value = newValue;
|
|
}
|
|
|
|
internal virtual void SetValueRaw(object newValue, bool preserveValueTypeSemantics)
|
|
{
|
|
SetValueRawImpl(newValue, preserveValueTypeSemantics);
|
|
}
|
|
|
|
private readonly CallSite<Func<CallSite, object, object>> _copyMutableValueSite =
|
|
CallSite<Func<CallSite, object, object>>.Create(PSVariableAssignmentBinder.Get());
|
|
|
|
internal object CopyMutableValues(object o)
|
|
{
|
|
// The variable assignment binder copies mutable values and returns other values as is.
|
|
return _copyMutableValueSite.Target.Invoke(_copyMutableValueSite, o);
|
|
}
|
|
|
|
internal void WrapValue()
|
|
{
|
|
if (!this.IsConstant)
|
|
{
|
|
if (_value != null)
|
|
{
|
|
_value = PSObject.AsPSObject(_value);
|
|
}
|
|
}
|
|
}
|
|
|
|
#if FALSE
|
|
// Replaced with a DLR based binder - but code is preserved in case that approach doesn't
|
|
// work well performance wise.
|
|
|
|
// See if it's a value type being assigned and
|
|
// make a copy if it is...
|
|
private static object PreserveValueType(object value)
|
|
{
|
|
if (value == null)
|
|
return null;
|
|
|
|
// Primitive types are immutable so just return them...
|
|
Type valueType = value.GetType();
|
|
if (valueType.IsPrimitive)
|
|
return value;
|
|
|
|
PSObject valueAsPSObject = value as PSObject;
|
|
if (valueAsPSObject != null)
|
|
{
|
|
object baseObject = valueAsPSObject.BaseObject;
|
|
if (baseObject != null)
|
|
{
|
|
valueType = baseObject.GetType();
|
|
if (valueType.IsValueType && !valueType.IsPrimitive)
|
|
{
|
|
return valueAsPSObject.Copy();
|
|
}
|
|
}
|
|
}
|
|
else if (valueType.IsValueType)
|
|
{
|
|
return PSObject.CopyValueType(value);
|
|
}
|
|
|
|
return value;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
internal class LocalVariable : PSVariable
|
|
{
|
|
private readonly MutableTuple _tuple;
|
|
private readonly int _tupleSlot;
|
|
|
|
public LocalVariable(string name, MutableTuple tuple, int tupleSlot)
|
|
: base(name, false)
|
|
{
|
|
_tuple = tuple;
|
|
_tupleSlot = tupleSlot;
|
|
}
|
|
|
|
public override ScopedItemOptions Options
|
|
{
|
|
get
|
|
{
|
|
return base.Options;
|
|
}
|
|
|
|
set
|
|
{
|
|
// Throw, but only if someone is actually changing the options.
|
|
if (value != base.Options)
|
|
{
|
|
SessionStateUnauthorizedAccessException e =
|
|
new SessionStateUnauthorizedAccessException(
|
|
Name,
|
|
SessionStateCategory.Variable,
|
|
"VariableOptionsNotSettable",
|
|
SessionStateStrings.VariableOptionsNotSettable);
|
|
|
|
throw e;
|
|
}
|
|
}
|
|
}
|
|
|
|
public override object Value
|
|
{
|
|
get
|
|
{
|
|
DebuggerCheckVariableRead();
|
|
return _tuple.GetValue(_tupleSlot);
|
|
}
|
|
|
|
set
|
|
{
|
|
_tuple.SetValue(_tupleSlot, value);
|
|
DebuggerCheckVariableWrite();
|
|
}
|
|
}
|
|
|
|
internal override void SetValueRaw(object newValue, bool preserveValueTypeSemantics)
|
|
{
|
|
if (preserveValueTypeSemantics)
|
|
{
|
|
newValue = CopyMutableValues(newValue);
|
|
}
|
|
|
|
this.Value = newValue;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This class is used for $null. It always returns null as a value and accepts
|
|
/// any value when it is set and throws it away.
|
|
/// </summary>
|
|
internal class NullVariable : PSVariable
|
|
{
|
|
/// <summary>
|
|
/// Constructor that calls the base class constructor with name "null" and
|
|
/// value null.
|
|
/// </summary>
|
|
internal NullVariable() : base(StringLiterals.Null, null, ScopedItemOptions.Constant | ScopedItemOptions.AllScope)
|
|
{
|
|
}
|
|
|
|
/// <summary>
|
|
/// Always returns null from get, and always accepts
|
|
/// but ignores the value on set.
|
|
/// </summary>
|
|
public override object Value
|
|
{
|
|
get
|
|
{
|
|
return null;
|
|
}
|
|
|
|
set
|
|
{
|
|
// All values are just ignored
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the description for $null.
|
|
/// </summary>
|
|
public override string Description
|
|
{
|
|
get { return _description ??= SessionStateStrings.DollarNullDescription; }
|
|
|
|
set { /* Do nothing */ }
|
|
}
|
|
|
|
private string _description;
|
|
|
|
/// <summary>
|
|
/// Gets the scope options for $null which is always None.
|
|
/// </summary>
|
|
public override ScopedItemOptions Options
|
|
{
|
|
get { return ScopedItemOptions.None; }
|
|
|
|
set { /* Do nothing */ }
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// The options that define some of the constraints for session state items like
|
|
/// variables, aliases, and functions.
|
|
/// </summary>
|
|
[Flags]
|
|
public enum ScopedItemOptions
|
|
{
|
|
/// <summary>
|
|
/// There are no constraints on the item.
|
|
/// </summary>
|
|
None = 0,
|
|
|
|
/// <summary>
|
|
/// The item is readonly. It can be removed but cannot be changed.
|
|
/// </summary>
|
|
ReadOnly = 0x1,
|
|
|
|
/// <summary>
|
|
/// The item cannot be removed or changed.
|
|
/// This flag can only be set a variable creation.
|
|
/// </summary>
|
|
Constant = 0x2,
|
|
|
|
/// <summary>
|
|
/// The item is private to the scope it was created in and
|
|
/// cannot be seen from child scopes.
|
|
/// </summary>
|
|
Private = 0x4,
|
|
|
|
/// <summary>
|
|
/// The item is propagated to each new child scope created.
|
|
/// </summary>
|
|
AllScope = 0x8,
|
|
|
|
/// <summary>
|
|
/// The option is not specified by the user.
|
|
/// </summary>
|
|
Unspecified = 0x10
|
|
}
|
|
}
|