Skip to content

Commit 40be593

Browse files
authored
Enable suppression of PSAvoidAssignmentToAutomaticVariable for specific variable or parameter (#1896)
* add ruleId to PSAvoidAssignmentToAutomaticVariable Enables suppression for specific variable/parameter. Fix #1589 * add tests
1 parent 2e77c2a commit 40be593

File tree

2 files changed

+81
-57
lines changed

2 files changed

+81
-57
lines changed

Diff for: Rules/AvoidAssignmentToAutomaticVariable.cs

+6-6
Original file line numberDiff line numberDiff line change
@@ -62,20 +62,20 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
6262
if (_readOnlyAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase))
6363
{
6464
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableError, variableName),
65-
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Error, fileName);
65+
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Error, fileName, variableName);
6666
}
6767

6868
if (_readOnlyAutomaticVariablesIntroducedInVersion6_0.Contains(variableName, StringComparer.OrdinalIgnoreCase))
6969
{
7070
var severity = IsPowerShellVersion6OrGreater() ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning;
7171
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableIntroducedInPowerShell6_0Error, variableName),
72-
variableExpressionAst.Extent, GetName(), severity, fileName);
72+
variableExpressionAst.Extent, GetName(), severity, fileName, variableName);
7373
}
7474

7575
if (_writableAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase))
7676
{
7777
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToWritableAutomaticVariableError, variableName),
78-
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
78+
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, variableName);
7979
}
8080
}
8181

@@ -93,20 +93,20 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
9393
if (_readOnlyAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase))
9494
{
9595
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableError, variableName),
96-
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Error, fileName);
96+
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Error, fileName, variableName);
9797
}
9898

9999
if (_readOnlyAutomaticVariablesIntroducedInVersion6_0.Contains(variableName, StringComparer.OrdinalIgnoreCase))
100100
{
101101
var severity = IsPowerShellVersion6OrGreater() ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning;
102102
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableIntroducedInPowerShell6_0Error, variableName),
103-
variableExpressionAst.Extent, GetName(), severity, fileName);
103+
variableExpressionAst.Extent, GetName(), severity, fileName, variableName);
104104
}
105105

106106
if (_writableAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase))
107107
{
108108
yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToWritableAutomaticVariableError, variableName),
109-
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName);
109+
variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, variableName);
110110
}
111111
}
112112
}

Diff for: Tests/Rules/AvoidAssignmentToAutomaticVariable.tests.ps1

