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

Support duck-typed awaitables and task-like types for Task/Async-related analyzers #1535

Merged
merged 18 commits into from
Sep 30, 2024

Conversation

Govorunb
Copy link
Contributor

Description

These changes add the same logic for checking duck-typed awaitables and task-like types that is currently in Roslyn.

This resolves #1529 - specifically, these analyzers/refactorings become aware of custom awaitables/custom task-like types:

  • RCS1046/RCS1047 (async/sync method name should/should not end in Async)
  • RCS1090 (use/remove ConfigureAwait(false))
  • RCS1229/RCS1174 (use/remove async/await)
  • RCS1261 (dispose asynchronously)
  • RR0209 (remove async/await)

Remarks

RCS1090's behaviour is less obvious here - it seems there is no official stance for duck-typing ConfigureAwait (even Roslyn isn't perfectly consistent), but I'm of the opinion that if the rest of the ducks are quacking, it's better to join the flock 😄 The result is that these checks are relaxed from the Task-specific ConfiguredTaskAwaitable(`1) return type to any awaitable return type.

I noticed there were some checks for WinRT async interfaces, these are covered as there's an extension GetAwaiter() method available on those types.

I'm not experienced with analyzers and their edge cases so it's possible I've missed writing some obvious tests, I'd love to get your feedback.

Add tests for RCS1229 covering duck-typed awaitables
Fix some RCS1229 tests being grouped under RCS1228
Custom task type can compile to a full state machine without being awaitable
Add more to RCS1229 tests
Add tests to RCS1261 since it uses the same fixer code as RCS1229
Better match the real check performed by the compiler (check member visibility, check for implementing INotifyCompletion instead of just the OnCompleted method)
@Govorunb
Copy link
Contributor Author

@dotnet-policy-service agree

@josefpihrt
Copy link
Collaborator

@Govorunb build failed

src/Core/SymbolUtility.cs Show resolved Hide resolved
src/Analyzers/CSharp/Analysis/UseAsyncAwaitAnalyzer.cs Outdated Show resolved Hide resolved
src/Core/SymbolUtility.cs Outdated Show resolved Hide resolved
src/Core/SymbolUtility.cs Outdated Show resolved Hide resolved
src/Core/SymbolUtility.cs Show resolved Hide resolved
@josefpihrt
Copy link
Collaborator

@Govorunb Please update changelog.

Shortcut awaitable check for Task/ValueTask
Improve documentation clarity
Types derived from Task(<T>) aren't special-cased and thus aren't inherently task-like
Likewise with awaitability, a derived type could declare a `new GetAwaiter` method (like Task<T> does) that actually doesn't return a valid awaiter type, so inheritance cannot be used to prove a type is awaitable
src/Core/SymbolUtility.cs Outdated Show resolved Hide resolved
src/Core/SymbolUtility.cs Show resolved Hide resolved
Add null checks
Inline "task-like" check
src/Core/SymbolUtility.cs Outdated Show resolved Hide resolved
src/Core/SymbolUtility.cs Outdated Show resolved Hide resolved
@josefpihrt josefpihrt merged commit 7be911c into dotnet:main Sep 30, 2024
17 checks passed
@josefpihrt
Copy link
Collaborator

@Govorunb Great PR! Thanks for the contribution.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
2 participants