diff --git a/Rules/UseCorrectCasing.cs b/Rules/UseCorrectCasing.cs index 5d1393d45..f4f2c40b7 100644 --- a/Rules/UseCorrectCasing.cs +++ b/Rules/UseCorrectCasing.cs @@ -103,7 +103,19 @@ public override IEnumerable AnalyzeScript(Ast ast, string file if (!commandName.Equals(correctlyCasedCommandName, StringComparison.Ordinal)) { - yield return GetDiagnosticRecord(commandAst, fileName, correctlyCasedCommandName, Strings.UseCorrectCasingError); + var extent = GetCommandExtent(commandAst); + yield return new DiagnosticRecord( + string.Format( + CultureInfo.CurrentCulture, + Strings.UseCorrectCasingError, + commandName, + correctlyCasedCommandName), + extent, + GetName(), + DiagnosticSeverity.Information, + fileName, + correctlyCasedCommandName, + GetCorrectionExtent(commandAst, extent, correctlyCasedCommandName)); } var commandParameterAsts = commandAst.FindAll( @@ -129,7 +141,19 @@ public override IEnumerable AnalyzeScript(Ast ast, string file var correctlyCasedParameterName = parameterMetaData.Name; if (!parameterName.Equals(correctlyCasedParameterName, StringComparison.Ordinal)) { - yield return GetDiagnosticRecord(commandParameterAst, fileName, correctlyCasedParameterName, Strings.UseCorrectCasingError); + yield return new DiagnosticRecord( + string.Format( + CultureInfo.CurrentCulture, + Strings.UseCorrectCasingParameterError, + commandParameterAst.Extent.Text, + commandName, + correctlyCasedParameterName), + commandParameterAst.Extent, + GetName(), + DiagnosticSeverity.Information, + fileName, + correctlyCasedParameterName, + GetCorrectionExtent(commandParameterAst, commandParameterAst.Extent, correctlyCasedParameterName)); } } } @@ -137,7 +161,6 @@ public override IEnumerable AnalyzeScript(Ast ast, string file } } - /// /// For a command like "gci -path c:", returns the extent of "gci" in the command /// @@ -197,32 +220,6 @@ private DiagnosticRecord GetDiagnosticRecord(Token token, string fileName, strin suggestedCorrections: extents); } - private DiagnosticRecord GetDiagnosticRecord(Ast ast, string fileName, string correction, string message) - { - var extent = ast is CommandAst ? GetCommandExtent((CommandAst)ast) : ast.Extent; - return new DiagnosticRecord( - string.Format(CultureInfo.CurrentCulture, message, extent.Text, correction), - extent, - GetName(), - DiagnosticSeverity.Information, - fileName, - correction, - suggestedCorrections: GetCorrectionExtent(ast, extent, correction)); - } - - private DiagnosticRecord GetDiagnosticRecord(CommandParameterAst ast, string fileName, string correction, string message) - { - var extent = ast.Extent; - return new DiagnosticRecord( - string.Format(CultureInfo.CurrentCulture, message, extent.Text, correction), - extent, - GetName(), - DiagnosticSeverity.Information, - fileName, - correction, - suggestedCorrections: GetCorrectionExtent(ast, extent, correction)); - } - /// /// GetName: Retrieves the name of this rule. /// diff --git a/Tests/Rules/UseCorrectCasing.tests.ps1 b/Tests/Rules/UseCorrectCasing.tests.ps1 index c142dd2da..7caafe4e0 100644 --- a/Tests/Rules/UseCorrectCasing.tests.ps1 +++ b/Tests/Rules/UseCorrectCasing.tests.ps1 @@ -103,6 +103,27 @@ Describe "UseCorrectCasing" { Should -BeExactly '$A++; $B--' } + It "Shows relevant diagnostic message for function/command name casing" { + $settings = @{ 'Rules' = @{ 'PSUseCorrectCasing' = @{ 'Enable' = $true; CheckCommands = $true; CheckKeywords = $true; CheckOperators = $true } } } + $violations = Invoke-ScriptAnalyzer -ScriptDefinition 'WHERE-OBJECT Name -EQ "Value"' -Settings $settings + $violations.Count | Should -Be 1 + $violations[0].Message | Should -Be "Function/Cmdlet 'WHERE-OBJECT' does not match its exact casing 'Where-Object'." + } + + It "Shows relevant diagnostic message for parameter casing" { + $settings = @{ 'Rules' = @{ 'PSUseCorrectCasing' = @{ 'Enable' = $true; CheckCommands = $true; CheckKeywords = $true; CheckOperators = $true } } } + $violations = Invoke-ScriptAnalyzer -ScriptDefinition 'Where-Object Name -eq "Value"' -Settings $settings + $violations.Count | Should -Be 1 + $violations[0].Message | Should -Be "Parameter '-eq' of function/cmdlet 'Where-Object' does not match its exact casing 'EQ'." + } + + It "Shows relevant diagnostic message for operator casing" { + $settings = @{ 'Rules' = @{ 'PSUseCorrectCasing' = @{ 'Enable' = $true; CheckCommands = $true; CheckKeywords = $true; CheckOperators = $true } } } + $violations = Invoke-ScriptAnalyzer -ScriptDefinition '$a -EQ 1' -Settings $settings + $violations.Count | Should -Be 1 + $violations[0].Message | Should -Be "Operator '-EQ' does not match the expected case '-eq'." + } + Context "Inconsistent Keywords" { It "Corrects keyword case" { Invoke-Formatter 'ForEach ($x IN $y) { $x }' | diff --git a/docs/Rules/UseCorrectCasing.md b/docs/Rules/UseCorrectCasing.md index 1874a7a84..9d7e96a18 100644 --- a/docs/Rules/UseCorrectCasing.md +++ b/docs/Rules/UseCorrectCasing.md @@ -25,7 +25,7 @@ commands. Using lowercase operators helps distinguish them from parameters. ```powershell Rules = @{ - PS UseCorrectCasing = @{ + PSUseCorrectCasing = @{ Enable = $true CheckCommands = $true CheckKeyword = $true @@ -42,7 +42,7 @@ Enable or disable the rule during ScriptAnalyzer invocation. #### CheckCommands: bool (Default value is `$true`) -If true, require the case of all operators to be lowercase. +If true, require the case of all command and parameter names to match their canonical casing. #### CheckKeyword: bool (Default value is `$true`) @@ -50,7 +50,7 @@ If true, require the case of all keywords to be lowercase. #### CheckOperator: bool (Default value is `$true`) -If true, require the case of all commands to match their actual casing. +If true, require the case of all operators (e.g. -eq, -ne, -gt) to be lowercase. ## Examples @@ -58,7 +58,7 @@ If true, require the case of all commands to match their actual casing. ```powershell ForEach ($file in Get-childitem -Recurse) { - $file.Extension -eq '.txt' + $file.Extension -EQ '.txt' } invoke-command { 'foo' } -runasadministrator