+75-51
Original file line numberDiff line numberDiff line change
@@ -7,60 +7,61 @@ BeforeAll {
77

88
Describe "AvoidAssignmentToAutomaticVariables" {
99
Context "ReadOnly Variables" {
10+
BeforeDiscovery {
11+
$excpectedSeverityForAutomaticVariablesInPowerShell6 = 'Warning'
12+
if ($PSVersionTable.PSVersion.Major -ge 6)
13+
{
14+
$excpectedSeverityForAutomaticVariablesInPowerShell6 = 'Error'
15+
}
1016

11-
$excpectedSeverityForAutomaticVariablesInPowerShell6 = 'Warning'
12-
if ($PSVersionTable.PSVersion.Major -ge 6)
13-
{
14-
$excpectedSeverityForAutomaticVariablesInPowerShell6 = 'Error'
17+
$testCases_AutomaticVariables = @(
18+
@{ VariableName = '?'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
19+
@{ VariableName = 'Error' ; ExpectedSeverity = 'Error'; IsReadOnly = $true }
20+
@{ VariableName = 'ExecutionContext'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
21+
@{ VariableName = 'false'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
22+
@{ VariableName = 'Home'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
23+
@{ VariableName = 'Host'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
24+
@{ VariableName = 'PID'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
25+
@{ VariableName = 'PSCulture'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
26+
@{ VariableName = 'PSEdition'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
27+
@{ VariableName = 'PSHome'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
28+
@{ VariableName = 'PSUICulture'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
29+
@{ VariableName = 'PSVersionTable'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
30+
@{ VariableName = 'ShellId'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
31+
@{ VariableName = 'true'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
32+
# Variables introduced only in PowerShell 6+ have a Severity of Warning only
33+
@{ VariableName = 'IsCoreCLR'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
34+
@{ VariableName = 'IsLinux'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
35+
@{ VariableName = 'IsMacOS'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
36+
@{ VariableName = 'IsWindows'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
37+
@{ VariableName = '_'; ExpectedSeverity = 'Warning' }
38+
@{ VariableName = 'AllNodes'; ExpectedSeverity = 'Warning' }
39+
@{ VariableName = 'Args'; ExpectedSeverity = 'Warning' }
40+
@{ VariableName = 'ConsoleFilename'; ExpectedSeverity = 'Warning' }
41+
@{ VariableName = 'Event'; ExpectedSeverity = 'Warning' }
42+
@{ VariableName = 'EventArgs'; ExpectedSeverity = 'Warning' }
43+
@{ VariableName = 'EventSubscriber'; ExpectedSeverity = 'Warning' }
44+
@{ VariableName = 'ForEach'; ExpectedSeverity = 'Warning' }
45+
@{ VariableName = 'Input'; ExpectedSeverity = 'Warning' }
46+
@{ VariableName = 'Matches'; ExpectedSeverity = 'Warning' }
47+
@{ VariableName = 'MyInvocation'; ExpectedSeverity = 'Warning' }
48+
@{ VariableName = 'NestedPromptLevel'; ExpectedSeverity = 'Warning' }
49+
@{ VariableName = 'Profile'; ExpectedSeverity = 'Warning' }
50+
@{ VariableName = 'PSBoundParameters'; ExpectedSeverity = 'Warning' }
51+
@{ VariableName = 'PsCmdlet'; ExpectedSeverity = 'Warning' }
52+
@{ VariableName = 'PSCommandPath'; ExpectedSeverity = 'Warning' }
53+
@{ VariableName = 'ReportErrorShowExceptionClass'; ExpectedSeverity = 'Warning' }
54+
@{ VariableName = 'ReportErrorShowInnerException'; ExpectedSeverity = 'Warning' }
55+
@{ VariableName = 'ReportErrorShowSource'; ExpectedSeverity = 'Warning' }
56+
@{ VariableName = 'ReportErrorShowStackTrace'; ExpectedSeverity = 'Warning' }
57+
@{ VariableName = 'Sender'; ExpectedSeverity = 'Warning' }
58+
@{ VariableName = 'StackTrace'; ExpectedSeverity = 'Warning' }
59+
@{ VariableName = 'This'; ExpectedSeverity = 'Warning' }
60+
)
61+
62+
$testCases_ReadOnlyAutomaticVariables = $testCases_AutomaticVariables | Where-Object { $_.IsReadonly }
1563
}
1664

17-
$testCases_AutomaticVariables = @(
18-
@{ VariableName = '?'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
19-
@{ VariableName = 'Error' ; ExpectedSeverity = 'Error'; IsReadOnly = $true }
20-
@{ VariableName = 'ExecutionContext'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
21-
@{ VariableName = 'false'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
22-
@{ VariableName = 'Home'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
23-
@{ VariableName = 'Host'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
24-
@{ VariableName = 'PID'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
25-
@{ VariableName = 'PSCulture'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
26-
@{ VariableName = 'PSEdition'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
27-
@{ VariableName = 'PSHome'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
28-
@{ VariableName = 'PSUICulture'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
29-
@{ VariableName = 'PSVersionTable'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
30-
@{ VariableName = 'ShellId'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
31-
@{ VariableName = 'true'; ExpectedSeverity = 'Error'; IsReadOnly = $true }
32-
# Variables introduced only in PowerShell 6+ have a Severity of Warning only
33-
@{ VariableName = 'IsCoreCLR'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
34-
@{ VariableName = 'IsLinux'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
35-
@{ VariableName = 'IsMacOS'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
36-
@{ VariableName = 'IsWindows'; ExpectedSeverity = $excpectedSeverityForAutomaticVariablesInPowerShell6; OnlyPresentInCoreClr = $true }
37-
@{ VariableName = '_'; ExpectedSeverity = 'Warning' }
38-
@{ VariableName = 'AllNodes'; ExpectedSeverity = 'Warning' }
39-
@{ VariableName = 'Args'; ExpectedSeverity = 'Warning' }
40-
@{ VariableName = 'ConsoleFilename'; ExpectedSeverity = 'Warning' }
41-
@{ VariableName = 'Event'; ExpectedSeverity = 'Warning' }
42-
@{ VariableName = 'EventArgs'; ExpectedSeverity = 'Warning' }
43-
@{ VariableName = 'EventSubscriber'; ExpectedSeverity = 'Warning' }
44-
@{ VariableName = 'ForEach'; ExpectedSeverity = 'Warning' }
45-
@{ VariableName = 'Input'; ExpectedSeverity = 'Warning' }
46-
@{ VariableName = 'Matches'; ExpectedSeverity = 'Warning' }
47-
@{ VariableName = 'MyInvocation'; ExpectedSeverity = 'Warning' }
48-
@{ VariableName = 'NestedPromptLevel'; ExpectedSeverity = 'Warning' }
49-
@{ VariableName = 'Profile'; ExpectedSeverity = 'Warning' }
50-
@{ VariableName = 'PSBoundParameters'; ExpectedSeverity = 'Warning' }
51-
@{ VariableName = 'PsCmdlet'; ExpectedSeverity = 'Warning' }
52-
@{ VariableName = 'PSCommandPath'; ExpectedSeverity = 'Warning' }
53-
@{ VariableName = 'ReportErrorShowExceptionClass'; ExpectedSeverity = 'Warning' }
54-
@{ VariableName = 'ReportErrorShowInnerException'; ExpectedSeverity = 'Warning' }
55-
@{ VariableName = 'ReportErrorShowSource'; ExpectedSeverity = 'Warning' }
56-
@{ VariableName = 'ReportErrorShowStackTrace'; ExpectedSeverity = 'Warning' }
57-
@{ VariableName = 'Sender'; ExpectedSeverity = 'Warning' }
58-
@{ VariableName = 'StackTrace'; ExpectedSeverity = 'Warning' }
59-
@{ VariableName = 'This'; ExpectedSeverity = 'Warning' }
60-
)
61-
62-
$testCases_ReadOnlyAutomaticVariables = $testCases_AutomaticVariables | Where-Object { $_.IsReadonly }
63-
6465
It "Variable <VariableName> produces warning of Severity <ExpectedSeverity>" -TestCases $testCases_AutomaticVariables {
6566
param ($VariableName, $ExpectedSeverity)
6667

@@ -133,6 +134,29 @@ Describe "AvoidAssignmentToAutomaticVariables" {
133134
}
134135
}
135136
}
137+
}
138+
139+
Context 'Suppression' {
140+
BeforeDiscovery {
141+
$testCases_RuleSuppression = @(
142+
@{ VariableName = 'true'; Type = 'ReadOnlyAutomaticVariableError' }
143+
@{ VariableName = 'IsWindows'; Type = 'ReadOnlyAutomaticVariableIntroducedInPowerShell6_0Error' }
144+
@{ VariableName = 'ForEach'; Type = 'WritableAutomaticVariableError' }
145+
)
146+
}
147+
148+
It 'Variable <VariableName> of type <Type> can be suppressed by RuleSuppressionId' -TestCases $testCases_RuleSuppression {
149+
$scriptDef = @"
150+
function suppressionTest {
151+
[System.Diagnostics.CodeAnalysis.SuppressMessageAttribute('$ruleName', '$VariableName')]
152+
param(
153+
`$$VariableName
154+
)
155+
}
156+
"@
136157

158+
$warnings = @(Invoke-ScriptAnalyzer -ScriptDefinition $scriptDef -ExcludeRule PSReviewUnusedParameter)
159+
$warnings.Count | Should -Be 0
160+
}
137161
}
138162
}

0 commit comments

Comments
 (0)