From 0f0921d5f8481a21f029ca23e3ff84dca9c6f3f8 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Fri, 21 Oct 2022 07:27:43 -0600 Subject: [PATCH] Fix VSTHRD110 failure to handle unobserved tasks in finalizers Fixes devdiv-1645072 --- .../CSharpUtils.cs | 6 +++++ ...0ObserveResultOfAsyncCallsAnalyzerTests.cs | 24 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs index fd8b66fb2..633aaa0d2 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs @@ -92,6 +92,12 @@ internal static ContainingFunctionData GetContainingFunction(CSharpSyntaxNode sy BlockSyntax block => o.WithBody(block), _ => throw new NotSupportedException(), }, + DestructorDeclarationSyntax d => (CSharpSyntaxNode newBody) => newBody switch + { + ArrowExpressionClauseSyntax expr => d.WithExpressionBody(expr), + BlockSyntax block => d.WithBody(block), + _ => throw new NotSupportedException(), + }, _ => throw new NotSupportedException(), }; return new ContainingFunctionData(method, method.Modifiers.Any(SyntaxKind.AsyncKeyword), method.ParameterList, method.Body, bodyReplacement); diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs index 224d392bc..e77c3baff 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs @@ -402,6 +402,30 @@ async Task Foo(Test? tester) await Verify.VerifyAnalyzerAsync(test); } + [Fact] + public async Task TaskInFinalizer() + { + string test = @" +using System; +using System.Threading.Tasks; + +public class Test : IAsyncDisposable +{ + ~Test() + { + Task.[|Run|](async () => await DisposeAsync().ConfigureAwait(false)); + } + + public async ValueTask DisposeAsync() + { + await Task.Delay(5000); + } +} +"; + + await Verify.VerifyAnalyzerAsync(test); + } + private DiagnosticResult CreateDiagnostic(int line, int column, int length) => Verify.Diagnostic().WithSpan(line, column, line, column + length); }