8000 Added Addtional Validation Attributes by dchristian3188 · Pull Request #4084 · PowerShell/PowerShell · GitHub
[go: up one dir, main page]

Skip to content

Added Addtional Validation Attributes#4084

Merged
lzybkr merged 12 commits intoPowerShell:masterfrom
dchristian3188:ValidatePositiveNegativeAttributes
Aug 2, 2017
Merged

Added Addtional Validation Attributes#4084
lzybkr merged 12 commits intoPowerShell:masterfrom
dchristian3188:ValidatePositiveNegativeAttributes

Conversation

@dchristian3188
Copy link
Contributor

First pass of additional parameter validations attributes as mentioned here: #2634

New attributes include:
ValidatePositiveAttribute
ValidateNonNegativeAttribute
ValidateNegativeAttribute
ValidateNonPositiveAttribute

Copy link
Contributor
@lzybkr lzybkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have existing cmdlet parameters where these new attributes should be used.

I think it make sense to start using the new attribute right away.

We also need to think through usage on all data types, and avoid introducing unnecessary new public apis (the base classes).

Context "ValidatePositive" {
BeforeAll {
$testCases = @(
@{ sb = { function Local:foo { param([ValidatePositive()] [int] $bar) }; foo -1 }; FullyQualifiedErrorId = "ParameterArgumentValidationError,foo"; InnerErrorId = "ValidateRangeTooSmall" }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

local: is unnecessary.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also - this is hard to read with all keys on the same line - I suggest each key on it's own line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll get this cleaned up. I was trying to follow the existing format of the file. Is it cool to update those other test as part of this PR as well?

{
/// <summary>
/// Minimum allowed value for the attribute
/// </summary>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What about other data types? Smaller should just work, but what about long, float, double or bigint?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible dynamic helps you here

In validate element, you would write:

dymamic val = element;
if (val > minValue) ...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Any tips on how to include the larger numbers? I was thinking if checking if the element has a CompareTo() but not sure if this is correct. For example, string also have compare to which would be an invalid type.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Try my suggestion to use dynamic - it might just work. Behind the scenes, the C# compiler will generate code calling the correct operator after testing the type of val.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, never used this before. Updated to use dynamic

/// <seealso cref="ValidatePositiveAttribute"/>,
/// <seealso cref="ValidateNonNegativeAttribute"/>
/// </remarks>
[AttributeUsage(AttributeTargets.Field | AttributeTargets.Property)]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This base class is not generally useful, so I'd prefer avoiding introducing a new public type.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will remove

@iSazonov
Copy link
Collaborator

@dchristian3188 Please put a message in #2634 that you are starting the fix to exclude conflicts.

@iSazonov
Copy link
Collaborator

We also need to think through usage on all data types, and avoid introducing unnecessary new public apis (the base classes).

We could exclude the new apis at all - if we want usage on all data types we should generalize existing ValidateElement(). So we can generalize ValidateRangeAttribute.ValidateElement() and add new constructor to support:

ValidateRange(Range="Positive")

@lzybkr
Copy link
Contributor
lzybkr commented Jun 23, 2017

@iSazonov - I was saying we don't need any unnecessary apis like the abstract base class used to share a tiny bit of code - that could easily be done without inheritance.

Your suggestion might look like:

public enum RangeKind {
    Positive, NonNegative, Negative, NonPositive
}

    // In ValidateRangeAttribute
    RangeKind? _rangeKind;
    public ValidateRange(RangeKind kind) { _rangeKind = kind; }

        // in ValidateElement
        if (_rangeKind.HasValue) { ... }
        else { /* existing code */ }

That might be fine too, I'm not sure I have a preference either way.

@iSazonov
Copy link
Collaborator

@lzybkr Thanks for you prototype. I like it. We use the similar approach for enhancing ValidateSet with valid values generator. First locally I used inheritance, but your idea (to add new constructor) was better. So I believe we should use the same pattern here. Users will find it easier to know and apply the enhancements than the new apis.

@dchristian3188
Copy link
Contributor Author

I think you guys are right. Extending Validate range does feel cleaner.

Copy link
Collaborator
@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a comment


/// <Summary>
/// predefined range kind to use with
/// ValidateRangeAttribute
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please start with capital and end with point.
Also we can fit all on one line.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

/// predefined range kind to use with
/// ValidateRangeAttribute
/// </Summary>
public enum ValidateRangeKind{
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add space before bracket.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

public enum ValidateRangeKind{

/// <Summary>
/// Range is greater than 0
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please end with a point in all comments.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

/// <Summary>
/// Range is less than or equal to 0
/// </Summary>
NonPositive
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I want to discuss the names. We could use names like math operations:

Name1 Name2 Name3
Positive ValueGT0 GT0
Nonnegative ValueGEzero GEzero
Negative ElementLT0 LT0
NonPositive ElementLEzero LEzero

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My Vote is for

1 - Positive, Negative, NonPostive, NonNegative
2 - ValueGTZero, ValueGEZero, ValueGTZero, ValueGEZero

if(_rangeKind.HasValue)
{
element = o.BaseObject;
dynamic val = element;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe add a comment here what types we expect/process here?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

switch (_rangeKind)
{
case ValidateRangeKind.Positive:
if(val <= 0)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should use CompareTo() as in original code.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

@{
sb = { function foo { param([ValidateCount(2, 1)] [string[]] $bar) }; foo }
FullyQualifiedErrorId = "ValidateRangeMaxLengthSmallerThanMinLength"
InnerErrorId = ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Indentation.
And below too.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

BeforeAll {
$testCases = @(
@{
sb = { function foo { param([ValidateRange('Positive')] [int] $bar) }; foo -1 }
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add test with the enum:

ValidateRange([ValidateRangeKind]::Positive)

I guess that's enough replace 'Positive' in one test and don't duplicate all tests.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I tried this but it failed since ValidateRangeKind is not exposed as a type accelerator. Should i use the full namespace or add [ValidateRangeKind]?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes.

$validTestCases = @(
@{
sb = { function foo { param([ValidateRange('Positive')] [int] $bar) }; foo 15 }
TestValue = 15
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We use LanguagePrimitives.TryConvertTo so we very "generic" here and we should add tests for non-numeric values.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add the tests.

}
}

Context "ValidateRange - NonNegative" {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can combine all ValidateRangeKind-s in one TestCases:

sb = { function foo { param([ValidateRange(   '<TestCase-Parameter-Here>'    )] [int] $bar) }; foo -1 } 

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Closed.

{
element = o.BaseObject;
// Using dynamic to handle different type of numbers such as
// int, double, decimal and float.
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

CompareTo() allow us be more general. I think we should enhance the comment.

else

// minRange and maxRange have the same type, so we just need
// to compare to one of them
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please correct the comment formatting.

element.ToString(), MaxRange.ToString());
}
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please remove the extra line.

Copy link
Contributor
@lzybkr lzybkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see you're reusing existing error messages - one reason for this feature was to improve the error message.

And once we've settled on naming, I'd really like to see this new form of the attribute used in our own code base - there are 80 or so places that could use this.

/// <Summary>
/// Predefined range kind to use with ValidateRangeAttribute.
/// </Summary>
public enum ValidateRangeKind {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please follow the conventions of the file you are editing, e.g. braces normally go on their own line, and you have no space after if.

switch (_rangeKind)
{
case ValidateRangeKind.Positive:
if(val.CompareTo(0) <= 0)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the argument does not implement IComparable, the error message will not be good.

element = o.BaseObject;
// Using dynamic to handle different type of numbers such as
// int, double, decimal and float.
dynamic val = element;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be too general - e.g. strings implement IComparable, but strings aren't positive or negative.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I also see you omit the test for PSObject - you'll probably want it for your code as well - and you should also ensure you have tests to cover simple (non-wrapped) arguments and PSObject wrapped arguments.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This might be too general - e.g. strings implement IComparable , but strings aren't positive or negative.

In general, we cannot know if the type is comparable with zero in advance. Should we test this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How do you feel about reusing the GetCommonType method from the validate range class?
We could use the incoming object and 0. I believe this will also throw the correct message if the user attempts to pass an incompatable object such as string

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems reasonable.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you share an example where the element was a string and you expected an integer?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Here's what i had for ValidateElement.

protected override void ValidateElement(object element)
{
    if (element == null)
    {
        throw new ValidationMetadataException(
                "ArgumentIsEmpty",
                null,
                Metadata.ValidateNotNullFailure);
    }

    var o = element as PSObject;
    if (o != null)
    {
        element = o.BaseObject;
    }
    
    if (_rangeKind.HasValue)
    {

        Type commonType = GetCommonType((0).GetType(),element.GetType());

        ...

Then in PowerShell

function foo { param([ValidateRange('Positive')] $bar) }

foo -1

At this point, element will be a string when we enter GetCommonType.

What's interesting is that this does work.

function foo { param([ValidateRange('Positive')] $bar) }

foo (-1)

I checked the existing code and they solve this by first getting the common type of the min and max values. They then try to cast element to this new type before comparison operations.

Since I don't have a common type, I was thinking of trying the cast to double.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is interesting. Maybe it is by design for -1 but confusing:

PS > function foo { param($bar) $bar.Gettype() }
PS > foo
You cannot call a method on a null-valued expression.
At line:1 char:29
+ function foo { param( $bar) $bar.Gettype() }
+                             ~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidOperation: (:) [], RuntimeException
    + FullyQualifiedErrorId : InvokeMethodOnNull

PS > foo 0

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType


PS > foo -1

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     String                                   System.Object


PS > foo 1

IsPublic IsSerial Name                                     BaseType
-------- -------- ----                                     --------
True     True     Int32                                    System.ValueType

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In general case, a custom class can implement CompareTo() and allow (CustomClass)0. If the class don't implement this we get an exception - it seems this is acceptable here.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The real problem here is the parameter is not typed - so I think this is by design. If the parameter was typed as [int], then it would have worked as expected.

Based on this, I think it's still reasonable to use GetCommonType.

@dchristian3188
Copy link
Contributor Author

Ok, i added the check for the common type. Also tried to make the error messages a little more relevant.

null,
Metadata.ValidateRangeElementType,
element.GetType().Name,
0.GetType().Name);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

0.GetType() and 0.GetType().Name is good condidates for static read only constant.


if (LanguagePrimitives.TryConvertTo(element, commonType, out resultValue))
{
elementValue = resultValue as IComparable;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What if we get elementValue == null ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That shouldn't be possible if there are no bugs in GetCommonType. I'd actually use a cast though so that if it did fail, the error would be better - can't convert instead of null reference.


if (_rangeKind.HasValue)
{
ValidatePredefinedRange(element);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Comparing is the same for any range kinds (including "user defined"). I believe we should create a common method to compare elements and call it with different arguments for different ranges.

@dchristian3188
Copy link
Contributor Author

I get what you're saying about the methods. I've consolidated them into one method with overload. Let me know how it looks.

Copy link
Collaborator
@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I meant that a range is a range and we can have one method for all range kinds. We need only add 'ExpliciteRange' in enum.

ValidateRangeKind? _rangeKind;

private readonly static Type _zeroType = 0.GetType();
private readonly static string _zeroTypeName = 0.GetType().Name;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please use s_zeroType for static constant.
And maybe _zeroTypeName = s_zeroType.Name;

@dchristian3188
Copy link
Contributor Author

Hey iSazonov, I'm not sure I follow on adding the additional range type. If we were to add the ExpliciteRange in the enum, wouldn't this allow a user to do something like this:

function foo { param([ValidateRange("ExpliciteRange")] [int] $bar) }; foo 0 }

@iSazonov
Copy link
Collaborator
iSazonov commented Jul 1, 2017

@dchristian3188 I agree - we should follow HasValue(). That's enough to make a choice in general method.

@iSazonov
Copy link
Collaborator
iSazonov commented Jul 2, 2017

We could enhance and unify Ranges. Currently Min and Max values are allowed but user can want to exclude them. Ex., "Positive" exclude zero. So the "Positive" range looks:

ValidateRange(0, int.MaxValue, RangeOption.ExcludeMin)

"Negative":

ValidateRange( -int.MaxValue, 0, RangeOption.ExcludeMax)

Exclude both (allow 0.5):

ValidateRange( 0, 1, RangeOption.ExcludeMin+RangeOption.ExcludeMax)

And we can move switch (rangeKind) to a constructor (with assigning a specific error message) and implement general ValidateElement method.

@dchristian3188
Copy link
Contributor Author

Hi iSazonov,

I think expanding the range functionality is a cool idea, but might be out of scope for this PR. Do you want me to open a separate issue for tracking?

Are there other updates I should make to the validate positive, negative, etc?

@iSazonov
Copy link
Collaborator

@dchristian3188 Please clarify do you plan continue in new PR or want cut off?

@dchristian3188
Copy link
Contributor Author
dchristian3188 commented Jul 12, 2017

Hi iSazonov,

I would continue the work you mentioned in the new PR. If we open the issue, would I be able to get it assigned to me?

@iSazonov
Copy link
Collaborator

@lzybkr Could you please continue the code review?


ValidateRangeKind? _rangeKind;

private readonly static Type s_zeroType = 0.GetType();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A static is not necessary, you should just use typeof(int) instead.

ValidateRangeKind? _rangeKind;

private readonly static Type s_zeroType = 0.GetType();
private readonly static string s_zeroTypeName = s_zeroType.Name;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A static is not necessary here either - the string is only used in error cases, so there is little point in always creating it.

s_zeroTypeName);
}

dynamic elementValue = element;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With this approach, you don't need dynamic.


if (LanguagePrimitives.TryConvertTo(element, commonType, out resultValue))
{
elementValue = resultValue as IComparable;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That shouldn't be possible if there are no bugs in GetCommonType. I'd actually use a cast though so that if it did fail, the error would be better - can't convert instead of null reference.

@ArieHein
Copy link

will this make the value zero validated both as NonNegative and NonPositive ?
or did I miss something ?

@dchristian3188
Copy link
Contributor Author

Yes 0 will fall into both NonNegative and NonPositive.
The breakdown is:

Positive -gt 0
NonNegative -ge 0
Negative -lt 0
NonPostive -le 0

@dchristian3188
Copy link
Contributor Author

@lzybkr

Latest PR removes static variables. Also reworked to get rid of the dynamic variable.

Let me know if everything looks ok.

@iSazonov
Copy link
Collaborator

@dchristian3188 For 0.GetType(); request was

you should just use typeof(int) instead.

@dchristian3188
Copy link
Contributor Author

hi @iSazonov , sorry missed that one.

Corrections have been made. Please review

@ArieHein
Copy link

Thers also the issue is 0 defined as positive or negative.

I need to test my DSC scripts to make sure if I use these validations I get the desired logic.

Copy link
Collaborator
@iSazonov iSazonov left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Leave a comment

{
dynamicZero = (IComparable)resultValue;
throwTypeError = false;
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can add else and exclude throwTypeError.

<value>The argument cannot be validated because its type "{0}" is not the same type ({1}) as the maximum and minimum limits of the parameter. Make sure the argument is of type {1} and then try the command again.</value>
</data>
<data name="ValidateRangePositiveFailure" xml:space="preserve">
<value>The argument "{0}" cannot be validated because its value is not greater than zero.</value>
2DA8
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We can "validate" but cannot "accept". Maybe better change this. Below too.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're right, this does make more sense. It also follows the same verbiage as existing Validate Range

@dchristian3188
Copy link
Contributor Author

Updates made in latest PR

Copy link
Contributor
@lzybkr lzybkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a few little things now - I think it's just about ready.

_rangeKind = kind;
}

private void ValidateRange(object element, ValidateRangeKind? rangeKind)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's a private method so it doesn't really matter, but rangeKind is not optional, so the parameter should not be nullable.


if (LanguagePrimitives.TryConvertTo(element, commonType, out resultValue))
{
element = (IComparable)resultValue;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this cast is pointless.
If the cast were to fail - the error message won't be good.
But I don't think the cast will fail, GetCommonType should not succeed if the type is not IComparable, and the cast isn't necessary when assigning to object.

null,
Metadata.ValidateRangeElementType,
element.GetType().Name,
typeof(int).Name);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't this be typeof(commonType).Name?

<value>The argument cannot be validated because its type "{0}" is not the same type ({1}) as the maximum and minimum limits of the parameter. Make sure the argument is of type {1} and then try the command again.</value>
</data>
<data name="ValidateRangePositiveFailure" xml:space="preserve">
<value>The argument "{0}" cannot be accepted because its value is not greater than zero.</value>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For consistency, validation errors use The argument "{0} cannot be validated - the cannot be accepted phrase is not commonly used in our code base, basically just in this resx file, and maybe we should change those messages.

@{ sb = { function Local:foo { param([ValidateCount(2, 3)] [string[]] $bar) }; foo 1 }; FullyQualifiedErrorId = "ParameterArgumentValidationError,foo"; InnerErrorId = "ValidateCountMinMaxFailure" }
@{ sb = { function Local:foo { param([ValidateCount(2, 3)] [string[]] $bar) }; foo 1,2,3,4 }; FullyQualifiedErrorId = "ParameterArgumentValidationError,foo"; InnerErrorId = "ValidateCountMinMaxFailure" }
@{
sb = { function foo { param([ValidateCount(-1,2)] [string[]] $bar) }; foo }
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize you didn't introduce this, but sb is not a great name - it is often used for StringBuilder as well. $ScriptBlock is probably better.

I won't block the PR if you want to leave it though.

dchristian3188 and others added 3 commits August 2, 2017 07:28
Revert attribute parameter (as opposed to PowerShell parameter validation) error message
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants

0