Skip to content
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

Merged
merged 28 commits into from Feb 10, 2023

Conversation

gregory-paidis-sonarsource
Copy link
Contributor

@gregory-paidis-sonarsource gregory-paidis-sonarsource commented Feb 1, 2023

Copy link
Contributor

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.

@gregory-paidis-sonarsource
Copy link
Contributor Author

@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.

@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.

Copy link
Contributor

Choose a reason for hiding this comment

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

Some clean-up.

var typeIdentifier = string.Empty;
if (ShouldRaise(context.SemanticModel, binary.Left, binary.Right, ref typeIdentifier))
{
context.ReportIssue(Diagnostic.Create(Rule, binary.GetLocation(), typeIdentifier));

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)

Copy link
Contributor Author

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.

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.

Copy link
Contributor

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.

Copy link
Contributor

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.

&& 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);

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.

Copy link
Contributor Author

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().

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.

Copy link
Contributor

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

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))

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

Suggested change
&& (constant < range.Min || constant > range.Max))
&& range.IsOutOfRange(constant)

@sonarcloud
Copy link

sonarcloud bot commented Feb 10, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

No Coverage information No Coverage information
No Duplication information No Duplication information

@sonarcloud
Copy link

sonarcloud bot commented Feb 10, 2023

Kudos, SonarCloud Quality Gate passed!    Quality Gate passed

Bug A 0 Bugs
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 0 Code Smells

97.8% 97.8% Coverage
0.0% 0.0% Duplication

@gregory-paidis-sonarsource gregory-paidis-sonarsource merged commit 833e003 into master Feb 10, 2023
@gregory-paidis-sonarsource gregory-paidis-sonarsource deleted the greg/implement-S2198 branch February 10, 2023 13:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

New rule S2198: Silly mathematical comparisons should not be made
2 participants