Skip to content
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 5 additions & 2 deletions Rules/AvoidDefaultValueForMandatoryParameter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,11 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
{
if (String.Equals(namedArgument.ArgumentName, "mandatory", StringComparison.OrdinalIgnoreCase))
{
// 2 cases: [Parameter(Mandatory)] and [Parameter(Mandatory=$true)]
if (namedArgument.ExpressionOmitted || (!namedArgument.ExpressionOmitted && String.Equals(namedArgument.Argument.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase)))
// 3 cases: [Parameter(Mandatory)], [Parameter(Mandatory=$true)] and [Parameter(Mandatory=value)] where value is not equal to 0.
int mandatoryValue = 0;
if (namedArgument.ExpressionOmitted
|| (String.Equals(namedArgument.Argument.Extent.Text, "$true", StringComparison.OrdinalIgnoreCase))
|| (int.TryParse(namedArgument.Argument.Extent.Text, out mandatoryValue) && mandatoryValue != 0))
Copy link
Collaborator

Choose a reason for hiding this comment

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

C# 7 allows you to inline out parameter declaration as (int.TryParse(namedArgument.Argument.Extent.Text, out int mandatoryValue) . This would allow you to delete the int mandatoryValue = 0; line.
But more importantly shouldn't the last comparison be mandatoryValue == 1?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Currently the powershell interpreter accepts every numeric value of Mandatory parameter. So all the following: Parameter(Mandatory=1), Parameter(Mandatory=-1), Parameter(Mandatory=100) are acceptable and mean that PowerShell treats the parameter as mandatory. Only in case Parameter(Mandatory=0), the parameter is not mandatory.

Hence, I adjusted the rule to the way PowerShell works, but definieily specifying parameter as e.g. Parameter(Mandatory=-100) is not a good coding practice... Maybe we should add some special rule for that?

Copy link
Collaborator

Choose a reason for hiding this comment

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

Hmm, sounds like we should raise at least an issue in the PowerShell repo to not allow values other than 0/1. If someone specified something else then it is most likely a so called fat-finger error. I can see the point of warning in PSSA but I am not sure if it is worth the effort and computational expense of having an extra rule just for that specifically but maybe rather a more generic rule for syntax validation ala PossibleUninentionalSyntax that we could use in the future for warnings unrelated to a rule itself. Therefore this question/issue should not concern/block this PR, which is a set of complete changes leading to improved behaviour of PSSA, therefore I will approve.

{
mandatory = true;
break;
Expand Down
12 changes: 12 additions & 0 deletions Tests/Rules/AvoidDefaultValueForMandatoryParameter.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ Describe "AvoidDefaultValueForMandatoryParameter" {
Where-Object { $_.RuleName -eq $ruleName }
$violations.Count | Should -Be 1
}

It "returns violations when the parameter is specified as mandatory=1 and has a default value" {
$violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Function foo{ Param([Parameter(Mandatory=1)]$Param1=''defaultValue'') }' |
Where-Object { $_.RuleName -eq $ruleName }
$violations.Count | Should -Be 1
}
}

Context "When there are no violations" {
Expand All @@ -21,5 +27,11 @@ Describe "AvoidDefaultValueForMandatoryParameter" {
Where-Object { $_.RuleName -eq $ruleName }
$violations.Count | Should -Be 0
}

It "returns no violations when the parameter is specified as mandatory=0 and has a default value" {
$violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Function foo{ Param([Parameter(Mandatory=$false)]$Param1=''val1'', [Parameter(Mandatory)]$Param2=''val2'', $Param3=''val3'') }' |
Where-Object { $_.RuleName -eq $ruleName }
Copy link
Collaborator

@bergmeister bergmeister Apr 13, 2018

Choose a reason for hiding this comment

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

This test seems to be a copy-paste version of the test above if I am not mistaking? I think you meant to change it t have Mandatory = 0. A cleanup of the other unnecessary and confusing parameters $Param2 and $Param3 would be nice as well.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

$violations.Count | Should -Be 0
}
}
}