mirror of
https://github.com/PowerShell/PowerShell
synced 2026-06-08 12:12:50 +00:00
Add PSForEach and PSWhere as aliases for the PowerShell intrinsic methods Where and Foreach (#25511)
This commit is contained in:
@@ -6455,7 +6455,9 @@ namespace System.Management.Automation
|
||||
new List<Tuple<string, string>>
|
||||
{
|
||||
new Tuple<string, string>("Where", "Where({ expression } [, mode [, numberToReturn]])"),
|
||||
new Tuple<string, string>("ForEach", "ForEach(expression [, arguments...])")
|
||||
new Tuple<string, string>("ForEach", "ForEach(expression [, arguments...])"),
|
||||
new Tuple<string, string>("PSWhere", "PSWhere({ expression } [, mode [, numberToReturn]])"),
|
||||
new Tuple<string, string>("PSForEach", "PSForEach(expression [, arguments...])"),
|
||||
};
|
||||
|
||||
// List of DSC collection-value variables
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// Copyright (c) Microsoft Corporation.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Buffers;
|
||||
using System.Collections;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
@@ -6533,6 +6534,14 @@ namespace System.Management.Automation.Language
|
||||
|
||||
internal sealed class PSInvokeMemberBinder : InvokeMemberBinder
|
||||
{
|
||||
private static readonly SearchValues<string> s_whereSearchValues = SearchValues.Create(
|
||||
["Where", "PSWhere"],
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
private static readonly SearchValues<string> s_foreachSearchValues = SearchValues.Create(
|
||||
["ForEach", "PSForEach"],
|
||||
StringComparison.OrdinalIgnoreCase);
|
||||
|
||||
internal enum MethodInvocationType
|
||||
{
|
||||
Ordinary,
|
||||
@@ -6681,12 +6690,14 @@ namespace System.Management.Automation.Language
|
||||
.WriteToDebugLog(this);
|
||||
BindingRestrictions argRestrictions = args.Aggregate(BindingRestrictions.Empty, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction()));
|
||||
|
||||
if (string.Equals(Name, "Where", StringComparison.OrdinalIgnoreCase))
|
||||
// We need to pass the empty enumerator to the ForEach/Where operators, so that they can return an empty collection.
|
||||
// The ForEach/Where operators will not be able to call the script block if the enumerator is empty.
|
||||
if (s_whereSearchValues.Contains(Name))
|
||||
{
|
||||
return InvokeWhereOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
|
||||
}
|
||||
|
||||
if (string.Equals(Name, "ForEach", StringComparison.OrdinalIgnoreCase))
|
||||
if (s_foreachSearchValues.Contains(Name))
|
||||
{
|
||||
return InvokeForEachOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
|
||||
}
|
||||
@@ -6866,12 +6877,12 @@ namespace System.Management.Automation.Language
|
||||
if (!_static && !_nonEnumerating && target.Value != AutomationNull.Value)
|
||||
{
|
||||
// Invoking Where and ForEach operators on collections.
|
||||
if (string.Equals(Name, "Where", StringComparison.OrdinalIgnoreCase))
|
||||
if (s_whereSearchValues.Contains(Name))
|
||||
{
|
||||
return InvokeWhereOnCollection(target, args, restrictions).WriteToDebugLog(this);
|
||||
}
|
||||
|
||||
if (string.Equals(Name, "ForEach", StringComparison.OrdinalIgnoreCase))
|
||||
if (s_foreachSearchValues.Contains(Name))
|
||||
{
|
||||
return InvokeForEachOnCollection(target, args, restrictions).WriteToDebugLog(this);
|
||||
}
|
||||
@@ -7490,7 +7501,7 @@ namespace System.Management.Automation.Language
|
||||
// As a last resort, we invoke 'Where' and 'ForEach' operators on singletons like
|
||||
// ([pscustomobject]@{ foo = 'bar' }).Foreach({$_})
|
||||
// ([pscustomobject]@{ foo = 'bar' }).Where({1})
|
||||
if (string.Equals(methodName, "Where", StringComparison.OrdinalIgnoreCase))
|
||||
if (s_whereSearchValues.Contains(methodName))
|
||||
{
|
||||
var enumerator = (new object[] { obj }).GetEnumerator();
|
||||
switch (args.Length)
|
||||
@@ -7506,7 +7517,7 @@ namespace System.Management.Automation.Language
|
||||
}
|
||||
}
|
||||
|
||||
if (string.Equals(methodName, "Foreach", StringComparison.OrdinalIgnoreCase))
|
||||
if (s_foreachSearchValues.Contains(methodName))
|
||||
{
|
||||
var enumerator = (new object[] { obj }).GetEnumerator();
|
||||
object[] argsToPass;
|
||||
|
||||
@@ -200,6 +200,11 @@ Describe "Adapter Tests" -tags "CI" {
|
||||
|
||||
# TODO: dynamic method calls
|
||||
}
|
||||
|
||||
It "Can use PSForEach as an alias for the Foreach magic method" {
|
||||
$x = 5
|
||||
$x.PSForEach({$_}) | Should -Be 5
|
||||
}
|
||||
}
|
||||
|
||||
Context "Where Magic Method Adapter Tests" {
|
||||
@@ -240,6 +245,11 @@ Describe "Adapter Tests" -tags "CI" {
|
||||
} -PassThru -Force
|
||||
$x.Where(5) | Should -Be 10
|
||||
}
|
||||
|
||||
It "Can use PSWhere as an alias for the Where magic method" {
|
||||
$x = 5
|
||||
$x.PSWhere{$true} | Should -Be 5
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user