From 183e5deef31e35ffcb934c87df8295086f4b8510 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 20 Sep 2024 17:20:47 -0600 Subject: [PATCH] Raise VSTHRD002 on improper sync-blocking of configured awaiters Closes #1354 --- .../CommonInterest.cs | 2 + .../VSTHRD002UseJtfRunAnalyzerTests.cs | 56 +++++++++++++++++++ 2 files changed, 58 insertions(+) diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs index 5a82d0b0a..436bed69e 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs @@ -37,8 +37,10 @@ internal static class CommonInterest new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(Task)), nameof(Task.Wait)), null), new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(Task)), nameof(Task.WaitAll)), null), new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(Task)), nameof(Task.WaitAny)), null), + new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter)), nameof(ConfiguredTaskAwaitable.ConfiguredTaskAwaiter.GetResult)), null), new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(TaskAwaiter)), nameof(TaskAwaiter.GetResult)), null), new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(ValueTaskAwaiter)), nameof(ValueTaskAwaiter.GetResult)), null), + new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter)), nameof(ConfiguredValueTaskAwaitable.ConfiguredValueTaskAwaiter.GetResult)), null), }; internal static readonly IEnumerable SyncBlockingMethods = JTFSyncBlockers.Concat(ProblematicSyncBlockingMethods).Concat(new[] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs index d57285e35..eaaafbdf3 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs @@ -538,6 +538,34 @@ async Task FAsync() { await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } + [Fact] + public async Task ConfiguredTask_GetAwaiter_GetResult_ShouldReportWarning() + { + var test = @" +using System; +using System.Threading.Tasks; + +class Test { + void F() { + var task = Task.Run(() => 1); + task.ConfigureAwait(false).GetAwaiter().[|GetResult|](); + } +} +"; + var withFix = @" +using System; +using System.Threading.Tasks; + +class Test { + async Task FAsync() { + var task = Task.Run(() => 1); + await task.ConfigureAwait(false); + } +} +"; + await CSVerify.VerifyCodeFixAsync(test, withFix); + } + [Fact] public async Task ValueTask_GetAwaiter_GetResult_ShouldReportWarning() { @@ -567,6 +595,34 @@ async Task FAsync() { await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } + [Fact] + public async Task ConfiguredValueTask_GetAwaiter_GetResult_ShouldReportWarning() + { + var test = @" +using System; +using System.Threading.Tasks; + +class Test { + void F() { + ValueTask task = default; + task.ConfigureAwait(false).GetAwaiter().[|GetResult|](); + } +} +"; + var withFix = @" +using System; +using System.Threading.Tasks; + +class Test { + async Task FAsync() { + ValueTask task = default; + await task.ConfigureAwait(false); + } +} +"; + await CSVerify.VerifyCodeFixAsync(test, withFix); + } + [Fact] public async Task TaskResult_FixUpdatesCallers() {