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

Use cancellation token throw if cancellation requested #4864

Conversation

NewellClark
Copy link
Contributor

Fix #33809

@NewellClark NewellClark requested a review from a team as a code owner February 17, 2021 19:36
@NewellClark NewellClark changed the base branch from master to release/6.0.1xx-preview2 February 17, 2021 19:37
@codecov
Copy link

codecov bot commented Feb 17, 2021

Codecov Report

Merging #4864 (f09b43e) into release/6.0.1xx (4bda814) will increase coverage by 0.00%.
The diff coverage is 96.09%.

@@                Coverage Diff                @@
##           release/6.0.1xx    #4864    +/-   ##
=================================================
  Coverage            95.57%   95.58%            
=================================================
  Files                 1212     1215     +3     
  Lines               277225   277840   +615     
  Branches             16737    16759    +22     
=================================================
+ Hits                264971   265564   +593     
- Misses               10020    10033    +13     
- Partials              2234     2243     +9     

@@ -1510,4 +1510,14 @@
<value>and all other platforms</value>
<comment>This call site is reachable on: 'windows' 10.0.2000 and later, and all other platforms</comment>
</data>
<data name="UseCancellationTokenThrowIfCancellationRequestedDescription" xml:space="preserve">
<value>'{0}' automatically checks whether the token has been canceled, and throws an '{2}' if it has.</value>
Copy link
Member

@Youssef1313 Youssef1313 Feb 17, 2021

Choose a reason for hiding this comment

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

Title and description doesn't use the format arguments as far as I know. They are for "Message" only.

@Evangelink Do you think it's worth extending DiagnosticDescriptorCreation analyzer for this?

Suggested change
<value>'{0}' automatically checks whether the token has been canceled, and throws an '{2}' if it has.</value>
<value>'ThrowIfCancellationRequested ' automatically checks whether the token has been canceled, and throws an 'OperationCanceledException' if it has.</value>

Copy link
Member

Choose a reason for hiding this comment

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

Hum that's a good question, I haven't really made the test. It's probably better to hardcode that call ToMinimalDisplayString when possible.

Regarding the improvement of the analyzer, I would personally rather go for a separate analyzer as it is something that would be useful for other situations.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

Comment on lines 1517 to 1518
<value>Use '{0}' instead of checking '{1}'</value>
<comment>0=ThrowIfCancellationRequested method, 1=IsCancellationRequested property, 2=OperationCanceledException type</comment>
Copy link
Member

@Youssef1313 Youssef1313 Feb 17, 2021

Choose a reason for hiding this comment

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

Because these are already known, I don't think there is a value in passing them as format arguments.

Suggested change
<value>Use '{0}' instead of checking '{1}'</value>
<comment>0=ThrowIfCancellationRequested method, 1=IsCancellationRequested property, 2=OperationCanceledException type</comment>
<value>Use 'ThrowIfCancellationRequested' instead of checking 'IsCancellationRequested'</value>

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Fixed.

@@ -1510,4 +1510,14 @@
<value>and all other platforms</value>
<comment>This call site is reachable on: 'windows' 10.0.2000 and later, and all other platforms</comment>
</data>
<data name="UseCancellationTokenThrowIfCancellationRequestedDescription" xml:space="preserve">
<value>'{0}' automatically checks whether the token has been canceled, and throws an '{2}' if it has.</value>
Copy link
Member

Choose a reason for hiding this comment

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

Hum that's a good question, I haven't really made the test. It's probably better to hardcode that call ToMinimalDisplayString when possible.

Regarding the improvement of the analyzer, I would personally rather go for a separate analyzer as it is something that would be useful for other situations.

int position = conditional.Syntax.SpanStart;
Diagnostic diagnostic = conditional.CreateDiagnostic(
Rule,
symbols.ThrowIfCancellationRequestedMethod.ToMinimalDisplayString(model, position, SymbolDisplayFormat.MinimallyQualifiedFormat),
Copy link
Member

Choose a reason for hiding this comment

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

@mavasani I don't remember if you said we should avoid these calls or not

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'll add a commit with the suggested changes tomorrow.

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've inlined the calls. Also removed calls to ToMinimalDisplayString as arguments are no longer used in the messages.

}

