Skip to content

Warn when using FileRedirection operator inside if/while statements and improve new PossibleIncorrectUsageOfAssignmentOperator rule #881

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from 5 commits
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
4a0485c
first working prototype that warns against usage of the redirection o…
bergmeister Feb 8, 2018
2c0bc28
adapt error message strings and add tests
bergmeister Feb 8, 2018
29c7e34
remove old todo comment
bergmeister Feb 8, 2018
7310387
remove duplicated test case
bergmeister Feb 8, 2018
4078e41
syntax fix from last cleanup commits
bergmeister Feb 8, 2018
b7ad069
tweak extents in error message: for equal sign warnings, it will poin…
bergmeister Feb 12, 2018
8a48a62
Enhance check for assignment by rather checking if assigned variable …
bergmeister Feb 17, 2018
c9d510f
Merge branch 'development' of https://github.com/PowerShell/PSScriptA…
bergmeister Feb 20, 2018
fd339f6
tweak messages and readme
bergmeister Feb 20, 2018
5e8a8be
Merge branch 'WarnPipelineInsideIfStatement' of https://github.com/be…
bergmeister Feb 20, 2018
c74a746
Merge branch 'development' of https://github.com/PowerShell/PSScriptA…
bergmeister Feb 20, 2018
b467d10
update to pester v4 syntax
bergmeister Feb 20, 2018
594414f
Revert to not check assigned variable usage of RHS but add optional c…
bergmeister Feb 25, 2018
c4e242e
Minor fix resource variable naming
bergmeister Feb 25, 2018
f7ce114
uncommented accidental comment out of ipmo pssa in tests
bergmeister Feb 25, 2018
bc00213
do not exclude BinaryExpressionAst on RHS because this case is the ch…
bergmeister Feb 26, 2018
c6c4f4a
update test to test against clang suppression
bergmeister Feb 26, 2018
691f2ce
make clang suppression work again
bergmeister Feb 26, 2018
fe30f4d
reword warning text to use 'equality operator' instead of 'equals ope…
bergmeister Feb 27, 2018
78ef4bf
Always warn when LHS is $null
bergmeister Feb 28, 2018
675e3eb
Enhance PossibleIncorrectUsageOfAssignmentOperator rule to do the sam…
bergmeister Mar 15, 2018
ad008cd
tweak message to be more generic in terms of the conditional statement
bergmeister Mar 15, 2018
d042f37
Merge branch 'development' of https://github.com/PowerShell/PSScriptA…
bergmeister Mar 23, 2018
f530d75
Address PR comments
bergmeister Mar 23, 2018
ed95d84
Merge branch 'development' of https://github.com/PowerShell/PSScriptA…
bergmeister Mar 30, 2018
bdf39ac
Merge branch 'development' of https://github.com/PowerShell/PSScriptA…
bergmeister Apr 5, 2018
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

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# PossibleIncorrectUsageOfComparisonOperator

**Severity Level: Information**
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I was wondering because we can determine pretty accurately know that the usage of the comparison operator inside if statements is unintentional, if we should up the level to warning because some people ignore/disable warnings of informational level?


## Description

In many programming languages, the comparison operator for greater is `>` but `PowerShell` uses `-gt` for it and `-ge` for `>=`. Similarly the equality operator is denoted as `==` or `=` in many programming languages, but `PowerShell` uses `-eq`. Since using as the FileRedirection operator `>` or the assignment operator are rarely needed inside if statements, this rule wants to call out this case because it was probably unintentional.
23 changes: 16 additions & 7 deletions Rules/PossibleIncorrectUsageOfAssignmentOperator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,13 @@
namespace Microsoft.Windows.PowerShell.ScriptAnalyzer.BuiltinRules
{
/// <summary>
/// PossibleIncorrectUsageOfAssignmentOperator: Warn if someone uses the '=' or '==' by accident in an if statement because in most cases that is not the intention.
/// PossibleIncorrectUsageOfAssignmentOperator: Warn if someone uses '>', '=' or '==' operators inside an if or elseif statement because in most cases that is not the intention.
/// The origin of this rule is that people often forget that operators change when switching between different languages such as C# and PowerShell.
/// </summary>
#if !CORECLR
[Export(typeof(IScriptRule))]
#endif
public class PossibleIncorrectUsageOfAssignmentOperator : AstVisitor, IScriptRule
public class PossibleIncorrectUsageOfComparisonOperator : AstVisitor, IScriptRule
{
/// <summary>
/// The idea is to get all AssignmentStatementAsts and then check if the parent is an IfStatementAst, which includes if, elseif and else statements.
Expand All @@ -49,7 +50,7 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
if (assignmentStatementAst.Right.Extent.Text.StartsWith("="))
{
yield return new DiagnosticRecord(
Strings.PossibleIncorrectUsageOfAssignmentOperatorError, assignmentStatementAst.Extent,
Strings.PossibleIncorrectUsageOfComparisonOperatorAssignmentOperatorError, assignmentStatementAst.Extent,
GetName(), DiagnosticSeverity.Warning, fileName);
}
else
Expand All @@ -60,11 +61,19 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
if (commandAst == null)
{
yield return new DiagnosticRecord(
Strings.PossibleIncorrectUsageOfAssignmentOperatorError, assignmentStatementAst.Extent,
Strings.PossibleIncorrectUsageOfComparisonOperatorAssignmentOperatorError, assignmentStatementAst.Extent,
GetName(), DiagnosticSeverity.Information, fileName);
}
}
}

