Skip to content

Commit 30eb91a

Browse files
bergmeisterJamesWTruher
authored andcommitted
Fix AvoidDefaultValueForMandatoryParameter documentation, rule and tests (#907)
* make AvoidDefaultValueForMandatoryParameter also warn when not using cmdletbinding and fix documentation: TODO: tidy up tests * adapt tests
1 parent bdb8707 commit 30eb91a

5 files changed

+32
-102
lines changed

RuleDocumentation/AvoidDefaultValueForMandatoryParameter.md

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,29 +4,35 @@
44

55
## Description
66

7-
Just like non-global scoped variables, parameters must have a default value if they are not mandatory, i.e `Mandatory=$false`.
8-
Having optional parameters without default values leads to uninitialized variables leading to potential bugs.
9-
10-
## How
11-
12-
Specify a default value for all parameters that are not mandatory.
7+
Mandatory parameters should not have a default values because there is no scenario where the default can be used because `PowerShell` will prompt anyway if the parameter value is not specified when calling the function.
138

149
## Example
1510

1611
### Wrong
1712

1813
``` PowerShell
19-
function Test($Param1)
14+
function Test
2015
{
21-
$Param1
16+
17+
[CmdletBinding()]
18+
Param
19+
(
20+
[Parameter(Mandatory=$true)]
21+
$Parameter1 = 'default Value'
22+
)
2223
}
2324
```
2425

2526
### Correct
2627

2728
``` PowerShell
28-
function Test($Param1 = $null)
29+
function Test
2930
{
30-
$Param1
31+
[CmdletBinding()]
32+
Param
33+
(
34+
[Parameter(Mandatory=$true)]
35+
$Parameter1
36+
)
3137
}
3238
```

Rules/AvoidDefaultValueForMandatoryParameter.cs

Lines changed: 4 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,8 @@
1-
//
2-
// Copyright (c) Microsoft Corporation.
3-
//
4-
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
5-
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
6-
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
7-
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
8-
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
9-
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
10-
// THE SOFTWARE.
11-
//
1+
// Copyright (c) Microsoft Corporation. All rights reserved.
2+
// Licensed under the MIT License.
123

134
using System;
14-
using System.Linq;
155
using System.Collections.Generic;
16-
using System.Management.Automation;
176
using System.Management.Automation.Language;
187
#if !CORECLR
198
using System.ComponentModel.Composition;
@@ -24,15 +13,15 @@
2413
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
2514
{
2615
/// <summary>
27-
/// ProvideDefaultParameterValue: Check if any uninitialized variable is used.
16+
/// AvoidDefaultValueForMandatoryParameter: Check if a mandatory parameter does not have a default value.
2817
/// </summary>
2918
#if !CORECLR
3019
[Export(typeof(IScriptRule))]
3120
#endif
3221
public class AvoidDefaultValueForMandatoryParameter : IScriptRule
3322
{
3423
/// <summary>
35-
/// AnalyzeScript: Check if any uninitialized variable is used.
24+
/// AnalyzeScript: Check if a mandatory parameter has a default value.
3625
/// </summary>
3726
public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
3827
{
@@ -46,12 +35,6 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
4635
if (funcAst.Body != null && funcAst.Body.ParamBlock != null
4736
&& funcAst.Body.ParamBlock.Attributes != null && funcAst.Body.ParamBlock.Parameters != null)
4837
{
49-
// only raise this rule for function with cmdletbinding
50-
if (!funcAst.Body.ParamBlock.Attributes.Any(attr => attr.TypeName.GetReflectionType() == typeof(CmdletBindingAttribute)))
51-
{
52-
continue;
53-
}
54-
5538
foreach (var paramAst in funcAst.Body.ParamBlock.Parameters)
5639
{
5740
bool mandatory = false;

Tests/Rules/AvoidDefaultValueForMandatoryParameter.ps1

Lines changed: 0 additions & 42 deletions
This file was deleted.
Lines changed: 12 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,26 @@
11
Import-Module PSScriptAnalyzer
2-
$violationName = "PSAvoidDefaultValueForMandatoryParameter"
3-
$violationMessage = "Mandatory Parameter 'Param1' is initialized in the Param block. To fix a violation of this rule, please leave it unintialized."
4-
$directory = Split-Path -Parent $MyInvocation.MyCommand.Path
5-
$violations = Invoke-ScriptAnalyzer "$directory\AvoidDefaultValueForMandatoryParameter.ps1" | Where-Object {$_.RuleName -match $violationName}
6-
$noViolations = Invoke-ScriptAnalyzer "$directory\AvoidDefaultValueForMandatoryParameterNoViolations.ps1"
2+
$ruleName = 'PSAvoidDefaultValueForMandatoryParameter'
73

84
Describe "AvoidDefaultValueForMandatoryParameter" {
95
Context "When there are violations" {
10-
It "has 1 provide default value for mandatory parameter violation" {
6+
It "has 1 provide default value for mandatory parameter violation with CmdletBinding" {
7+
$violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Function foo{ [CmdletBinding()]Param([Parameter(Mandatory)]$Param1=''defaultValue'') }' |
8+
Where-Object { $_.RuleName -eq $ruleName }
119
$violations.Count | Should -Be 1
1210
}
1311

14-
It "has the correct description message" {
15-
$violations[0].Message | Should -Match $violationMessage
12+
It "has 1 provide default value for mandatory=$true parameter violation without CmdletBinding" {
13+
$violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Function foo{ Param([Parameter(Mandatory=$true)]$Param1=''defaultValue'') }' |
14+
Where-Object { $_.RuleName -eq $ruleName }
15+
$violations.Count | Should -Be 1
1616
}
1717
}
1818

1919
Context "When there are no violations" {
20-
It "returns no violations" {
21-
$noViolations.Count | Should -Be 0
20+
It "has 1 provide default value for mandatory parameter violation" {
21+
$violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Function foo{ Param([Parameter(Mandatory=$false)]$Param1=''val1'', [Parameter(Mandatory)]$Param2=''val2'', $Param3=''val3'') }' |
22+
Where-Object { $_.RuleName -eq $ruleName }
23+
$violations.Count | Should -Be 0
2224
}
2325
}
2426
}

Tests/Rules/AvoidDefaultValueForMandatoryParameterNoViolations.ps1

Lines changed: 0 additions & 19 deletions
This file was deleted.

0 commit comments

Comments
 (0)