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 S3063: "StringBuilder" data should be used #6696

Merged
merged 41 commits into from Feb 14, 2023

Conversation

cristian-ambrosini-sonarsource
Copy link
Contributor

Fixes #6659

Copy link
Contributor

Choose a reason for hiding this comment

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

First round of comments.

Copy link
Contributor

Choose a reason for hiding this comment

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

Cool stuff, great test coverage, and a really nice find with the interpolation 👍

We need to find a better way to detect the reads but you can read more about this below.

Copy link
Contributor

Choose a reason for hiding this comment

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

I found a couple of things that could be improved but nothing is blocking the rule from being merged.

Feel free to prioritize and cut branches by creating tickets or leaving a comment. I'm on a hardening sprint with Tim next week and we can pick up from there.

Copy link
Contributor

Choose a reason for hiding this comment

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

Some cosmetic changes are left and there are some cases which need clarification.

{
InvocationExpressionSyntax invocation =>
(IsAccessInvocation(invocation.GetName()) && IsSameReference(model, symbol, invocation.Expression))
|| (IsSameReference(model, symbol, invocation.Expression) && model.GetOperation(invocation).Kind is OperationKindEx.PropertyReference),

Choose a reason for hiding this comment

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

The or part looks wrong to me. Can it be removed without breaking things?

If not make the "or" part it's own pattern matching branch (this reads better IMO).

Try to get rid of the model.GetOperation call if possible.

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 line is meant to support indexers:
Dim a = sb(0)

Unfortunately, I wasn't able to find any other way to detect a property reference in VB other than looking at the operation kind. In CS indexers are treated differently and I can register for them with ElementAccessExpressionSyntax, thus avoiding the check on the operation.

Choose a reason for hiding this comment

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

You are right about the syntax check: There is no way to detect whether the invocation is a method or an indexer. You can use IPropertySymbol.IsIndexer instead of IOperation though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

You are right! Nice find 👍

ElementAccessExpressionSyntax elementAccess => IsSameReference(model, symbol, elementAccess.Expression),
ArgumentSyntax argument => IsSameReference(model, symbol, argument.Expression),
MemberAccessExpressionSyntax memberAccess => IsAccessExpression(memberAccess.Name.GetName()) && IsSameReference(model, symbol, memberAccess.Expression),
EqualsValueClauseSyntax { Value: IdentifierNameSyntax identifier } => IsSameReference(model, symbol, identifier),

Choose a reason for hiding this comment

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

Educational: Can you give me an example for EqualsValueClauseSyntax (VB too), please?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sure!
Here for CS and here for VB.

Copy link
Contributor

Choose a reason for hiding this comment

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

I see. There is propably no problem with this but there other places the syntax is used (VB and CS):

  • EnumMemberDeclarationSyntax (Initilaizer)
  • PropertyDeclarationSyntax (Initilaizer)
  • ParameterSyntax (Default)

You better check for { Parent: VariableDeclaratorSyntax } or even better VariableDeclaratorSyntax { Initializer.Value: { .. } }

(The only way I'm aware of to check for something like this is to checkout Roslyn and use "FindAllReferences" on the SyntaxNode.)

@cristian-ambrosini-sonarsource
Copy link
Contributor Author

I will add coverage for the GetIdentifier method in the facade on a separate PR.

};

protected override bool DescendIntoChildren(SyntaxNode node) =>
!(node.IsAnyKind(SkipChildren) && node.IsKind(SyntaxKindEx.LocalFunctionStatement) && ((LocalFunctionStatementSyntaxWrapper)node).Modifiers.Any(SyntaxKind.StaticKeyword));

Choose a reason for hiding this comment

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

Can you increase the code coverage here?

Copy link
Contributor

Choose a reason for hiding this comment

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

LGTM. There is one fishy looking syntax kind. Also if you have time

  • Increase the coverage a bit so we can merge without admin approval
  • There seems to be no test for top-level statements

SyntaxKind.StructDeclaration,
SyntaxKind.EnumDeclaration,
SyntaxKind.InterfaceDeclaration,
SyntaxKind.UsingDirective,

Choose a reason for hiding this comment

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

Why is this?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In the case of top-level statements we are not going through the children of the using directives (see here).

  • The test for top-level statements is called UnusedStringBuilder_TopLevelStatements and it's a parameterized test.

@sonarcloud
Copy link

sonarcloud bot commented Feb 14, 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 14, 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

95.9% 95.9% Coverage
0.0% 0.0% Duplication

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 S3063: "StringBuilder" data should be used
3 participants