var fileRedirectionAst = clause.Item1.Find(testAst => testAst is FileRedirectionAst, searchNestedScriptBlocks: false) as FileRedirectionAst;
if (fileRedirectionAst != null)
{
yield return new DiagnosticRecord(
Strings.PossibleIncorrectUsageOfComparisonOperatorFileRedirectionOperatorError, fileRedirectionAst.Extent,
GetName(), DiagnosticSeverity.Warning, fileName);
}
}
}
}
Expand All @@ -75,7 +84,7 @@ public IEnumerable<DiagnosticRecord> AnalyzeScript(Ast ast, string fileName)
/// <returns>The name of this rule</returns>
public string GetName()
{
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.PossibleIncorrectUsageOfAssignmentOperatorName);
return string.Format(CultureInfo.CurrentCulture, Strings.NameSpaceFormat, GetSourceName(), Strings.PossibleIncorrectUsageOfComparisonOperatorName);
}

/// <summary>
Expand All @@ -84,7 +93,7 @@ public string GetName()
/// <returns>The common name of this rule</returns>
public string GetCommonName()
{
return string.Format(CultureInfo.CurrentCulture, Strings.PossibleIncorrectUsageOfAssignmentOperatorCommonName);
return string.Format(CultureInfo.CurrentCulture, Strings.PossibleIncorrectUsageOfComparisonOperatorCommonName);
}

/// <summary>
Expand All @@ -93,7 +102,7 @@ public string GetCommonName()
/// <returns>The description of this rule</returns>
public string GetDescription()
{
return string.Format(CultureInfo.CurrentCulture, Strings.AvoidUsingWriteHostDescription);
return string.Format(CultureInfo.CurrentCulture, Strings.PossibleIncorrectUsageOfComparisonOperatorDescription);
}

/// <summary>
Expand Down
34 changes: 26 additions & 8 deletions Rules/Strings.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

16 changes: 11 additions & 5 deletions Rules/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -981,14 +981,14 @@
<data name="AlignAssignmentStatementError" xml:space="preserve">
<value>Assignment statements are not aligned</value>
</data>
<data name="PossibleIncorrectUsageOfAssignmentOperatorCommonName" xml:space="preserve">
<data name="PossibleIncorrectUsageOfComparisonOperatorCommonName" xml:space="preserve">
<value>'=' operator means assignment. Did you mean the equal operator '-eq'?</value>
</data>
<data name="PossibleIncorrectUsageOfAssignmentOperatorError" xml:space="preserve">
<value>Did you really mean to make an assignment inside an if statement? If you rather meant to check for equality, use the '-eq' operator.</value>
<data name="PossibleIncorrectUsageOfComparisonOperatorAssignmentOperatorError" xml:space="preserve">
<value>Did you really mean to use the assignment operator '=' inside an if statement? If you rather meant to check for equality, use the '-eq' operator.</value>
</data>
<data name="PossibleIncorrectUsageOfAssignmentOperatorName" xml:space="preserve">
<value>PossibleIncorrectUsageOfAssignmentOperator</value>
<data name="PossibleIncorrectUsageOfComparisonOperatorName" xml:space="preserve">
<value>PossibleIncorrectUsageOfComparisonOperator</value>
</data>
<data name="AvoidAssignmentToReadOnlyAutomaticVariable" xml:space="preserve">
<value>Use a different variable name</value>
Expand All @@ -1005,4 +1005,10 @@
<data name="AvoidAssignmentToAutomaticVariableName" xml:space="preserve">
<value>AvoidAssignmentToAutomaticVariable</value>
</data>
<data name="PossibleIncorrectUsageOfComparisonOperatorDescription" xml:space="preserve">
<value>'&gt;', '=' or '==' are not comparison operators in the PowerShell language and rarely needed inside if statements.</value>
</data>
<data name="PossibleIncorrectUsageOfComparisonOperatorFileRedirectionOperatorError" xml:space="preserve">
<value>Did you really mean to use the redirection operator '&gt;'? If you wanted to use an equality comparer then use the '-gt' (greater than) or '-ge' (greater or equal) operators.</value>
</data>
</root>
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
Import-Module PSScriptAnalyzer
$ruleName = "PSPossibleIncorrectUsageOfAssignmentOperator"
#Import-Module PSScriptAnalyzer
$ruleName = "PSPossibleIncorrectUsageOfComparisonOperator"

Describe "PossibleIncorrectUsageOfAssignmentOperator" {
Describe "PossibleIncorrectUsageOfComparisonOperator" {
Context "When there are violations" {
It "assignment inside if statement causes warning" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a=$b){}' | Where-Object {$_.RuleName -eq $ruleName}
Expand Down Expand Up @@ -37,6 +37,26 @@ Describe "PossibleIncorrectUsageOfAssignmentOperator" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a == "$b"){}' | Where-Object {$_.RuleName -eq $ruleName}
$warnings.Count | Should Be 1
}

It "File redirection operator inside if statement causes warning" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a > $b){}' | Where-Object {$_.RuleName -eq $ruleName}
$warnings.Count | Should Be 1
}

It "File redirection operator inside if statement causes warning when wrapped in command expression" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a > ($b)){}' | Where-Object {$_.RuleName -eq $ruleName}
$warnings.Count | Should Be 1
}

It "File redirection operator inside if statement causes warning when wrapped in expression" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a > "$b"){}' | Where-Object {$_.RuleName -eq $ruleName}
$warnings.Count | Should Be 1
}

It "File redirection operator inside elseif statement causes warning" {
$warnings = Invoke-ScriptAnalyzer -ScriptDefinition 'if ($a -eq $b){}elseif($a > $b){}' | Where-Object {$_.RuleName -eq $ruleName}
$warnings.Count | Should Be 1
}
}

Context "When there are no violations" {
Expand Down