mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Make approved features non-experimental (#11303)
# Conflicts: # src/System.Management.Automation/engine/ExperimentalFeature/ExperimentalFeature.cs
This commit is contained in:
@@ -11,7 +11,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// <summary>
|
||||
/// Class for Get-Error implementation.
|
||||
/// </summary>
|
||||
[Experimental("Microsoft.PowerShell.Utility.PSGetError", ExperimentAction.Show)]
|
||||
[Cmdlet(VerbsCommon.Get, "Error",
|
||||
HelpUri = "https://docs.microsoft.com/powershell/module/microsoft.powershell.utility/get-error?view=powershell-7&WT.mc_id=ps-gethelp",
|
||||
DefaultParameterSetName = NewestParameterSetName)]
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace Microsoft.PowerShell
|
||||
static UpdatesNotification()
|
||||
{
|
||||
s_notificationType = GetNotificationType();
|
||||
CanNotifyUpdates = s_notificationType != NotificationType.Off && ExperimentalFeature.IsEnabled("PSUpdatesNotification");
|
||||
CanNotifyUpdates = s_notificationType != NotificationType.Off;
|
||||
|
||||
if (CanNotifyUpdates)
|
||||
{
|
||||
|
||||
@@ -109,24 +109,6 @@ namespace System.Management.Automation
|
||||
new ExperimentalFeature(
|
||||
name: "PSCommandNotFoundSuggestion",
|
||||
description: "Recommend potential commands based on fuzzy search on a CommandNotFoundException"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSForEachObjectParallel",
|
||||
description: "New parameter set for ForEach-Object to run script blocks in parallel"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSTernaryOperator",
|
||||
description: "Support the ternary operator in PowerShell language"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSErrorView",
|
||||
description: "New formatting for ErrorRecord"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSUpdatesNotification",
|
||||
description: "Print notification message when new releases are available"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSCoalescingOperators",
|
||||
description: "Support the null coalescing operator and null coalescing assignment operator in PowerShell language"),
|
||||
new ExperimentalFeature(
|
||||
name: "PSPipelineChainOperators",
|
||||
description: "Allow use of && and || as operators between pipeline invocations"),
|
||||
#if UNIX
|
||||
new ExperimentalFeature(
|
||||
name: "PSUnixFileStat",
|
||||
@@ -135,11 +117,6 @@ namespace System.Management.Automation
|
||||
new ExperimentalFeature(
|
||||
name: "PSNullConditionalOperators",
|
||||
description: "Support the null conditional member access operators in PowerShell language"),
|
||||
#if !UNIX
|
||||
new ExperimentalFeature(
|
||||
name: "PSWindowsPowerShellCompatibility",
|
||||
description: "Load non-PSCore-compartible modules into Windows PowerShell over PS Remoting")
|
||||
#endif
|
||||
};
|
||||
EngineExperimentalFeatures = new ReadOnlyCollection<ExperimentalFeature>(engineFeatures);
|
||||
|
||||
|
||||
@@ -4426,7 +4426,7 @@ end {
|
||||
internal const ActionPreference DefaultWarningPreference = ActionPreference.Continue;
|
||||
internal const ActionPreference DefaultInformationPreference = ActionPreference.SilentlyContinue;
|
||||
|
||||
internal const ErrorView DefaultErrorView = ErrorView.NormalView;
|
||||
internal const ErrorView DefaultErrorView = ErrorView.ConciseView;
|
||||
internal const bool DefaultWhatIfPreference = false;
|
||||
internal const ConfirmImpact DefaultConfirmPreference = ConfirmImpact.High;
|
||||
|
||||
@@ -4501,7 +4501,7 @@ end {
|
||||
new ArgumentTypeConverterAttribute(typeof(ActionPreference))),
|
||||
new SessionStateVariableEntry(
|
||||
SpecialVariables.ErrorView,
|
||||
ExperimentalFeature.IsEnabled("PSErrorView") ? ErrorView.ConciseView : DefaultErrorView,
|
||||
DefaultErrorView,
|
||||
RunspaceInit.ErrorViewDescription,
|
||||
ScopedItemOptions.None,
|
||||
new ArgumentTypeConverterAttribute(typeof(ErrorView))),
|
||||
|
||||
@@ -234,7 +234,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// <summary>
|
||||
/// Gets or sets a script block to run in parallel for each pipeline object.
|
||||
/// </summary>
|
||||
[Experimental("PSForEachObjectParallel", ExperimentAction.Show)]
|
||||
[Parameter(Mandatory = true, ParameterSetName = ForEachObjectCommand.ParallelParameterSet)]
|
||||
public ScriptBlock Parallel { get; set; }
|
||||
|
||||
@@ -242,7 +241,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// Gets or sets the maximum number of concurrently running scriptblocks on separate threads.
|
||||
/// The default number is 5.
|
||||
/// </summary>
|
||||
[Experimental("PSForEachObjectParallel", ExperimentAction.Show)]
|
||||
[Parameter(ParameterSetName = ForEachObjectCommand.ParallelParameterSet)]
|
||||
[ValidateRange(1, Int32.MaxValue)]
|
||||
public int ThrottleLimit { get; set; } = 5;
|
||||
@@ -251,7 +249,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// Gets or sets a timeout time in seconds, after which the parallel running scripts will be stopped
|
||||
/// The default value is 0, indicating no timeout.
|
||||
/// </summary>
|
||||
[Experimental("PSForEachObjectParallel", ExperimentAction.Show)]
|
||||
[Parameter(ParameterSetName = ForEachObjectCommand.ParallelParameterSet)]
|
||||
[ValidateRange(0, (Int32.MaxValue / 1000))]
|
||||
public int TimeoutSeconds { get; set; }
|
||||
@@ -260,7 +257,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// Gets or sets a flag that returns a job object immediately for the parallel operation, instead of returning after
|
||||
/// all foreach processing is completed.
|
||||
/// </summary>
|
||||
[Experimental("PSForEachObjectParallel", ExperimentAction.Show)]
|
||||
[Parameter(ParameterSetName = ForEachObjectCommand.ParallelParameterSet)]
|
||||
public SwitchParameter AsJob { get; set; }
|
||||
|
||||
|
||||
@@ -103,12 +103,6 @@ namespace System.Management.Automation
|
||||
var moduleManifestProperties = PsUtils.GetModuleManifestProperties(modulePath, PsUtils.FastModuleManifestAnalysisPropertyNames);
|
||||
if (moduleManifestProperties != null)
|
||||
{
|
||||
if (!ExperimentalFeature.IsEnabled("PSWindowsPowerShellCompatibility") && ModuleIsEditionIncompatible(modulePath, moduleManifestProperties))
|
||||
{
|
||||
ModuleIntrinsics.Tracer.WriteLine($"Module lies on the Windows System32 legacy module path and is incompatible with current PowerShell edition, skipping module: {modulePath}");
|
||||
return null;
|
||||
}
|
||||
|
||||
Version version;
|
||||
if (ModuleUtils.IsModuleInVersionSubdirectory(modulePath, out version))
|
||||
{
|
||||
@@ -491,14 +485,6 @@ namespace System.Management.Automation
|
||||
{
|
||||
ModuleIntrinsics.Tracer.WriteLine("Requested caching for {0}", module.Name);
|
||||
|
||||
// Don't cache incompatible modules on the system32 module path even if loaded with
|
||||
// -SkipEditionCheck, since it will break subsequent sessions.
|
||||
if (!ExperimentalFeature.IsEnabled("PSWindowsPowerShellCompatibility") && !module.IsConsideredEditionCompatible)
|
||||
{
|
||||
ModuleIntrinsics.Tracer.WriteLine($"Module '{module.Name}' not edition compatible and not cached.");
|
||||
return;
|
||||
}
|
||||
|
||||
DateTime lastWriteTime;
|
||||
ModuleCacheEntry moduleCacheEntry;
|
||||
GetModuleEntryFromCache(module.Path, out lastWriteTime, out moduleCacheEntry);
|
||||
|
||||
@@ -53,7 +53,6 @@ namespace Microsoft.PowerShell.Commands
|
||||
private const string ParameterSet_FQName_ViaPsrpSession = "FullyQualifiedNameAndPSSession";
|
||||
private const string ParameterSet_ViaWinCompat = "WinCompat";
|
||||
private const string ParameterSet_FQName_ViaWinCompat = "FullyQualifiedNameAndWinCompat";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// This parameter specifies whether to import to the current session state
|
||||
@@ -85,7 +84,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
[Parameter(ParameterSetName = ParameterSet_Name, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaPsrpSession, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaCimSession, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_ViaWinCompat, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaWinCompat, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[ValidateTrustedData]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")]
|
||||
public string[] Name { set; get; } = Array.Empty<string>();
|
||||
@@ -95,7 +94,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// </summary>
|
||||
[Parameter(ParameterSetName = ParameterSet_FQName, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter(ParameterSetName = ParameterSet_FQName_ViaPsrpSession, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_FQName_ViaWinCompat, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[Parameter(ParameterSetName = ParameterSet_FQName_ViaWinCompat, Mandatory = true, ValueFromPipeline = true, Position = 0)]
|
||||
[ValidateTrustedData]
|
||||
[SuppressMessage("Microsoft.Performance", "CA1819:PropertiesShouldNotReturnArrays", Justification = "Cmdlets use arrays for parameters.")]
|
||||
public ModuleSpecification[] FullyQualifiedName { get; set; }
|
||||
@@ -275,7 +274,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
[Parameter(ParameterSetName = ParameterSet_Name)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaPsrpSession)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaCimSession)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
[Alias("Version")]
|
||||
public Version MinimumVersion
|
||||
{
|
||||
@@ -290,7 +289,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
[Parameter(ParameterSetName = ParameterSet_Name)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaPsrpSession)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaCimSession)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
public string MaximumVersion
|
||||
{
|
||||
get
|
||||
@@ -320,7 +319,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
[Parameter(ParameterSetName = ParameterSet_Name)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaPsrpSession)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaCimSession)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaWinCompat)]
|
||||
public Version RequiredVersion
|
||||
{
|
||||
get { return BaseRequiredVersion; }
|
||||
@@ -425,8 +424,8 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// This parameter causes a module to be loaded into Windows PowerShell.
|
||||
/// This is mutually exclusive with SkipEditionCheck parameter.
|
||||
/// </summary>
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_ViaWinCompat, Mandatory = true)]
|
||||
[Parameter("PSWindowsPowerShellCompatibility", ExperimentAction.Show, ParameterSetName = ParameterSet_FQName_ViaWinCompat, Mandatory = true)]
|
||||
[Parameter(ParameterSetName = ParameterSet_ViaWinCompat, Mandatory = true)]
|
||||
[Parameter(ParameterSetName = ParameterSet_FQName_ViaWinCompat, Mandatory = true)]
|
||||
[Alias("UseWinPS")]
|
||||
public SwitchParameter UseWindowsPowerShell { get; set; }
|
||||
|
||||
|
||||
@@ -293,7 +293,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
/// Session name for WindowsPS compat remoting session.
|
||||
/// </summary>
|
||||
internal const string WindowsPowerShellCompatRemotingSessionName = "WinPSCompatSession";
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Synchronization object for creation/cleanup of WindowsPS compat remoting session.
|
||||
/// </summary>
|
||||
@@ -2363,62 +2363,18 @@ namespace Microsoft.PowerShell.Commands
|
||||
bool isConsideredCompatible = ModuleUtils.IsPSEditionCompatible(moduleManifestPath, inferredCompatiblePSEditions);
|
||||
if (!BaseSkipEditionCheck && !isConsideredCompatible)
|
||||
{
|
||||
if (ExperimentalFeature.IsEnabled("PSWindowsPowerShellCompatibility"))
|
||||
if (importingModule)
|
||||
{
|
||||
if (importingModule)
|
||||
{
|
||||
IList<PSModuleInfo> moduleProxies = ImportModulesUsingWinCompat(new string [] {moduleManifestPath}, null, new ImportModuleOptions());
|
||||
IList<PSModuleInfo> moduleProxies = ImportModulesUsingWinCompat(new string [] {moduleManifestPath}, null, new ImportModuleOptions());
|
||||
|
||||
// we are loading by a single ManifestPath so expect max of 1
|
||||
if(moduleProxies.Count > 0)
|
||||
{
|
||||
return moduleProxies[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
// we are loading by a single ManifestPath so expect max of 1
|
||||
if(moduleProxies.Count > 0)
|
||||
{
|
||||
return moduleProxies[0];
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
containedErrors = true;
|
||||
|
||||
if (writingErrors)
|
||||
else
|
||||
{
|
||||
message = StringUtil.Format(
|
||||
Modules.PSEditionNotSupported,
|
||||
moduleManifestPath,
|
||||
PSVersionInfo.PSEdition,
|
||||
string.Join(',', inferredCompatiblePSEditions));
|
||||
|
||||
InvalidOperationException ioe = new InvalidOperationException(message);
|
||||
|
||||
ErrorRecord er = new ErrorRecord(
|
||||
ioe,
|
||||
nameof(Modules) + "_" + nameof(Modules.PSEditionNotSupported),
|
||||
ErrorCategory.ResourceUnavailable,
|
||||
moduleManifestPath);
|
||||
|
||||
WriteError(er);
|
||||
}
|
||||
|
||||
if (bailOnFirstError)
|
||||
{
|
||||
// If we're trying to load the module, return null so that caches
|
||||
// are not polluted
|
||||
if (importingModule)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// If we return null with Get-Module, a fake module info will be created. Since
|
||||
// we want to suppress output of the module, we need to do that here.
|
||||
return new PSModuleInfo(moduleManifestPath, context: null, sessionState: null)
|
||||
{
|
||||
HadErrorsLoading = true,
|
||||
IsConsideredEditionCompatible = false,
|
||||
};
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -4954,7 +4910,7 @@ namespace Microsoft.PowerShell.Commands
|
||||
}
|
||||
}
|
||||
|
||||
if (ExperimentalFeature.IsEnabled("PSWindowsPowerShellCompatibility") && module.IsWindowsPowerShellCompatModule && (System.Threading.Interlocked.Decrement(ref s_WindowsPowerShellCompatUsageCounter) == 0))
|
||||
if (module.IsWindowsPowerShellCompatModule && (System.Threading.Interlocked.Decrement(ref s_WindowsPowerShellCompatUsageCounter) == 0))
|
||||
{
|
||||
CleanupWindowsPowerShellCompatResources();
|
||||
}
|
||||
|
||||
@@ -955,7 +955,7 @@ namespace System.Management.Automation.Language
|
||||
case TokenKind.MultiplyEquals: et = ExpressionType.Multiply; break;
|
||||
case TokenKind.DivideEquals: et = ExpressionType.Divide; break;
|
||||
case TokenKind.RemainderEquals: et = ExpressionType.Modulo; break;
|
||||
case TokenKind.QuestionQuestionEquals when ExperimentalFeature.IsEnabled("PSCoalescingOperators"): et = ExpressionType.Coalesce; break;
|
||||
case TokenKind.QuestionQuestionEquals: et = ExpressionType.Coalesce; break;
|
||||
}
|
||||
|
||||
var exprs = new List<Expression>();
|
||||
@@ -5896,7 +5896,7 @@ namespace System.Management.Automation.Language
|
||||
lhs.Cast(typeof(object)),
|
||||
rhs.Cast(typeof(object)),
|
||||
ExpressionCache.Constant(false));
|
||||
case TokenKind.QuestionQuestion when ExperimentalFeature.IsEnabled("PSCoalescingOperators"):
|
||||
case TokenKind.QuestionQuestion:
|
||||
return Coalesce(lhs, rhs);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,8 +35,6 @@ namespace System.Management.Automation.Language
|
||||
/// </summary>
|
||||
public sealed class Parser
|
||||
{
|
||||
private static readonly bool s_pipelineChainsEnabled = ExperimentalFeature.IsEnabled("PSPipelineChainOperators");
|
||||
|
||||
private readonly Tokenizer _tokenizer;
|
||||
internal Token _ungotToken;
|
||||
private bool _disableCommaOperator;
|
||||
@@ -5715,11 +5713,6 @@ namespace System.Management.Automation.Language
|
||||
|
||||
// If this feature is not enabled,
|
||||
// just look for pipelines as before.
|
||||
if (!s_pipelineChainsEnabled)
|
||||
{
|
||||
return PipelineRule(allowBackground: true);
|
||||
}
|
||||
|
||||
RuntimeHelpers.EnsureSufficientExecutionStack();
|
||||
|
||||
// First look for assignment, since PipelineRule once handled that and this supercedes that.
|
||||
@@ -5950,7 +5943,6 @@ namespace System.Management.Automation.Language
|
||||
while (scanning)
|
||||
{
|
||||
CommandBaseAst commandAst;
|
||||
Token assignToken = null;
|
||||
|
||||
if (expr == null)
|
||||
{
|
||||
@@ -5960,21 +5952,6 @@ namespace System.Management.Automation.Language
|
||||
{
|
||||
SetTokenizerMode(TokenizerMode.Expression);
|
||||
expr = ExpressionRule();
|
||||
|
||||
// When pipeline chains are not enabled, we must process assignment.
|
||||
// We are looking for <expr> = <statement>, and have seen <expr>.
|
||||
// Now looking for '='
|
||||
if (!s_pipelineChainsEnabled && expr != null)
|
||||
{
|
||||
// We peek here because we are in expression mode,
|
||||
// otherwise =0 will get scanned as a single token.
|
||||
Token token = PeekToken();
|
||||
if (token.Kind.HasTrait(TokenFlags.AssignmentOperator))
|
||||
{
|
||||
SkipToken();
|
||||
assignToken = token;
|
||||
}
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
@@ -5993,35 +5970,6 @@ namespace System.Management.Automation.Language
|
||||
ParserStrings.ExpressionsMustBeFirstInPipeline);
|
||||
}
|
||||
|
||||
// To process assignment when pipeline chains are not enabled,
|
||||
// we have seen '<expr> = ' and now expect a statement
|
||||
if (!s_pipelineChainsEnabled && assignToken != null)
|
||||
{
|
||||
SkipNewlines();
|
||||
StatementAst statement = StatementRule();
|
||||
|
||||
if (statement == null)
|
||||
{
|
||||
// ErrorRecovery:
|
||||
// We are likely at EOF, since almost anything else should result in a pipeline,
|
||||
// so just keep parsing
|
||||
IScriptExtent errorExtent = After(assignToken);
|
||||
ReportIncompleteInput(
|
||||
errorExtent,
|
||||
nameof(ParserStrings.ExpectedValueExpression),
|
||||
ParserStrings.ExpectedValueExpression,
|
||||
assignToken.Kind.Text());
|
||||
statement = new ErrorStatementAst(errorExtent);
|
||||
}
|
||||
|
||||
return new AssignmentStatementAst(
|
||||
ExtentOf(expr, statement),
|
||||
expr,
|
||||
assignToken.Kind,
|
||||
statement,
|
||||
assignToken.Extent);
|
||||
}
|
||||
|
||||
RedirectionAst[] redirections = null;
|
||||
var redirectionToken = PeekToken() as RedirectionToken;
|
||||
RedirectionAst lastRedirection = null;
|
||||
@@ -6098,31 +6046,11 @@ namespace System.Management.Automation.Language
|
||||
|
||||
case TokenKind.AndAnd:
|
||||
case TokenKind.OrOr:
|
||||
if (s_pipelineChainsEnabled)
|
||||
{
|
||||
scanning = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
// Report that &&/|| are unsupported
|
||||
SkipToken();
|
||||
SkipNewlines();
|
||||
ReportError(
|
||||
nextToken.Extent,
|
||||
nameof(ParserStrings.InvalidEndOfLine),
|
||||
ParserStrings.InvalidEndOfLine,
|
||||
nextToken.Text);
|
||||
|
||||
if (PeekToken().Kind == TokenKind.EndOfInput)
|
||||
{
|
||||
scanning = false;
|
||||
}
|
||||
|
||||
break;
|
||||
scanning = false;
|
||||
continue;
|
||||
|
||||
case TokenKind.Ampersand:
|
||||
// When pipeline chains are not enabled, pipelines always handle backgrounding
|
||||
if (s_pipelineChainsEnabled && !allowBackground)
|
||||
if (!allowBackground)
|
||||
{
|
||||
// Handled by invoking rule
|
||||
scanning = false;
|
||||
@@ -6720,12 +6648,6 @@ namespace System.Management.Automation.Language
|
||||
// G ternary-expression:
|
||||
// G binary-expression '?' new-lines:opt ternary-expression new-lines:opt ':' new-lines:opt ternary-expression
|
||||
|
||||
// TODO: remove this if-block when making 'ternary operator' an official feature.
|
||||
if (!ExperimentalFeature.IsEnabled("PSTernaryOperator"))
|
||||
{
|
||||
return BinaryExpressionRule();
|
||||
}
|
||||
|
||||
RuntimeHelpers.EnsureSufficientExecutionStack();
|
||||
var oldTokenizerMode = _tokenizer.Mode;
|
||||
try
|
||||
|
||||
@@ -727,7 +727,7 @@ namespace System.Management.Automation.Language
|
||||
internal bool ForceEndNumberOnTernaryOpChars
|
||||
{
|
||||
get { return _forceEndNumberOnTernaryOpChars; }
|
||||
set { _forceEndNumberOnTernaryOpChars = value && ExperimentalFeature.IsEnabled("PSTernaryOperator"); }
|
||||
set { _forceEndNumberOnTernaryOpChars = value; }
|
||||
}
|
||||
|
||||
internal bool WantSimpleName { get; set; }
|
||||
@@ -5015,23 +5015,20 @@ namespace System.Management.Automation.Language
|
||||
return this.NewToken(TokenKind.Colon);
|
||||
|
||||
case '?' when InExpressionMode():
|
||||
if (ExperimentalFeature.IsEnabled("PSCoalescingOperators"))
|
||||
c1 = PeekChar();
|
||||
|
||||
if (c1 == '?')
|
||||
{
|
||||
SkipChar();
|
||||
c1 = PeekChar();
|
||||
|
||||
if (c1 == '?')
|
||||
if (c1 == '=')
|
||||
{
|
||||
SkipChar();
|
||||
c1 = PeekChar();
|
||||
|
||||
if (c1 == '=')
|
||||
{
|
||||
SkipChar();
|
||||
return this.NewToken(TokenKind.QuestionQuestionEquals);
|
||||
}
|
||||
|
||||
return this.NewToken(TokenKind.QuestionQuestion);
|
||||
return this.NewToken(TokenKind.QuestionQuestionEquals);
|
||||
}
|
||||
|
||||
return this.NewToken(TokenKind.QuestionQuestion);
|
||||
}
|
||||
|
||||
return this.NewToken(TokenKind.QuestionMark);
|
||||
|
||||
@@ -161,11 +161,10 @@ namespace Microsoft.PowerShell.Commands
|
||||
[Parameter(ValueFromPipelineByPropertyName = true,
|
||||
ParameterSetName = NewPSSessionCommand.VMNameParameterSet)]
|
||||
public string ConfigurationName { get; set; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets parameter value that creates connection to a Windows PowerShell process.
|
||||
/// </summary>
|
||||
[Experimental("PSWindowsPowerShellCompatibility", ExperimentAction.Show)]
|
||||
[Parameter(Mandatory = true, ParameterSetName = NewPSSessionCommand.UseWindowsPowerShellParameterSet)]
|
||||
public SwitchParameter UseWindowsPowerShell { get; set; }
|
||||
|
||||
|
||||
@@ -3,30 +3,15 @@
|
||||
|
||||
Describe 'NullCoalesceOperations' -Tags 'CI' {
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSCoalescingOperators')
|
||||
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSCoalescingOperators' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
} else {
|
||||
$someGuid = New-Guid
|
||||
$typesTests = @(
|
||||
@{ name = 'string'; valueToSet = 'hello' }
|
||||
@{ name = 'dotnetType'; valueToSet = $someGuid }
|
||||
@{ name = 'byte'; valueToSet = [byte]0x94 }
|
||||
@{ name = 'intArray'; valueToSet = 1..2 }
|
||||
@{ name = 'stringArray'; valueToSet = 'a'..'c' }
|
||||
@{ name = 'emptyArray'; valueToSet = @(1, 2, 3) }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
$someGuid = New-Guid
|
||||
$typesTests = @(
|
||||
@{ name = 'string'; valueToSet = 'hello' }
|
||||
@{ name = 'dotnetType'; valueToSet = $someGuid }
|
||||
@{ name = 'byte'; valueToSet = [byte]0x94 }
|
||||
@{ name = 'intArray'; valueToSet = 1..2 }
|
||||
@{ name = 'stringArray'; valueToSet = 'a'..'c' }
|
||||
@{ name = 'emptyArray'; valueToSet = @(1, 2, 3) }
|
||||
)
|
||||
}
|
||||
|
||||
Context "Null conditional assignment operator ??=" {
|
||||
|
||||
@@ -3,15 +3,6 @@
|
||||
|
||||
Describe "Experimental Feature: && and || operators - Feature-Enabled" -Tag CI {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSPipelineChainOperators')
|
||||
if ($skipTest)
|
||||
{
|
||||
Write-Verbose "Test Suite Skipped: These tests require the PSPipelineChainOperators experimental feature to be enabled" -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
return
|
||||
}
|
||||
|
||||
function Test-SuccessfulCommand
|
||||
{
|
||||
Write-Output "SUCCESS"
|
||||
@@ -135,12 +126,6 @@ Describe "Experimental Feature: && and || operators - Feature-Enabled" -Tag CI {
|
||||
)
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It "Gets the correct output with statement '<Statement>'" -TestCases $simpleTestCases {
|
||||
param($Statement, $Output)
|
||||
|
||||
|
||||
@@ -3,54 +3,46 @@
|
||||
|
||||
Describe "Using of ternary operator" -Tags CI {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSTernaryOperator')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSTernaryOperator' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
else {
|
||||
$testCases = @(
|
||||
## Condition: variable and constant expressions
|
||||
@{ Script = { $true ? 1 : 2 }; ExpectedValue = 1 }
|
||||
@{ Script = { $true? ?1 :2 }; ExpectedValue = 2 }
|
||||
@{ Script = { ${true}?1:2 }; ExpectedValue = 1 }
|
||||
@{ Script = { 1 ? 1kb : 0xf }; ExpectedValue = 1kb }
|
||||
@{ Script = { 0 ?1kb:0xf }; ExpectedValue = 15 }
|
||||
@{ Script = { 's' ?1kb:0xf }; ExpectedValue = 1kb }
|
||||
@{ Script = { $null ?1kb:0xf }; ExpectedValue = 15 }
|
||||
@{ Script = { '' ?1kb:0xf }; ExpectedValue = 15 }
|
||||
$testCases = @(
|
||||
## Condition: variable and constant expressions
|
||||
@{ Script = { $true ? 1 : 2 }; ExpectedValue = 1 }
|
||||
@{ Script = { $true? ?1 :2 }; ExpectedValue = 2 }
|
||||
@{ Script = { ${true}?1:2 }; ExpectedValue = 1 }
|
||||
@{ Script = { 1 ? 1kb : 0xf }; ExpectedValue = 1kb }
|
||||
@{ Script = { 0 ?1kb:0xf }; ExpectedValue = 15 }
|
||||
@{ Script = { 's' ?1kb:0xf }; ExpectedValue = 1kb }
|
||||
@{ Script = { $null ?1kb:0xf }; ExpectedValue = 15 }
|
||||
@{ Script = { '' ?1kb:0xf }; ExpectedValue = 15 }
|
||||
|
||||
## Condition: other primary expressions
|
||||
@{ Script = { 1,2,3,4 ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @(1,2,3,4) ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'} ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'}.name ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'}.Contains('name') ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { (Test-Path Env:\NonExist) ? 'true' : 'false' }; ExpectedValue = 'false' }
|
||||
@{ Script = { (Test-Path Env:\PSModulePath) ? 'true' : 'false' }; ExpectedValue = 'true' }
|
||||
@{ Script = { $($p = Get-Process -Id $PID; $p.Name -eq 'pwsh') ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { ($a = 1) ? 2 : 3 }; ExpectedValue = 2 }
|
||||
@{ Script = { $($a = 1) ? 2 : 3 }; ExpectedValue = 3 }
|
||||
@{ Script = { (Write-Warning -Message warning -WarningAction SilentlyContinue) ? 1 : 2 }; ExpectedValue = 2 }
|
||||
@{ Script = { (Write-Error -Message error -ErrorAction SilentlyContinue) ? 1 : 2 }; ExpectedValue = 2 }
|
||||
## Condition: other primary expressions
|
||||
@{ Script = { 1,2,3,4 ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @(1,2,3,4) ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'} ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'}.name ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { @{name = 'name'}.Contains('name') ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { (Test-Path Env:\NonExist) ? 'true' : 'false' }; ExpectedValue = 'false' }
|
||||
@{ Script = { (Test-Path Env:\PSModulePath) ? 'true' : 'false' }; ExpectedValue = 'true' }
|
||||
@{ Script = { $($p = Get-Process -Id $PID; $p.Name -eq 'pwsh') ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { ($a = 1) ? 2 : 3 }; ExpectedValue = 2 }
|
||||
@{ Script = { $($a = 1) ? 2 : 3 }; ExpectedValue = 3 }
|
||||
@{ Script = { (Write-Warning -Message warning -WarningAction SilentlyContinue) ? 1 : 2 }; ExpectedValue = 2 }
|
||||
@{ Script = { (Write-Error -Message error -ErrorAction SilentlyContinue) ? 1 : 2 }; ExpectedValue = 2 }
|
||||
|
||||
## Condition: unary and binary expression expressions
|
||||
@{ Script = { -not $IsCoreCLR ? 'Desktop' : 'Core' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $PSEdition -eq 'Core' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $IsCoreCLR -and (Get-Process -Id $PID).Name -eq 'pwsh' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $IsCoreCLR -and 'pwsh' -match 'p.*h' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { 1,2,3 -contains 2 ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
## Condition: unary and binary expression expressions
|
||||
@{ Script = { -not $IsCoreCLR ? 'Desktop' : 'Core' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $PSEdition -eq 'Core' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $IsCoreCLR -and (Get-Process -Id $PID).Name -eq 'pwsh' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { $IsCoreCLR -and 'pwsh' -match 'p.*h' ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
@{ Script = { 1,2,3 -contains 2 ? 'Core' : 'Desktop' }; ExpectedValue = 'Core' }
|
||||
|
||||
## Nested ternary expressions
|
||||
@{ Script = { $IsCoreCLR ? $false ? 'nested-if-true' : 'nested-if-false' : 'if-false' }; ExpectedValue = 'nested-if-false' }
|
||||
@{ Script = { $IsCoreCLR ? $false ? 'nested-if-true' : $true ? 'nested-nested-if-true' : 'nested-nested-if-false' : 'if-false' }; ExpectedValue = 'nested-nested-if-true' }
|
||||
## Nested ternary expressions
|
||||
@{ Script = { $IsCoreCLR ? $false ? 'nested-if-true' : 'nested-if-false' : 'if-false' }; ExpectedValue = 'nested-if-false' }
|
||||
@{ Script = { $IsCoreCLR ? $false ? 'nested-if-true' : $true ? 'nested-nested-if-true' : 'nested-nested-if-false' : 'if-false' }; ExpectedValue = 'nested-nested-if-true' }
|
||||
|
||||
## Binary operator has higher precedence order than ternary
|
||||
@{ Script = { !$IsCoreCLR ? 'Core' : 'Desktop' -eq 'Core' }; ExpectedValue = !$IsCoreCLR ? 'Core' : ('Desktop' -eq 'Core') }
|
||||
@{ Script = { ($IsCoreCLR ? 'Core' : 'Desktop') -eq 'Core' }; ExpectedValue = $true }
|
||||
)
|
||||
}
|
||||
## Binary operator has higher precedence order than ternary
|
||||
@{ Script = { !$IsCoreCLR ? 'Core' : 'Desktop' -eq 'Core' }; ExpectedValue = !$IsCoreCLR ? 'Core' : ('Desktop' -eq 'Core') }
|
||||
@{ Script = { ($IsCoreCLR ? 'Core' : 'Desktop') -eq 'Core' }; ExpectedValue = $true }
|
||||
)
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
@@ -263,21 +263,6 @@ Describe 'assignment statement parsing' -Tags "CI" {
|
||||
}
|
||||
|
||||
Describe 'null coalescing assignment statement parsing' -Tag 'CI' {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSCoalescingOperators')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSCoalescingOperators' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
ShouldBeParseError '1 ??= 1' InvalidLeftHandSide 0
|
||||
ShouldBeParseError '@() ??= 1' InvalidLeftHandSide 0
|
||||
ShouldBeParseError '@{} ??= 1' InvalidLeftHandSide 0
|
||||
@@ -287,21 +272,6 @@ Describe 'null coalescing assignment statement parsing' -Tag 'CI' {
|
||||
}
|
||||
|
||||
Describe 'null coalescing statement parsing' -Tag "CI" {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSCoalescingOperators')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSCoalescingOperators' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
ShouldBeParseError '$x??=' ExpectedValueExpression 5
|
||||
ShouldBeParseError '$x ??Get-Thing' ExpectedValueExpression,UnexpectedToken 5,5
|
||||
ShouldBeParseError '$??=$false' ExpectedValueExpression,InvalidLeftHandSide 3,0
|
||||
@@ -393,42 +363,28 @@ Describe 'Unicode escape sequence parsing' -Tag "CI" {
|
||||
|
||||
Describe "Ternary Operator parsing" -Tags CI {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSTernaryOperator')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSTernaryOperator' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
else {
|
||||
$testCases_basic = @(
|
||||
@{ Script = '$true?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$false?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$:abc'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$env:abc'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$env:123'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = 'a?2:2'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '1?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = 'a?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = 'a?b'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '1?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
)
|
||||
$testCases_basic = @(
|
||||
@{ Script = '$true?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$false?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$:abc'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$env:abc'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = '$env:123'; TokenKind = [System.Management.Automation.Language.TokenKind]::Variable; }
|
||||
@{ Script = 'a?2:2'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '1?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = 'a?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = 'a?b'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '1?'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
@{ Script = '?2:3'; TokenKind = [System.Management.Automation.Language.TokenKind]::Generic; }
|
||||
)
|
||||
|
||||
$testCases_incomplete = @(
|
||||
@{ Script = '$true ?'; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = '$true ? 3'; ErrorId = "MissingColonInTernaryExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = '$true ? 3 :'; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.TernaryExpressionAst] }
|
||||
@{ Script = "`$true`t?"; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = "`$true`t?`t3"; ErrorId = "MissingColonInTernaryExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = "`$true`t?`t3`t:"; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.TernaryExpressionAst] }
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
$testCases_incomplete = @(
|
||||
@{ Script = '$true ?'; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = '$true ? 3'; ErrorId = "MissingColonInTernaryExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = '$true ? 3 :'; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.TernaryExpressionAst] }
|
||||
@{ Script = "`$true`t?"; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = "`$true`t?`t3"; ErrorId = "MissingColonInTernaryExpression"; AstType = [System.Management.Automation.Language.ErrorExpressionAst] }
|
||||
@{ Script = "`$true`t?`t3`t:"; ErrorId = "ExpectedValueExpression"; AstType = [System.Management.Automation.Language.TernaryExpressionAst] }
|
||||
)
|
||||
}
|
||||
|
||||
It "Question-mark and colon parsed correctly in <Script> when not in ternary expression context" -TestCases $testCases_basic {
|
||||
|
||||
-17
@@ -885,23 +885,6 @@ try
|
||||
|
||||
Describe "ForEach-Object -Parallel Constrained Language Tests" -Tags 'Feature','RequireAdminOnWindows' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSForEachObjectParallel')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSForEachObjectParallel' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It 'Foreach-Object -Parallel must run in ConstrainedLanguage mode under system lock down' {
|
||||
|
||||
try
|
||||
|
||||
+4
-65
@@ -4,23 +4,7 @@
|
||||
Describe 'ForEach-Object -Parallel Basic Tests' -Tags 'CI' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSForEachObjectParallel')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSForEachObjectParallel' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
else {
|
||||
$sb = { "Hello!" }
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
$sb = { "Hello!" }
|
||||
}
|
||||
|
||||
It "Verifies dollar underbar variable" {
|
||||
@@ -88,7 +72,7 @@ Describe 'ForEach-Object -Parallel Basic Tests' -Tags 'CI' {
|
||||
}
|
||||
|
||||
It 'Verifies debug data streaming' {
|
||||
|
||||
|
||||
$actualDebug = 1..1 | ForEach-Object -Parallel { Write-Debug "Debug!" -Debug } -Debug 5>&1
|
||||
$actualDebug.Message | Should -BeExactly 'Debug!'
|
||||
}
|
||||
@@ -105,7 +89,7 @@ Describe 'ForEach-Object -Parallel Basic Tests' -Tags 'CI' {
|
||||
}
|
||||
|
||||
It 'Verifies error for script block piped variable' {
|
||||
|
||||
|
||||
$actualError = $sb | ForEach-Object -Parallel { "Hello" } 2>&1
|
||||
$actualError.FullyQualifiedErrorId | Should -BeExactly 'ParallelPipedInputObjectCannotBeScriptBlock,Microsoft.PowerShell.Commands.ForEachObjectCommand'
|
||||
}
|
||||
@@ -126,13 +110,6 @@ Describe 'ForEach-Object -Parallel common parameters' -Tags 'CI' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSForEachObjectParallel')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSForEachObjectParallel' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
|
||||
# Test cases
|
||||
$TestCasesNotSupportedCommonParameters = @(
|
||||
@{
|
||||
@@ -182,10 +159,6 @@ Describe 'ForEach-Object -Parallel common parameters' -Tags 'CI' {
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
|
||||
$global:actualVariable = $null
|
||||
}
|
||||
|
||||
@@ -207,23 +180,6 @@ Describe 'ForEach-Object -Parallel common parameters' -Tags 'CI' {
|
||||
|
||||
Describe 'ForEach-Object -Parallel -AsJob Basic Tests' -Tags 'CI' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSForEachObjectParallel')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSForEachObjectParallel' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It 'Verifies TimeoutSeconds parameter is excluded from AsJob' {
|
||||
|
||||
{ 1..1 | ForEach-Object -AsJob -Parallel { "Hello" } -TimeoutSeconds 60 } | Should -Throw -ErrorId 'ParallelCannotUseTimeoutWithJob,Microsoft.PowerShell.Commands.ForEachObjectCommand'
|
||||
@@ -360,23 +316,6 @@ Describe 'ForEach-Object -Parallel -AsJob Basic Tests' -Tags 'CI' {
|
||||
|
||||
Describe 'ForEach-Object -Parallel Functional Tests' -Tags 'Feature' {
|
||||
|
||||
BeforeAll {
|
||||
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('PSForEachObjectParallel')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'PSForEachObjectParallel' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It 'Verifies job queuing and throttle limit' {
|
||||
|
||||
# Run four job tasks, two in parallel at a time.
|
||||
@@ -417,7 +356,7 @@ Describe 'ForEach-Object -Parallel Functional Tests' -Tags 'Feature' {
|
||||
|
||||
It 'Verifies timeout and throttle parameters' {
|
||||
|
||||
# With ThrottleLimit set to 1, the two 60 second long script blocks will run sequentially,
|
||||
# With ThrottleLimit set to 1, the two 60 second long script blocks will run sequentially,
|
||||
# until the timeout in 5 seconds.
|
||||
$results = 1..2 | ForEach-Object -Parallel { "Output $_"; Start-Sleep -Seconds 60 } -TimeoutSeconds 5 -ThrottleLimit 1 2>&1
|
||||
$results.Count | Should -BeExactly 2
|
||||
|
||||
@@ -2,21 +2,6 @@
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe 'Get-Error tests' -Tag CI {
|
||||
BeforeAll {
|
||||
$skipTest = -not $EnabledExperimentalFeatures.Contains('Microsoft.PowerShell.Utility.PSGetError')
|
||||
if ($skipTest) {
|
||||
Write-Verbose "Test Suite Skipped. The test suite requires the experimental feature 'Microsoft.PowerShell.Utility.PSGetError' to be enabled." -Verbose
|
||||
$originalDefaultParameterValues = $PSDefaultParameterValues.Clone()
|
||||
$PSDefaultParameterValues["it:skip"] = $true
|
||||
}
|
||||
}
|
||||
|
||||
AfterAll {
|
||||
if ($skipTest) {
|
||||
$global:PSDefaultParameterValues = $originalDefaultParameterValues
|
||||
}
|
||||
}
|
||||
|
||||
It 'Get-Error resolves $Error[0] and includes InnerException' {
|
||||
try {
|
||||
1/0
|
||||
|
||||
@@ -8,11 +8,7 @@ Describe 'Tests for $ErrorView' -Tag CI {
|
||||
}
|
||||
|
||||
It '$ErrorView should have correct default value' {
|
||||
$expectedDefault = 'NormalView'
|
||||
|
||||
if ((Get-ExperimentalFeature -Name PSErrorView).Enabled) {
|
||||
$expectedDefault = 'ConciseView'
|
||||
}
|
||||
$expectedDefault = 'ConciseView'
|
||||
|
||||
$ErrorView | Should -BeExactly $expectedDefault
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
{
|
||||
"ExperimentalFeatures": {
|
||||
"ExpTest.FeatureOne": [ "test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1" ],
|
||||
"PSForEachObjectParallel": [ "test/powershell/Modules/Microsoft.PowerShell.Utility/Foreach-Object-Parallel.Tests.ps1", "test/powershell/Modules/Microsoft.PowerShell.Security/ConstrainedLanguageRestriction.Tests.ps1" ],
|
||||
"PSPipelineChainOperators": [ "test/powershell/Language/Operators/PipelineChainOperator.Tests.ps1" ]
|
||||
"ExpTest.FeatureOne": [ "test/powershell/engine/ExperimentalFeature/ExperimentalFeature.Basic.Tests.ps1" ]
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user