var codeAction = CodeAction.Create(
Resx.UseCancellationTokenThrowIfCancellationRequestedTitle,
Copy link
Member

Choose a reason for hiding this comment

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

@mavasani The title makes sense as code-fix title in this case, would you prefer to have a separate entry for it anyway (with the same content).

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've added a separate resource for the code fix title to be consistent.

Copy link
Contributor

@buyaa-n buyaa-n left a comment

Choose a reason for hiding this comment

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

Overall looks great, thanks @NewellClark, left few questions. Just curious did you tested it with runtime repo?

NewellClark and others added 3 commits February 27, 2021 10:29
Changes to code will be applied separately.

Co-authored-by: Buyaa Namnan <buyankhishig.namnan@microsoft.com>
@buyaa-n
Copy link
Contributor

buyaa-n commented Mar 9, 2021

Thanks @NewellClark for addressing comments, somehow the analyzer not working after adding it in VS SDK analyzers folder, did you tried that? I can see from VS the analyzer added within the SDK analyzers, I did changed the severity to warning but still no warning, I see similar unit tests passed but no warning in VS, do you have any idea? cc @mavasani

@sharwell
Copy link
Member

sharwell commented Apr 8, 2021

somehow the analyzer not working after adding it in VS SDK analyzers folder

I would not expect this to work without other changes. Can you describe the complete set of steps you followed?

@buyaa-n
Copy link
Contributor

buyaa-n commented Apr 8, 2021

I would not expect this to work without other changes.

That was what i was expecting

Can you describe the complete set of steps you followed?

Just normal steps i do whenever i need to test analyzer changes manually, build with a version my repo using and replace the build result with the nugget package/sdk analyzers with the new build, upgrade the rule level to warning, add a code that should warn, no warning. The steps worked for all i have ever tried, IDK what is wrong here

whenTrueUnwrapped is IThrowOperation @throw &&
@throw.Exception is IObjectCreationOperation objectCreation &&
IsDefaultOrTokenOperationCanceledExceptionCtor(objectCreation.Constructor) &&
conditional.WhenFalse is null)
Copy link
Contributor

@mavasani mavasani Apr 14, 2021

Choose a reason for hiding this comment

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

Why this restriction? Even if there is an else block, I believe the code can still be written as cancellationToken.ThrowIfCancellationRequested(); followed by the body of the else/WhenFalse block.

Copy link
Contributor Author

@NewellClark NewellClark May 10, 2021

Choose a reason for hiding this comment

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

I was implementing the analyzer as specified here, which specified two cases that should be detected and fixed:

  1. A simple affirmative check with no else clause, or
  2. A negated check with an else clause.

I'll remove the restriction. Edit: restriction has been removed.

{
var editor = await DocumentEditor.CreateAsync(context.Document, token).ConfigureAwait(false);
SyntaxNode expressionStatement = CreateThrowIfCancellationRequestedExpressionStatement(editor, conditional, propertyReference);
editor.ReplaceNode(conditional.Syntax, expressionStatement);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do we need to preserve the trivia, say:

if (token.IsCancellationRequested)
{
    // Comment to be preserved
    throw new OperationCanceledException();
}

Copy link
Contributor Author

@NewellClark NewellClark May 10, 2021

Choose a reason for hiding this comment

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

Good catch! Sorry I didn't see this earlier; for some reason I never received an email notification about this comment. I'll add some tests to ensure trivia is preserved.

@mavasani
Copy link
Contributor

Overall looks good to me. @NewellClark Can you please retarget the PRs to preview4 branch?

- Add tests ensuring trivia is preserved
- Ensure trivia is preserved
@NewellClark NewellClark changed the base branch from release/6.0.1xx-preview2 to release/6.0.1xx-preview4 May 13, 2021 16:37
/// Use <see cref="CancellationToken.ThrowIfCancellationRequested"/> instead of checking <see cref="CancellationToken.IsCancellationRequested"/> and
/// throwing <see cref="OperationCanceledException"/>.
/// </summary>
[ExportCodeFixProvider(LanguageNames.CSharp, LanguageNames.VisualBasic)]
Copy link
Member

Choose a reason for hiding this comment

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

@sharwell @mavasani Does this needs SharedAttribute? Isn't there an analyzer for missing shared attributes?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Youssef1313 I've gone ahead and added the Shared attribute.

Comment on lines 98 to 99
// Ensure if-blocks with multiple statements maintain correct indentation.
return await Formatter.FormatAsync(editor.GetChangedDocument(), Formatter.Annotation, cancellationToken: token).ConfigureAwait(false);
Copy link
Contributor

Choose a reason for hiding this comment

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

@sharwell Is this the recommend way to achieve this formatting? Normally, I see fixers just attaching the formatter annotation and not explicitly invoking the formatter API. @NewellClark Any reason that approach did not work?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@mavasani I did not realize that editor.GetChangedDocument() would automatically apply formatting. That's good to know. I've gone ahead and simplified it.

Copy link
Contributor

@mavasani mavasani left a comment

Choose a reason for hiding this comment

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

Overall looks great to me. As always, thanks for the extensive unit tests and comments in source code with examples, very much appreciated!

Please retarget the PR to release\6.0.1xx branch and address the remaining comments so it can be merged.

@NewellClark NewellClark changed the base branch from release/6.0.1xx-preview4 to release/6.0.1xx May 17, 2021 17:01
NewellClark and others added 4 commits May 17, 2021 13:02
Co-authored-by: Manish Vasani <mavasani@microsoft.com>
…ancellationTokenThrowIfCancellationRequested.cs

Co-authored-by: Manish Vasani <mavasani@microsoft.com>
@mavasani mavasani merged commit 92a247f into dotnet:release/6.0.1xx May 20, 2021
@NewellClark NewellClark mentioned this pull request May 21, 2021
@NewellClark NewellClark deleted the use-CancellationToken-ThrowIfCancellationRequested branch August 27, 2021 13:46
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.

Use CancellationToken.ThrowIfCancellationRequested
6 participants