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

Enable NetAnalyzers reliability and globalization rules #22625

Merged
1 commit merged into from
Sep 22, 2020
Merged

Conversation

roji
Copy link
Member

@roji roji commented Sep 20, 2020

The .NET 5.0 SDK comes with its own new code analysis, which does some of what FxCop previously did. We opt into the new warnings by adding <AnalysisLevel> in the csproj, and then configuring rules via .editorconfig (the new way to manage code analysis rules).

This enables the reliability and globalization rules (see the docs. Commits are split by rule along with the corresponding fixes, we can discuss rule-by-rule etc.

  • Set AnalysisLevel and add editorconfig template
  • CA2000: Dispose objects before losing scope
  • CA2012: Use ValueTasks correctly
  • CA2008: Do not create tasks without passing a TaskScheduler
  • CA2016: Forward the 'CancellationToken' parameter to methods that take one
  • CA1310: Specify StringComparison for correctness
  • CA1309: Use ordinal stringcomparison
  • CA1304: Specify CultureInfo
  • Add other rules without code changes

Part of #18870 (but via the built-in analysis instead of FxCop)
Replaces #22591

@roji roji requested a review from a team September 20, 2020 18:08
_enumerator?.DisposeAsync();
_enumerator = null;

var enumerator = _enumerator;
Copy link
Member Author

Choose a reason for hiding this comment

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

Note that this method returns and user code continues potentially before _enumerator actually gets disposed. Depending on whether CosmosClientWrapper cares if we call ExecuteSqlQuery before the previous enumerator completed, this could be a potentially serious concurrency bug.

Copy link
Member Author

Choose a reason for hiding this comment

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

@@ -122,7 +122,7 @@ public override bool Equals(object obj)

private bool Equals(KeyAccessExpression keyAccessExpression)
=> base.Equals(keyAccessExpression)
&& string.Equals(Name, keyAccessExpression.Name)
&& Name == keyAccessExpression.Name
Copy link
Member Author

Choose a reason for hiding this comment

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

This technically doesn't solve a problem, but the string equality operator is defined to be the same as string.Equals, and the code analysis flags this.

Copy link
Member

Choose a reason for hiding this comment

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

What is the severity of this rule?

Copy link
Member Author

Choose a reason for hiding this comment

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

This comes from CA1309 (Use ordinal StringComparison), and is currently configured as error (we can of course change this).

Interestingly, configuring the rule as warning in .editorconfig doesn't make the build fail although WarningsAsErrors is on (I think the new rules are exempted via WarningsNotAsErrors...).


namespace System.Threading.Tasks
{
internal static class RelationalTaskExtensions
Copy link
Member Author

Choose a reason for hiding this comment

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

This was dead code. Note also that ContinueWith performs significantly worse than just doing the simple thing, async/await (but the situation may have been different in the past).

@@ -106,7 +106,9 @@ IEnumerator IEnumerable.GetEnumerator()
/// doing so can result in application failures when updating to a new Entity Framework Core release.
/// </summary>
public virtual IAsyncEnumerator<TResult> GetAsyncEnumerator(CancellationToken cancellationToken = default)
=> _queryProvider.ExecuteAsync<IAsyncEnumerable<TResult>>(Expression).GetAsyncEnumerator(cancellationToken);
=> _queryProvider
Copy link
Member Author

Choose a reason for hiding this comment

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

Potentially important missing cancellation token

Copy link
Member

Choose a reason for hiding this comment

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

Not actually important since ExecuteAsync which returns enumerable just compiles the expression and never execute it. The real execution uses the cancellation token from GetAsyncEnumerator. No functional impact.

Copy link
Member Author

Choose a reason for hiding this comment

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

OK.

In that case is it right for ExecuteAsync to be async and even accept a cancellation token?

Copy link
Member

Choose a reason for hiding this comment

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

If ExecuteAsync is called with non enumerable kind of return value then it is going to hit the database and that is where cancellation token will be used.

@@ -740,7 +740,7 @@ await using (var transaction = await beginTransaction(c, cancellationToken).Conf
return s.Result;
}, async (c, s, ct) => new ExecutionResult<TResult>(
s.CommitFailed && await s.VerifySucceeded(s.State, ct).ConfigureAwait(false),
s.Result));
s.Result), cancellationToken);
Copy link
Member Author

Choose a reason for hiding this comment

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

Potentially important missing cancellation token

Copy link
Member

Choose a reason for hiding this comment

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

This is only used when the operation failed and it wasn't in a transaction, so it would be a very corner case for cancellation

The following rules led to code changes:

- CA2000: Dispose objects before losing scope
- CA2012: Use ValueTasks correctly
- CA2008: Do not create tasks without passing a TaskScheduler
- CA2016: Forward the 'CancellationToken' parameter to methods that take one
- CA1310: Specify StringComparison for correctness
- CA1309: Use ordinal stringcomparison
- CA1304: Specify CultureInfo

Part of #18870
@ghost
Copy link

ghost commented Sep 22, 2020

Hello @roji!

Because this pull request has the auto-merge label, I will be glad to assist with helping to merge this pull request once all check-in policies pass.

p.s. you can customize the way I help with merging this pull request, such as holding this pull request until a specific person approves. Simply @mention me (@msftbot) and give me an instruction to get started! Learn more here.

roji added a commit that referenced this pull request Sep 22, 2020
@ghost ghost merged commit a0a053b into main Sep 22, 2020
@ghost ghost deleted the Netanalyzers branch September 22, 2020 06:36
bricelam added a commit to bricelam/efcore that referenced this pull request Mar 8, 2021
An update to dispose all the things in PR dotnet#22625 accidentally broke our argument parsing logic. This updates that change to preserve the original logic.

Fixes dotnet#24251
bricelam added a commit to bricelam/efcore that referenced this pull request Mar 8, 2021
An update to dispose all the things in PR dotnet#22625 accidentally broke our argument parsing logic. This updates that change to preserve the original logic.

Fixes dotnet#24251
bricelam added a commit to bricelam/efcore that referenced this pull request Mar 9, 2021
An update to dispose all the things in PR dotnet#22625 accidentally broke our argument parsing logic. This updates that change to preserve the original logic.

Fixes dotnet#24251
This pull request was closed.
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.

3 participants