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

[Analyzer proposal]: Simplify calls to string.Substring and Memory/Span.Slice #68946

Closed
Tracked by #79053
GrabYourPitchforks opened this issue May 6, 2022 · 10 comments · Fixed by dotnet/roslyn-analyzers#6814
Assignees
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime code-analyzer Marks an issue that suggests a Roslyn analyzer code-fixer Marks an issue that suggests a Roslyn code fixer
Milestone

Comments

@GrabYourPitchforks
Copy link
Member

Inspired by Steve's comment at #68937 (comment).

We should consider promoting usage of Substring/Slice(offset) over Substring/Slice(offset, length) for "slice to the end of the buffer" scenarios. In both cases it makes the code a little easier to read and is less error-prone since it doesn't require the caller to get the length check correct. And for Slice specifically, it will result in slightly better codegen.

// Detect these patterns
someString.Substring(expression, someString.Length - expression);
someMemory.Slice(expression, someMemory.Length - expression);
someSpan.Slice(expression, someSpan.Length - expression);

// And replace them with these:
someString.Substring(expression);
someMemory.Slice(expression);
someSpan.Slice(expression);

Any analyzer / fixer would need to be a little smart and ensure that evaluating neither this nor expression has side effects, otherwise changing the number of occurrences from 2 to 1 would result in an observable behavioral change. This means that we might not be able to trigger the analyzer / fixer if this or expression contains a property accessor, unless we can reason that the property accessor is a dumb field wrapper.

The prevalent patterns that I saw in #68937 were:

value.Substring(local, value.Length - local);
value.Substring(local1 + local2, value.Length - local1 - local2);
value.Substring(local1 + local2, value.Length - (local1 + local2));
value.Substring(field, value.Length - field);
value.Substring(field + const, value.Length - field - const);
value.Substring(field + const, value.Length - (field + const));

Suggested category: Maintainability
Suggested severity: Info

@GrabYourPitchforks GrabYourPitchforks added area-System.Runtime code-analyzer Marks an issue that suggests a Roslyn analyzer code-fixer Marks an issue that suggests a Roslyn code fixer labels May 6, 2022
@ghost ghost added the untriaged New issue has not been triaged by the area owner label May 6, 2022
@ghost
Copy link

ghost commented May 6, 2022

Tagging subscribers to this area: @dotnet/area-system-runtime
See info in area-owners.md if you want to be subscribed.

Issue Details

Inspired by Steve's comment at #68937 (comment).

We should consider promoting usage of Substring/Slice(offset) over Substring/Slice(offset, length) for "slice to the end of the buffer" scenarios. In both cases it makes the code a little easier to read and is less error-prone since it doesn't require the caller to get the length check correct. And for Slice specifically, it will result in slightly better codegen.

// Detect these patterns
someString.Substring(expression, someString.Length - expression);
someMemory.Slice(expression, someMemory.Length - expression);
someSpan.Slice(expression, someSpan.Length - expression);

// And replace them with these:
someString.Substring(expression);
someMemory.Slice(expression);
someSpan.Slice(expression);

Any analyzer / fixer would need to be a little smart and ensure that evaluating neither this nor expression has side effects, otherwise changing the number of occurrences from 2 to 1 would result in an observable behavioral change. This means that we might not be able to trigger the analyzer / fixer if this or expression contains a property accessor, unless we can reason that the property accessor is a dumb field wrapper.

The prevalent patterns that I saw in #68937 were:

value.Substring(local, value.Length - local);
value.Substring(local1 + local2, value.Length - local1 - local2);
value.Substring(local1 + local2, value.Length - (local1 + local2));
value.Substring(field, value.Length - field);
value.Substring(field + const, value.Length - field - const);
value.Substring(field + const, value.Length - (field + const));

Suggested category: Maintainability
Suggested severity: Info

Author: GrabYourPitchforks
Assignees: -
Labels:

area-System.Runtime, code-analyzer, code-fixer

Milestone: -

@teo-tsirpanis teo-tsirpanis added the api-suggestion Early API idea and discussion, it is NOT ready for implementation label May 6, 2022
@carlossanlop
Copy link
Member

@GrabYourPitchforks your proposal looks ready for review, especially since you already found a bunch of cases in #68937 .

@carlossanlop carlossanlop added api-ready-for-review API is ready for review, it is NOT ready for implementation and removed api-suggestion Early API idea and discussion, it is NOT ready for implementation untriaged New issue has not been triaged by the area owner labels May 12, 2022
@carlossanlop carlossanlop added this to the 7.0.0 milestone May 12, 2022
@terrajobst
Copy link
Member

terrajobst commented Jun 23, 2022

Video

  • Looks good as proposed

Category: Maintainability
Severity: Info

@terrajobst terrajobst added api-approved API was approved in API review, it can be implemented and removed api-ready-for-review API is ready for review, it is NOT ready for implementation labels Jun 23, 2022
@carlossanlop carlossanlop modified the milestones: 7.0.0, 8.0.0 Jul 6, 2022
@buyaa-n buyaa-n added the help wanted [up-for-grabs] Good issue for external contributors label Nov 15, 2022
@buyaa-n
Copy link
Contributor

buyaa-n commented Nov 15, 2022

Estimates:

Analyzer: Small
Fixer: Small

@TonyValenti
Copy link

Instead of using Substring, would it be better to use the slice syntax?

Ie. String[x..] ?

@dstarosta
Copy link

I wish it would also report a missing check for length when the optimization is not applicable. That is one of the biggest sources of bugs I have seen with .NET in my experience.

@cybertyche
Copy link

Instead of using Substring, would it be better to use the slice syntax?

Ie. String[x..] ?

Given that there is already another analyzer that does that particular recommendation (move from string.Substring(foo) to string[foo..]) it does seem prudent to go directly to the slice syntax rather than create a syntax that another analyzer is just going to flag.

@cybertyche
Copy link

On the other hand, the rule that suggests the slice syntax as a simplification of substring is an IDE not a CA warning. It might therefore be good to do it in two parts, one that removes the second parameter (CA) and one that then suggests moving to the slice syntax (IDE).

@tannergooding tannergooding modified the milestones: 8.0.0, Future Jul 24, 2023
@mpidash
Copy link
Contributor

mpidash commented Jul 25, 2023

I would like to work on this analyzer if that is ok.

@carlossanlop
Copy link
Member

@mpidash thank you for offering your help! I'm assigning the issue to you.

If you have any questions, feel free to ask @mavasani, @Youssef1313, @buyaa-n or I for help.

@buyaa-n buyaa-n removed the help wanted [up-for-grabs] Good issue for external contributors label Sep 21, 2023
@ghost ghost locked as resolved and limited conversation to collaborators Oct 23, 2023
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
api-approved API was approved in API review, it can be implemented area-System.Runtime code-analyzer Marks an issue that suggests a Roslyn analyzer code-fixer Marks an issue that suggests a Roslyn code fixer
Projects
None yet
Development

Successfully merging a pull request may close this issue.

10 participants