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

Fix S109 FP: named arguments, constructor calls, single-value attributes #5247

Merged
merged 12 commits into from
Jan 12, 2022

Conversation

andrei-epure-sonarsource
Copy link
Contributor

@andrei-epure-sonarsource andrei-epure-sonarsource commented Jan 7, 2022

Fixes #4737

For validation - doc with Peach numbers before this PR

Please review commit by commit. Most of the changed lines are in updated ITs - 8df471f

@andrei-epure-sonarsource
Copy link
Contributor Author

andrei-epure-sonarsource commented Jan 10, 2022

To avoid a rabbit-hole, I am splitting the discussion&implementation around:

This PR will only focus on reducing the noise.

@andrei-epure-sonarsource andrei-epure-sonarsource changed the title S109 - reduce false positives S109 - reduce false positives for named arguments, attribute usage and other special cases Jan 10, 2022
@andrei-epure-sonarsource andrei-epure-sonarsource changed the title S109 - reduce false positives for named arguments, attribute usage and other special cases S109 - reduce false positives for named arguments, attribute usage and single digit comparisons for well-known properties Jan 10, 2022
@@ -61,52 +61,49 @@ public sealed class MagicNumberShouldNotBeUsed : SonarDiagnosticAnalyzer

private static bool IsExceptionToTheRule(LiteralExpressionSyntax literalExpression) =>
NotConsideredAsMagicNumbers.Contains(literalExpression.Token.ValueText)
// It's ok to use magic numbers as part of a variable declaration
Copy link
Contributor Author

Choose a reason for hiding this comment

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

the comments were useless, removing them

// Inside property we consider magic numbers as exceptions in the following cases:
// - A {get; set;} = MAGIC_NUMBER
// - A { get { return MAGIC_NUMBER; } }
private static bool IsInsideProperty(SyntaxNode node)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was just reordered above, no functional change


private static bool IsSingleDigitInToleratedComparisons(LiteralExpressionSyntax literalExpression) =>
literalExpression.Parent is BinaryExpressionSyntax binaryExpression
&& binaryExpression.IsAnyKind(SyntaxKind.EqualsExpression, SyntaxKind.LessThanExpression, SyntaxKind.LessThanOrEqualExpression)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was fixed in bc1eebc

@andrei-epure-sonarsource andrei-epure-sonarsource changed the title S109 - reduce false positives for named arguments, attribute usage and single digit comparisons for well-known properties S109 - reduce false positives for named arguments, attribute usage, "From...()" methods and single digit comparisons for well-known properties Jan 10, 2022
// Inside property we consider magic numbers as exceptions in the following cases:
// - A {get; set;} = MAGIC_NUMBER
// - A { get { return MAGIC_NUMBER; } }
private static bool IsInsideProperty(SyntaxNode node)
Copy link
Contributor Author

Choose a reason for hiding this comment

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

this was just reordered from below, no functional change (see in overall changes this part didn't change)


private static bool ToStringContainsAnyAcceptedNames(SyntaxNode syntaxNode)
{
var toString = syntaxNode.ToString().ToLower();
Copy link
Contributor

Choose a reason for hiding this comment

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

My understanding is that we accept the methods Count, Size, Length, Order coming from particular namespaces (e.g., IEnumerable).
In this case, the full name needs to be checked otherwise if a developer creates their own method count which might do something different, it's going to be a false negative.
Also, I think the character case needs to be taken into account (no need to turn the method names to lower), as COUNT() and Count() are two different methods even if they are in the same class.

Copy link
Contributor

Choose a reason for hiding this comment

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

In case the intention is to avoid using the semantic model, at least a strict comparison with equals should create fewer FNs.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

well, I'd say that in general if we want to compare anything that is Count to a single digit, it should be fine

if (Foo.BarCount < 3) {}

why would the rule ask the dev to put 3 in a magic constant?

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 think the risk would be something like if (CountOfMonteChristo == 9), or something like this, but I'd say it's fairly low

And I dropped the idea of Order - should I actually add it?

Will people do something like if (Foo.Order < 3) - I guess I should?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

(offline discussion - the initial idea was to avoid noise when someone is comparing the size of a collection with single-digit number to access the first elements - so I reduced it to this scenario

we will still have FPs because this is a simple AST-based rule so we won't have dataflow and we don't plan to
we will still have FPs , in general, with this rule - this is why it's not (and probably never will be) part of SonarWay)

Copy link
Contributor

@mary-georgiou-sonarsource mary-georgiou-sonarsource left a comment

Choose a reason for hiding this comment

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

One comment regarding the AcceptedNamesForSingleDigitComparison.

@andrei-epure-sonarsource
Copy link
Contributor Author

Updated RSPEC (to be merged after this gets merged) SonarSource/rspec#694

<li> a variable/field declaration </li>
<li> the single argument of an attribute </li>
<li> a named argument for a method or attribute </li>
<li> a constructor call </li>
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 haven't included the single-digit comparison because it's hard to explain and isn't worth the effort TBH

// We allow single-digit comparisons when checking the size of a collection, which is usually done to access the first elements.
private static bool IsComparingCollectionSize(BinaryExpressionSyntax binaryComparisonToLiteral)
{
var comparedToLiteral = binaryComparisonToLiteral.Left is LiteralExpressionSyntax ? binaryComparisonToLiteral.Right : binaryComparisonToLiteral.Left;
Copy link
Contributor Author

Choose a reason for hiding this comment

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

add a test with number on left

@sonarqubecloud
Copy link

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

@sonarqubecloud
Copy link

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 1 Code Smell

98.0% 98.0% Coverage
0.0% 0.0% Duplication

Copy link
Contributor

@mary-georgiou-sonarsource mary-georgiou-sonarsource left a comment

Choose a reason for hiding this comment

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

LGTM

@mary-georgiou-sonarsource mary-georgiou-sonarsource added this to the 8.34 milestone Jan 12, 2022
@mary-georgiou-sonarsource mary-georgiou-sonarsource merged commit e594a9d into master Jan 12, 2022
@mary-georgiou-sonarsource mary-georgiou-sonarsource deleted the andrei/4737 branch January 12, 2022 15:24
@andrei-epure-sonarsource andrei-epure-sonarsource removed this from the 8.34 milestone Jan 12, 2022
@andrei-epure-sonarsource andrei-epure-sonarsource changed the title S109 - reduce false positives for named arguments, attribute usage, "From...()" methods and single digit comparisons for well-known properties Fix S109 FP: named arguments, constructor calls, single-value attributes Jan 12, 2022
@andrei-epure-sonarsource
Copy link
Contributor Author

Validation: for some projects it didn't reduce the noise, for others it significantly did. For example:

  • dnSpy went from 5,3K to 3,9K S109 issues (26% less)
  • Microsoft Automatic Graph Layout from 3K to 2.1K (30% less)
  • cloudscribe from 1,4K to 770 (~50% less)

Validation done.

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.

Fix S109 FP: named arguments, constructor calls, single-value attributes
2 participants