Add the parameter '-Not' to 'Where-Object' (#6464)
This commit is contained in:
parent
701b919345
commit
31405f7283
|
@ -813,6 +813,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "CaseSensitiveNotInSet")]
|
||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsSet")]
|
||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsNotSet")]
|
||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "Not")]
|
||||
[ValidateNotNullOrEmpty]
|
||||
public string Property
|
||||
{
|
||||
|
@ -1199,6 +1200,16 @@ namespace Microsoft.PowerShell.Commands
|
|||
get { return _binaryOperator == TokenKind.IsNot; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Binary operator -Not.
|
||||
/// </summary>
|
||||
[Parameter(Mandatory = true, ParameterSetName = "Not")]
|
||||
public SwitchParameter Not
|
||||
{
|
||||
set { _binaryOperator = TokenKind.Not; }
|
||||
get { return _binaryOperator == TokenKind.Not; }
|
||||
}
|
||||
|
||||
#endregion binary operator parameters
|
||||
|
||||
private readonly CallSite<Func<CallSite, object, bool>> _toBoolSite =
|
||||
|
@ -1211,6 +1222,16 @@ namespace Microsoft.PowerShell.Commands
|
|||
return (x, y) => site.Target.Invoke(site, x, y);
|
||||
}
|
||||
|
||||
private static Func<object, object, object> GetCallSiteDelegateBoolean(ExpressionType expressionType, bool ignoreCase)
|
||||
{
|
||||
// flip 'lval' and 'rval' in the scenario '... | Where-Object property' so as to make it
|
||||
// equivalent to '... | Where-Object {$true -eq property}'. Because we want the property to
|
||||
// be compared under the bool context. So that '"string" | Where-Object Length' would behave
|
||||
// just like '"string" | Where-Object {$_.Length}'.
|
||||
var site = CallSite<Func<CallSite, object, object, object>>.Create(binder: PSBinaryOperationBinder.Get(expressionType, ignoreCase));
|
||||
return (x, y) => site.Target.Invoke(site, y, x);
|
||||
}
|
||||
|
||||
private static Tuple<CallSite<Func<CallSite, object, IEnumerator>>, CallSite<Func<CallSite, object, object, object>>> GetContainsCallSites(bool ignoreCase)
|
||||
{
|
||||
var enumerableSite = CallSite<Func<CallSite, object, IEnumerator>>.Create(PSEnumerableBinder.Get());
|
||||
|
@ -1261,12 +1282,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
}
|
||||
else
|
||||
{
|
||||
// flip 'lval' and 'rval' in the scenario '... | Where-Object property' so as to make it
|
||||
// equivalent to '... | Where-Object {$true -eq property}'. Because we want the property to
|
||||
// be compared under the bool context. So that '"string" | Where-Object Length' would behave
|
||||
// just like '"string" | Where-Object {$_.Length}'.
|
||||
var site = CallSite<Func<CallSite, object, object, object>>.Create(PSBinaryOperationBinder.Get(ExpressionType.Equal, true));
|
||||
_operationDelegate = (x, y) => site.Target.Invoke(site, y, x);
|
||||
_operationDelegate = GetCallSiteDelegateBoolean(ExpressionType.Equal, ignoreCase: true);
|
||||
}
|
||||
break;
|
||||
case TokenKind.Ceq:
|
||||
|
@ -1338,6 +1354,9 @@ namespace Microsoft.PowerShell.Commands
|
|||
_operationDelegate =
|
||||
(lval, rval) => ParserOps.MatchOperator(Context, PositionUtilities.EmptyExtent, lval, rval, notMatch: true, ignoreCase: false);
|
||||
break;
|
||||
case TokenKind.Not:
|
||||
_operationDelegate = GetCallSiteDelegateBoolean(ExpressionType.NotEqual, ignoreCase: true);
|
||||
break;
|
||||
// the second to last parameter in ContainsOperator has flipped semantics compared to others.
|
||||
// "true" means "contains" while "false" means "notcontains"
|
||||
case TokenKind.Icontains:
|
||||
|
@ -1463,7 +1482,7 @@ namespace Microsoft.PowerShell.Commands
|
|||
else
|
||||
{
|
||||
// Both -Property and -Value need to be specified if the user specifies the binary operation
|
||||
if (_valueNotSpecified && (_binaryOperator != TokenKind.Ieq || !_forceBooleanEvaluation))
|
||||
if (_valueNotSpecified && ((_binaryOperator != TokenKind.Ieq && _binaryOperator != TokenKind.Not) || !_forceBooleanEvaluation))
|
||||
{
|
||||
// The binary operation is specified explicitly by the user and the -Value parameter is
|
||||
// not specified
|
||||
|
@ -1829,4 +1848,4 @@ namespace Microsoft.PowerShell.Commands
|
|||
#endregion Set-StrictMode
|
||||
|
||||
#endregion Built-in cmdlets that are used by or require direct access to the engine.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,128 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License.
|
||||
|
||||
Describe "Where-Object" -Tags "CI" {
|
||||
BeforeAll {
|
||||
$Computers = @(
|
||||
[PSCustomObject]@{
|
||||
ComputerName = "SPC-1234"
|
||||
IPAddress = "192.168.0.1"
|
||||
NumberOfCores = 1
|
||||
Drives = 'C','D'
|
||||
},
|
||||
[PSCustomObject]@{
|
||||
ComputerName = "BGP-5678"
|
||||
IPAddress = ""
|
||||
NumberOfCores = 2
|
||||
Drives = 'C','D','E'
|
||||
},
|
||||
[PSCustomObject]@{
|
||||
ComputerName = "MGC-9101"
|
||||
NumberOfCores = 3
|
||||
Drives = 'C'
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
It "Where-Object -Not Prop" {
|
||||
$Result = $Computers | Where-Object -Not 'IPAddress'
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$true -ne $_.Prop}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$true -ne $_.IPAddress}
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It "Where-Object Prop" {
|
||||
$Result = $Computers | Where-Object 'IPAddress'
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$true -eq $_.Prop}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$true -eq $_.IPAddress}
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -contains Value}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.Drives -contains 'D'}
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -contains Value' {
|
||||
$Result = $Computers | Where-Object Drives -contains 'D'
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -in $Array}' {
|
||||
$Array = 'SPC-1234','BGP-5678'
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -in $Array}
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object $Array -in Prop' {
|
||||
$Array = 'SPC-1234','BGP-5678'
|
||||
$Result = $Computers | Where-Object ComputerName -in $Array
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -ge 2}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -ge 2}
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -ge 2' {
|
||||
$Result = $Computers | Where-Object NumberOfCores -ge 2
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -gt 2}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -gt 2}
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -gt 2' {
|
||||
$Result = $Computers | Where-Object NumberOfCores -gt 2
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -le 2}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -le 2}
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -le 2' {
|
||||
$Result = $Computers | Where-Object NumberOfCores -le 2
|
||||
$Result.Count | Should -Be 2
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -lt 2}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.NumberOfCores -lt 2}
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -lt 2' {
|
||||
$Result = $Computers | Where-Object NumberOfCores -lt 2
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -Like Value}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -like 'MGC-9101'}
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -like Value' {
|
||||
$Result = $Computers | Where-Object ComputerName -like 'MGC-9101'
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object -FilterScript {$_.Prop -Match Pattern}' {
|
||||
$Result = $Computers | Where-Object -FilterScript {$_.ComputerName -match '^MGC.+'}
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
|
||||
It 'Where-Object Prop -like Value' {
|
||||
$Result = $Computers | Where-Object ComputerName -match '^MGC.+'
|
||||
$Result.Count | Should -Be 1
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue