From 65d5b7a0e4d13a918fa4f26fbd2120b33821a353 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Tue, 5 Mar 2019 13:49:46 +0000 Subject: [PATCH 1/8] Fixes #9058 --- .../engine/Attributes.cs | 6 ++++ .../engine/TypeMetadata.cs | 33 ++++++++++++------- 2 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/System.Management.Automation/engine/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index f82e37e11a5..159dd190972 100644 --- a/src/System.Management.Automation/engine/Attributes.cs +++ b/src/System.Management.Automation/engine/Attributes.cs @@ -1014,6 +1014,11 @@ public sealed class ValidateRangeAttribute : ValidateEnumeratedArgumentsAttribut /// private Type _promotedType; + /// + /// The name of the predefined range. + /// + public ValidateRangeKind? RangeKind { get; } + ValidateRangeKind? _rangeKind; /// @@ -1136,6 +1141,7 @@ public ValidateRangeAttribute(object minRange, object maxRange) : base() public ValidateRangeAttribute(ValidateRangeKind kind) : base() { _rangeKind = kind; + RangeKind = kind; } private void ValidateRange(object element, ValidateRangeKind rangeKind) diff --git a/src/System.Management.Automation/engine/TypeMetadata.cs b/src/System.Management.Automation/engine/TypeMetadata.cs index 81353802046..b71589f59e5 100644 --- a/src/System.Management.Automation/engine/TypeMetadata.cs +++ b/src/System.Management.Automation/engine/TypeMetadata.cs @@ -758,6 +758,7 @@ internal bool IsMatchingType(PSTypeName psTypeName) private const string ParameterSetNameFormat = "ParameterSetName='{0}'"; private const string AliasesFormat = @"{0}[Alias({1})]"; private const string ValidateLengthFormat = @"{0}[ValidateLength({1}, {2})]"; + private const string ValidateRangeRangeKindFormat = @"{0}[ValidateRange([System.Management.Automation.ValidateRangeKind]::{1})]"; private const string ValidateRangeFloatFormat = @"{0}[ValidateRange({1:R}, {2:R})]"; private const string ValidateRangeFormat = @"{0}[ValidateRange({1}, {2})]"; private const string ValidatePatternFormat = "{0}[ValidatePattern('{1}')]"; @@ -908,22 +909,32 @@ private string GetProxyAttributeData(Attribute attrib, string prefix) ValidateRangeAttribute validRangeAttrib = attrib as ValidateRangeAttribute; if (validRangeAttrib != null) { - Type rangeType = validRangeAttrib.MinRange.GetType(); - string format; - - if (rangeType == typeof(float) || rangeType == typeof(double)) + if (validRangeAttrib.RangeKind.HasValue) { - format = ValidateRangeFloatFormat; + result = string.Format(CultureInfo.InvariantCulture, + ValidateRangeRangeKindFormat, prefix, + validRangeAttrib.RangeKind.ToString()); + return result; } else { - format = ValidateRangeFormat; - } + Type rangeType = validRangeAttrib.MinRange.GetType(); + string format; - result = string.Format(CultureInfo.InvariantCulture, - format, prefix, - validRangeAttrib.MinRange, validRangeAttrib.MaxRange); - return result; + if (rangeType == typeof(float) || rangeType == typeof(double)) + { + format = ValidateRangeFloatFormat; + } + else + { + format = ValidateRangeFormat; + } + + result = string.Format(CultureInfo.InvariantCulture, + format, prefix, + validRangeAttrib.MinRange, validRangeAttrib.MaxRange); + return result; + } } AllowNullAttribute allowNullAttrib = attrib as AllowNullAttribute; From d034b624d69b74cd4efa038aa885a8bbb0e4529f Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Tue, 5 Mar 2019 14:00:09 +0000 Subject: [PATCH 2/8] Fixes RangeKind description --- src/System.Management.Automation/engine/Attributes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index 159dd190972..d13b35dc04f 100644 --- a/src/System.Management.Automation/engine/Attributes.cs +++ b/src/System.Management.Automation/engine/Attributes.cs @@ -1015,7 +1015,7 @@ public sealed class ValidateRangeAttribute : ValidateEnumeratedArgumentsAttribut private Type _promotedType; /// - /// The name of the predefined range. + /// Gets the name of the predefined range. /// public ValidateRangeKind? RangeKind { get; } From 5d37e3084d3126421c1ec7d2df2e7b17c3522e25 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Tue, 5 Mar 2019 14:02:26 +0000 Subject: [PATCH 3/8] Fixes method parameter layout --- .../engine/TypeMetadata.cs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/System.Management.Automation/engine/TypeMetadata.cs b/src/System.Management.Automation/engine/TypeMetadata.cs index b71589f59e5..1661bc945be 100644 --- a/src/System.Management.Automation/engine/TypeMetadata.cs +++ b/src/System.Management.Automation/engine/TypeMetadata.cs @@ -900,9 +900,11 @@ private string GetProxyAttributeData(Attribute attrib, string prefix) ValidateLengthAttribute validLengthAttrib = attrib as ValidateLengthAttribute; if (validLengthAttrib != null) { - result = string.Format(CultureInfo.InvariantCulture, + result = string.Format( + CultureInfo.InvariantCulture, ValidateLengthFormat, prefix, - validLengthAttrib.MinLength, validLengthAttrib.MaxLength); + validLengthAttrib.MinLength, + validLengthAttrib.MaxLength); return result; } @@ -911,8 +913,10 @@ private string GetProxyAttributeData(Attribute attrib, string prefix) { if (validRangeAttrib.RangeKind.HasValue) { - result = string.Format(CultureInfo.InvariantCulture, - ValidateRangeRangeKindFormat, prefix, + result = string.Format( + CultureInfo.InvariantCulture, + ValidateRangeRangeKindFormat, + prefix, validRangeAttrib.RangeKind.ToString()); return result; } From e48902ab79727a7061cd98599a4d1f65a8170103 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Tue, 5 Mar 2019 18:19:38 +0000 Subject: [PATCH 4/8] Adds tests for ProxyCommand.GetParamBlock --- .../engine/Basic/ProxyCommand.tests.ps1 | 79 +++++++++++++++++++ 1 file changed, 79 insertions(+) create mode 100644 test/powershell/engine/Basic/ProxyCommand.tests.ps1 diff --git a/test/powershell/engine/Basic/ProxyCommand.tests.ps1 b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 new file mode 100644 index 00000000000..88830c52079 --- /dev/null +++ b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 @@ -0,0 +1,79 @@ +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. +# +Describe 'ProxyCommand Tests' -Tag 'CI' { + BeforeAll { + $testCases = @( + @{ Name = 'ValidateLengthAttribute'; ParamBlock = '[ValidateLength(1, 10)][int]${Parameter}' } + @{ Name = 'ValidateRangeAttribute with Minimum and Maximum'; ParamBlock = '[ValidateRange(1, 10)][int]${Parameter}' } + @{ Name = 'ValidateRangeAttribute with RangeKind'; ParamBlock = '[ValidateRange([System.Management.Automation.ValidateRangeKind]::Positive)][int]${Parameter}' } + @{ Name = 'AllowNullAttribute'; ParamBlock = '[AllowNull()][int]${Parameter}' } + @{ Name = 'AllowEmptyStringAttribute'; ParamBlock = '[AllowEmptyString()][int]${Parameter}' } + @{ Name = 'AllowEmptyCollectionAttribute'; ParamBlock = '[AllowEmptyCollection()][int]${Parameter}' } + @{ Name = 'ValidatePatternAttribute'; ParamBlock = '[ValidatePattern(''.*'')][int]${Parameter}' } + @{ Name = 'ValidateCountAttribute'; ParamBlock = '[ValidateCount(1, 10)][int]${Parameter}' } + @{ Name = 'ValidateNotNullAttribute'; ParamBlock = '[ValidateNotNull()][int]${Parameter}' } + @{ Name = 'ValidateNotNullOrEmptyAttribute'; ParamBlock = '[ValidateNotNullOrEmpty()][int]${Parameter}' } + @{ Name = 'ValidateSetAttribute with explicit set'; ParamBlock = '[ValidateSet(''1'',''10'')][int]${Parameter}' } + @{ Name = 'PSTypeNameAttribute'; ParamBlock = '[PSTypeName(''TypeName'')][int]${Parameter}' } + ) + } + + Context 'GetParamBlock method' { + BeforeEach { + $errorRecord = $null + } + + AfterAll { + if (Test-Path function:testProxyCommandFunction) { + Remove-Item function:testProxyCommandFunction + } + } + + It 'Generates a param block when is used' -TestCases $testCases { + param ( + $Name, + + $ParamBlock + ) + + $functionDefinition = 'param ( {0} )' -f $ParamBlock + Set-Item -Path function:testProxyCommandFunction -Value $functionDefinition + + try { + $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( + (Get-Command testProxyCommandFunction) + ) + $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' + } catch { + $errorRecord = $_ + } + + $errorRecord | Should -BeNullOrEmpty + $generatedParamBlock | Should -Be $ParamBlock + } + + It 'Generates a param block when ValidateScriptAttribute is used' { + param ( + $Name, + + $ParamBlock + ) + + $functionDefinition = 'param ( [ValidateScript({ $true })][int]${Parameter} )' + Set-Item -Path function:testProxyCommandFunction -Value $functionDefinition + + try { + $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( + (Get-Command testProxyCommandFunction) + ) + $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' + } catch { + $errorRecord = $_ + } + + $errorRecord | Should -BeNullOrEmpty + $generatedParamBlock | Should -Be '[ValidateScript({ $true })][int]${Parameter}' + } + } +} From 4f3473ec73dedb8f13ffcd4262fc8b044c0c3eb3 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Tue, 5 Mar 2019 20:14:59 +0000 Subject: [PATCH 5/8] Sets accessor for RangeKind to internal --- src/System.Management.Automation/engine/Attributes.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/System.Management.Automation/engine/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index d13b35dc04f..5e02ac13d27 100644 --- a/src/System.Management.Automation/engine/Attributes.cs +++ b/src/System.Management.Automation/engine/Attributes.cs @@ -1017,7 +1017,7 @@ public sealed class ValidateRangeAttribute : ValidateEnumeratedArgumentsAttribut /// /// Gets the name of the predefined range. /// - public ValidateRangeKind? RangeKind { get; } + internal ValidateRangeKind? RangeKind { get => _rangeKind; } ValidateRangeKind? _rangeKind; @@ -1141,7 +1141,6 @@ public ValidateRangeAttribute(object minRange, object maxRange) : base() public ValidateRangeAttribute(ValidateRangeKind kind) : base() { _rangeKind = kind; - RangeKind = kind; } private void ValidateRange(object element, ValidateRangeKind rangeKind) From e4d77637b0211a3f311cd4580333109e0f322936 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Wed, 6 Mar 2019 08:19:14 +0000 Subject: [PATCH 6/8] Removes empty lines. Removes try/catch. --- .../engine/Basic/ProxyCommand.tests.ps1 | 34 +++++-------------- 1 file changed, 9 insertions(+), 25 deletions(-) diff --git a/test/powershell/engine/Basic/ProxyCommand.tests.ps1 b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 index 88830c52079..4f7062df716 100644 --- a/test/powershell/engine/Basic/ProxyCommand.tests.ps1 +++ b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 @@ -1,6 +1,5 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. -# Describe 'ProxyCommand Tests' -Tag 'CI' { BeforeAll { $testCases = @( @@ -25,54 +24,39 @@ Describe 'ProxyCommand Tests' -Tag 'CI' { } AfterAll { - if (Test-Path function:testProxyCommandFunction) { - Remove-Item function:testProxyCommandFunction - } + Remove-Item function:testProxyCommandFunction } It 'Generates a param block when is used' -TestCases $testCases { param ( $Name, - $ParamBlock ) $functionDefinition = 'param ( {0} )' -f $ParamBlock Set-Item -Path function:testProxyCommandFunction -Value $functionDefinition - try { - $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( - (Get-Command testProxyCommandFunction) - ) - $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' - } catch { - $errorRecord = $_ - } + $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( + (Get-Command testProxyCommandFunction) + ) + $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' - $errorRecord | Should -BeNullOrEmpty $generatedParamBlock | Should -Be $ParamBlock } It 'Generates a param block when ValidateScriptAttribute is used' { param ( $Name, - $ParamBlock ) $functionDefinition = 'param ( [ValidateScript({ $true })][int]${Parameter} )' Set-Item -Path function:testProxyCommandFunction -Value $functionDefinition + $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( + (Get-Command testProxyCommandFunction) + ) + $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' - try { - $generatedParamBlock = [System.Management.Automation.ProxyCommand]::GetParamBlock( - (Get-Command testProxyCommandFunction) - ) - $generatedParamBlock = $generatedParamBlock -split '\r?\n' -replace '^ *' -join '' - } catch { - $errorRecord = $_ - } - - $errorRecord | Should -BeNullOrEmpty $generatedParamBlock | Should -Be '[ValidateScript({ $true })][int]${Parameter}' } } From 61a29d6d936040e9c097781bf7b1ffe9cf012609 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Wed, 6 Mar 2019 12:35:59 +0000 Subject: [PATCH 7/8] Fix formatting. Remove redundant variable. --- src/System.Management.Automation/engine/TypeMetadata.cs | 9 ++++++--- test/powershell/engine/Basic/ProxyCommand.tests.ps1 | 7 ++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/System.Management.Automation/engine/TypeMetadata.cs b/src/System.Management.Automation/engine/TypeMetadata.cs index 1661bc945be..f54b326e7eb 100644 --- a/src/System.Management.Automation/engine/TypeMetadata.cs +++ b/src/System.Management.Automation/engine/TypeMetadata.cs @@ -934,9 +934,12 @@ private string GetProxyAttributeData(Attribute attrib, string prefix) format = ValidateRangeFormat; } - result = string.Format(CultureInfo.InvariantCulture, - format, prefix, - validRangeAttrib.MinRange, validRangeAttrib.MaxRange); + result = string.Format( + CultureInfo.InvariantCulture, + format, + prefix, + validRangeAttrib.MinRange, + validRangeAttrib.MaxRange); return result; } } diff --git a/test/powershell/engine/Basic/ProxyCommand.tests.ps1 b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 index 4f7062df716..947c4634249 100644 --- a/test/powershell/engine/Basic/ProxyCommand.tests.ps1 +++ b/test/powershell/engine/Basic/ProxyCommand.tests.ps1 @@ -1,5 +1,6 @@ # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. + Describe 'ProxyCommand Tests' -Tag 'CI' { BeforeAll { $testCases = @( @@ -19,12 +20,8 @@ Describe 'ProxyCommand Tests' -Tag 'CI' { } Context 'GetParamBlock method' { - BeforeEach { - $errorRecord = $null - } - AfterAll { - Remove-Item function:testProxyCommandFunction + Remove-Item function:testProxyCommandFunction -ErrorAction SilentlyContinue } It 'Generates a param block when is used' -TestCases $testCases { From 48a1b207655d9c02e1b30b8444a33046b31fe309 Mon Sep 17 00:00:00 2001 From: Chris Dent Date: Thu, 25 Apr 2019 17:03:59 +0100 Subject: [PATCH 8/8] Change ValidateRangeAttribute._rangeKind to private --- src/System.Management.Automation/engine/Attributes.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/System.Management.Automation/engine/Attributes.cs b/src/System.Management.Automation/engine/Attributes.cs index 5e02ac13d27..d501f395903 100644 --- a/src/System.Management.Automation/engine/Attributes.cs +++ b/src/System.Management.Automation/engine/Attributes.cs @@ -1019,7 +1019,7 @@ public sealed class ValidateRangeAttribute : ValidateEnumeratedArgumentsAttribut /// internal ValidateRangeKind? RangeKind { get => _rangeKind; } - ValidateRangeKind? _rangeKind; + private ValidateRangeKind? _rangeKind; /// /// Validates that each parameter argument falls in the range