Add the parameter '-Not' to 'Where-Object' (#6464)
This commit is contained in:
parent
701b919345
commit
31405f7283
2 changed files with 155 additions and 8 deletions
|
@ -813,6 +813,7 @@ namespace Microsoft.PowerShell.Commands
|
||||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "CaseSensitiveNotInSet")]
|
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "CaseSensitiveNotInSet")]
|
||||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsSet")]
|
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsSet")]
|
||||||
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsNotSet")]
|
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "IsNotSet")]
|
||||||
|
[Parameter(Mandatory = true, Position = 0, ParameterSetName = "Not")]
|
||||||
[ValidateNotNullOrEmpty]
|
[ValidateNotNullOrEmpty]
|
||||||
public string Property
|
public string Property
|
||||||
{
|
{
|
||||||
|
@ -1199,6 +1200,16 @@ namespace Microsoft.PowerShell.Commands
|
||||||
get { return _binaryOperator == TokenKind.IsNot; }
|
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
|
#endregion binary operator parameters
|
||||||
|
|
||||||
private readonly CallSite<Func<CallSite, object, bool>> _toBoolSite =
|
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);
|
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)
|
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());
|
var enumerableSite = CallSite<Func<CallSite, object, IEnumerator>>.Create(PSEnumerableBinder.Get());
|
||||||
|
@ -1261,12 +1282,7 @@ namespace Microsoft.PowerShell.Commands
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// flip 'lval' and 'rval' in the scenario '... | Where-Object property' so as to make it
|
_operationDelegate = GetCallSiteDelegateBoolean(ExpressionType.Equal, ignoreCase: true);
|
||||||
// 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);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TokenKind.Ceq:
|
case TokenKind.Ceq:
|
||||||
|
@ -1338,6 +1354,9 @@ namespace Microsoft.PowerShell.Commands
|
||||||
_operationDelegate =
|
_operationDelegate =
|
||||||
(lval, rval) => ParserOps.MatchOperator(Context, PositionUtilities.EmptyExtent, lval, rval, notMatch: true, ignoreCase: false);
|
(lval, rval) => ParserOps.MatchOperator(Context, PositionUtilities.EmptyExtent, lval, rval, notMatch: true, ignoreCase: false);
|
||||||
break;
|
break;
|
||||||
|
case TokenKind.Not:
|
||||||
|
_operationDelegate = GetCallSiteDelegateBoolean(ExpressionType.NotEqual, ignoreCase: true);
|
||||||
|
break;
|
||||||
// the second to last parameter in ContainsOperator has flipped semantics compared to others.
|
// the second to last parameter in ContainsOperator has flipped semantics compared to others.
|
||||||
// "true" means "contains" while "false" means "notcontains"
|
// "true" means "contains" while "false" means "notcontains"
|
||||||
case TokenKind.Icontains:
|
case TokenKind.Icontains:
|
||||||
|
@ -1463,7 +1482,7 @@ namespace Microsoft.PowerShell.Commands
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Both -Property and -Value need to be specified if the user specifies the binary operation
|
// 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
|
// The binary operation is specified explicitly by the user and the -Value parameter is
|
||||||
// not specified
|
// not specified
|
||||||
|
|
|
@ -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