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

Add analyzer/codefix for usage of interpolated strings in raw query methods #30835

Merged
merged 23 commits into from
May 24, 2023
Merged

Add analyzer/codefix for usage of interpolated strings in raw query methods #30835

merged 23 commits into from
May 24, 2023

Conversation

DoctorKrolic
Copy link
Contributor

@DoctorKrolic DoctorKrolic commented May 6, 2023

Closes #30965

  • Added an analyzer, that produces a warning when using interpolations in FromSqlRaw, ExecuteSqlRaw and ExecuteSqlRawAsync methods
  • Added corresponding code fix provider (and all necessary changes for it), that enables quick-fixing most reported cases
  • Added EFCore.Analyzers.Deployment project, that represents a VS extension, that references analyzers project. This enables VS users to not only verify analyzers/code fixes in unit tests, but also in a VS instance as well. I am aware, that most (if not the whole) EF Team members use Rider, but I don't think this is gonna be an issue. If you accept this change, I will need infra help since this project should not be built in CI! This thing randomly stopped working for me, so reverted the change

@DoctorKrolic DoctorKrolic changed the title Interpolated strings in raw queries analyzer codefix Interpolated strings in raw queries analyzer May 6, 2023
@DoctorKrolic DoctorKrolic marked this pull request as draft May 6, 2023 15:37
@DoctorKrolic DoctorKrolic changed the title Interpolated strings in raw queries analyzer Add analyzer/codefix for usage of interpolated strings in raw query methods May 6, 2023
@DoctorKrolic DoctorKrolic marked this pull request as ready for review May 6, 2023 16:30
@roji
Copy link
Member

roji commented May 9, 2023

Thanks for the quality work on this @DoctorKrolic!

Before doing any extra work, let me confirm with the team that we want to go ahead with this. There are cases where string interpolation with the Raw functions is OK, even required (e.g. interpolating a column/table name, which cannot be parameterized in SQL), so this would generate false positive warnings that would need to be suppressed. I still think this makes sense, but I'd like to make sure that everyone else does too.

A couple quick notes: in EF 7 we introduced FromSql, which is a synonym for FromSqlInterpolated but without the long name. We did this to steer users towards using the safer, FormattableString variant by default - so the code fix should correct to that.

Also, EF 7.0 introduced SqlQuery/SqlQueryRaw for querying scalars - we should do the same analysis and code fix for that too.

(but again, better to wait for confirmation before spending more time on this)

@DoctorKrolic
Copy link
Contributor Author

There are cases where string interpolation with the Raw functions is OK, even required (e.g. interpolating a column/table name, which cannot be parameterized in SQL)

I already excluded constant interpolation from reported cases. We can add specific terms for other things, like nameof in order to provide better experience as well

A couple quick notes: in EF 7 we introduced FromSql, which is a synonym for FromSqlInterpolated but without the long name. We did this to steer users towards using the safer, FormattableString variant by default - so the code fix should correct to that.

Several lines fix. Also smells like a good refactoring opportunity to me)

@roji
Copy link
Member

roji commented May 9, 2023

I already excluded constant interpolation from reported cases. We can add specific terms for other things, like nameof in order to provide better experience as well

Makes sense, and exempting nameof definitely sounds right. But the problem at the end of the day is that there are valid cases for interpolation of non-constants, e.g. when the table name is passed as some method parameter, or even read from a UI (and then properly sanitized!). Though again, I don't believe that should prevent us from warning.

@DoctorKrolic
Copy link
Contributor Author

@roji A week has passed. Any updates?

@roji
Copy link
Member

roji commented May 16, 2023

@DoctorKrolic sorry for the delay - I am currently abroad and so we haven't yet had a design discussion on this. It's definitely on my list and we should have an answer by the end of the week.

@DoctorKrolic
Copy link
Contributor Author

@roji Was there a design discussion about this change?

@roji
Copy link
Member

roji commented May 19, 2023

@DoctorKrolic yes - we just had a discussion on this in our design meeting, and there's consensus in the team that this is a good idea. We raised the possibility of reporting a similar warning for string cancatenation, but decided to defer that for now.

So please feel free to continue working on this based on my comments above (please also rebase and make the build pass). I'll also try to give this a proper review in the coming days.

@DoctorKrolic
Copy link
Contributor Author

@roji Adressed your previous feedback, this is ready for a review pass. Also don't forget about better message suggestions if there are any, thanks!

Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Thanks @DoctorKrolic, this looks really good (and has good test coverage too).

src/EFCore.Analyzers/AnalyzerReleases.Shipped.md Outdated Show resolved Hide resolved
Debug.Assert(targetMethod.Name == "FromSqlRaw");

// Correct `FromSqlRaw` is an extension method, therefore it must be static
if (!targetMethod.IsStatic)
Copy link
Member

Choose a reason for hiding this comment

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

Rather than all the verification steps below, why not just extract the method symbol from the DbSet type symbol (and cache it), and then just compare the invocation's target method against that? This should simplify the code considerably.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, it simpliffies things a lot, but I am not sure about the caching. I believe it is incorrect to hold IMethodSymbol and then compare it to another IMethodSymbol, that come from different Compilation object. LMK what kind of caching did you mean

src/EFCore.Analyzers/Properties/AnalyzerStrings.resx Outdated Show resolved Hide resolved
src/EFCore.Analyzers/Properties/AnalyzerStrings.resx Outdated Show resolved Hide resolved
src/EFCore.Analyzers/Properties/AnalyzerStrings.resx Outdated Show resolved Hide resolved
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Thanks @DoctorKrolic, this looks really good (and has good test coverage too).

@roji
Copy link
Member

roji commented May 24, 2023

FYI I've opened #30965 to have an issue tracking this - you can reference it from the commit and the PR instead of #22086.

DoctorKrolic and others added 4 commits May 24, 2023 17:28
Co-authored-by: Shay Rojansky <roji@roji.org>
Co-authored-by: Shay Rojansky <roji@roji.org>
Co-authored-by: Shay Rojansky <roji@roji.org>
@DoctorKrolic DoctorKrolic requested a review from roji May 24, 2023 17:20
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Just a few remaining nits.

@DoctorKrolic DoctorKrolic requested a review from roji May 24, 2023 18:25
Copy link
Member

@roji roji left a comment

Choose a reason for hiding this comment

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

Thanks for quality work and for the quick turnaround @DoctorKrolic! Looking forward to seeing more work from you!

@roji
Copy link
Member

roji commented May 24, 2023

/azp run

@azure-pipelines
Copy link

Azure Pipelines successfully started running 1 pipeline(s).

@roji roji merged commit 3df1899 into dotnet:main May 24, 2023
@DoctorKrolic DoctorKrolic deleted the interpolated-strings-in-raw-queries-analyzer-codefix branch May 25, 2023 04:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Analyzer: warn (and code fix) for use of interpolation in SQL methods accepting raw strings
3 participants