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
New rule S2198: Silly mathematical comparisons should not be made #6695
Conversation
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@gregory-paidis-sonarsource you are probably better of deleting much of your changes so far. This is the most difficult thing to do as a developer (I'm also bad at this) but there is too much debris from previous attempts lurking around that is just a distraction. Start with my bullet points so we have something sensible to start with.
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyBitwiseOperation.cs
Outdated
Show resolved
Hide resolved
@martin-strecker-sonarsource makes sense, it looks quite messy right now. Thank you greatly for all the feedback and the steps you suggested, I will implement this in that manner only for floats (baby steps) and then get back to you. |
…ats for this step
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Some clean-up.
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
var typeIdentifier = string.Empty; | ||
if (ShouldRaise(context.SemanticModel, binary.Left, binary.Right, ref typeIdentifier)) | ||
{ | ||
context.ReportIssue(Diagnostic.Create(Rule, binary.GetLocation(), typeIdentifier)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Roslyn provides an API for naming things in the shortest possible way:
var typeName = context.SemanticModel.GetSymbolInfo(other).Symbol.ToMinimalDisplayString(model, other.GetLocation().SourceSpan.Start)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried it, but for some reason it gives me the name of the entire node, for example ulong variableName
.
I ended up using this, which is also slightly more succinct:
// returns ulong, instead of 'ulong variableName'
var typeName = context.SemanticModel.GetTypeInfo(second).Type.ToString();
It also works if you declare the type as System.UInt64
, giving back the simplest form of the type (the primitive ulong
).
Note: Included the ulong
and long
types, since they are not checked by the CS0652
compiler warning.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You probably called it on an ILocalSymbol
which represents a local variable. You need it for the ITypeSymbol of the type of the expression. Use semanticModel.GetTypeInfo(second)
and call ToDisplayString on it.
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we will scope the PR to what we have now. The checks at the boundary can be done later.
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.CSharp9.cs
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good. Let's do some clean-up.
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
&& TryGetRange(typeSymbolOfOther, out var min, out var max) | ||
&& (constant < min || constant > max)) | ||
{ | ||
var typeName = context.SemanticModel.GetTypeInfo(other).Type.ToMinimalDisplayString(context.SemanticModel, other.GetLocation().SourceSpan.Start); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You can use the location of the node here and in the report. Store the location as a local for re-use.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
But i use two different locations. One if other.GetLocation()
, the other is other.Parent.GetLocation()
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ToMinimalDisplayString needs the position to be aware of the usings
and namespace
that are relevant to the position. You can post whatever location is close. other
or other.Parent
don't make a difference in this respect.
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/tests/SonarAnalyzer.UnitTest/TestCases/SillyMathematicalComparison.CSharp9.cs
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
analyzers/src/SonarAnalyzer.CSharp/Rules/SillyMathematicalComparison.cs
Outdated
Show resolved
Hide resolved
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM. Two minor suggestions.
const float number1 = 42; | ||
const double number2 = double.MaxValue; | ||
|
||
_ = number1 != number2; // Compliant, constant in both operands |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Link to the issue about this phenomenon.
if (TryGetConstantValue(context.SemanticModel, (BinaryExpressionSyntax)context.Node, out var constant, out var other) | ||
&& context.SemanticModel.GetTypeInfo(other).Type is { } typeSymbolOfOther | ||
&& TryGetRange(typeSymbolOfOther) is { } range | ||
&& (constant < range.Min || constant > range.Max)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
NIT: Could be made a method on the ValueRange
type
&& (constant < range.Min || constant > range.Max)) | |
&& range.IsOutOfRange(constant) |
Kudos, SonarCloud Quality Gate passed! |
Kudos, SonarCloud Quality Gate passed! |
Fixed #6658
RSPEC PR: SonarSource/rspec#1534
S2198