diff --git a/Rules/AvoidAssignmentToAutomaticVariable.cs b/Rules/AvoidAssignmentToAutomaticVariable.cs index 8188ccb70..c1ce88462 100644 --- a/Rules/AvoidAssignmentToAutomaticVariable.cs +++ b/Rules/AvoidAssignmentToAutomaticVariable.cs @@ -79,6 +79,31 @@ public IEnumerable AnalyzeScript(Ast ast, string fileName) } } + IEnumerable forEachStatementAsts = ast.FindAll(testAst => testAst is ForEachStatementAst, searchNestedScriptBlocks: true); + foreach (ForEachStatementAst forEachStatementAst in forEachStatementAsts) + { + var variableExpressionAst = forEachStatementAst.Variable; + var variableName = variableExpressionAst.VariablePath.UserPath; + if (_readOnlyAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase)) + { + yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableError, variableName), + variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Error, fileName, variableName); + } + + if (_readOnlyAutomaticVariablesIntroducedInVersion6_0.Contains(variableName, StringComparer.OrdinalIgnoreCase)) + { + var severity = IsPowerShellVersion6OrGreater() ? DiagnosticSeverity.Error : DiagnosticSeverity.Warning; + yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToReadOnlyAutomaticVariableIntroducedInPowerShell6_0Error, variableName), + variableExpressionAst.Extent, GetName(), severity, fileName, variableName); + } + + if (_writableAutomaticVariables.Contains(variableName, StringComparer.OrdinalIgnoreCase)) + { + yield return new DiagnosticRecord(DiagnosticRecordHelper.FormatError(Strings.AvoidAssignmentToWritableAutomaticVariableError, variableName), + variableExpressionAst.Extent, GetName(), DiagnosticSeverity.Warning, fileName, variableName); + } + } + IEnumerable parameterAsts = ast.FindAll(testAst => testAst is ParameterAst, searchNestedScriptBlocks: true); foreach (ParameterAst parameterAst in parameterAsts) { diff --git a/Tests/Rules/AvoidAssignmentToAutomaticVariable.tests.ps1 b/Tests/Rules/AvoidAssignmentToAutomaticVariable.tests.ps1 index e9cc5331f..98f82be41 100644 --- a/Tests/Rules/AvoidAssignmentToAutomaticVariable.tests.ps1 +++ b/Tests/Rules/AvoidAssignmentToAutomaticVariable.tests.ps1 @@ -65,13 +65,22 @@ Describe "AvoidAssignmentToAutomaticVariables" { It "Variable produces warning of Severity " -TestCases $testCases_AutomaticVariables { param ($VariableName, $ExpectedSeverity) - $warnings = Invoke-ScriptAnalyzer -ScriptDefinition "`$${VariableName} = 'foo'" -ExcludeRule PSUseDeclaredVarsMoreThanAssignments + [System.Array] $warnings = Invoke-ScriptAnalyzer -ScriptDefinition "`$${VariableName} = 'foo'" -ExcludeRule PSUseDeclaredVarsMoreThanAssignments $warnings.Count | Should -Be 1 $warnings.Severity | Should -Be $ExpectedSeverity $warnings.RuleName | Should -Be $ruleName } - It "Using Variable as parameter name produces warning of Severity error" -TestCases $testCases_AutomaticVariables { + It "Using Variable as foreach assignment produces warning of Severity " -TestCases $testCases_AutomaticVariables { + param ($VariableName, $ExpectedSeverity) + + [System.Array] $warnings = Invoke-ScriptAnalyzer -ScriptDefinition "foreach (`$$VariableName in `$foo) {}" + $warnings.Count | Should -Be 1 + $warnings.Severity | Should -Be $ExpectedSeverity + $warnings.RuleName | Should -Be $ruleName + } + + It "Using Variable as parameter name produces warning of Severity " -TestCases $testCases_AutomaticVariables { param ($VariableName, $ExpectedSeverity) [System.Array] $warnings = Invoke-ScriptAnalyzer -ScriptDefinition "function foo{Param(`$$VariableName)}" -ExcludeRule PSReviewUnusedParameter @@ -80,7 +89,7 @@ Describe "AvoidAssignmentToAutomaticVariables" { $warnings.RuleName | Should -Be $ruleName } - It "Using Variable as parameter name in param block produces warning of Severity error" -TestCases $testCases_AutomaticVariables { + It "Using Variable as parameter name in param block produces warning of Severity " -TestCases $testCases_AutomaticVariables { param ($VariableName, $ExpectedSeverity) [System.Array] $warnings = Invoke-ScriptAnalyzer -ScriptDefinition "function foo(`$$VariableName){}"