From 0b8cf61a60db529de3d5de5f3bdb7ea964b6bc4b Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 7 Dec 2022 11:02:22 -0700 Subject: [PATCH 1/2] Remove namespace from analyzer tests --- .../Helpers/CSharpCodeFixVerifier`2+Test.cs | 5 ----- .../Helpers/CSharpCodeFixVerifier`2.cs | 3 --- .../Helpers/ReferencesHelper.cs | 1 - .../VisualBasicCodeFixVerifier`2+Test.cs | 3 --- .../Helpers/VisualBasicCodeFixVerifier`2.cs | 3 --- .../MultiAnalyzerTests.cs | 9 ++------- .../Usings.cs | 9 +++++++++ ...UseSwitchToMainThreadAsyncAnalyzerTests.cs | 4 ---- .../VSTHRD002UseJtfRunAnalyzerTests.cs | 6 ------ .../VSTHRD003UseJtfRunAsyncAnalyzerTests.cs | 9 --------- ...aitSwitchToMainThreadAsyncAnalyzerTests.cs | 5 ----- .../VSTHRD010MainThreadUsageAnalyzerTests.cs | 5 ----- .../VSTHRD011UseAsyncLazyAnalyzerTests.cs | 6 ------ .../VSTHRD012SpecifyJtfWhereAllowedTests.cs | 5 ----- .../VSTHRD100AsyncVoidMethodAnalyzerTests.cs | 16 ++++++---------- .../VSTHRD100AsyncVoidMethodCodeFixTests.cs | 8 ++------ .../VSTHRD101AsyncVoidLambdaAnalyzerTests.cs | 5 ----- ...idJtfRunInNonPublicMembersAnalyzerTests.cs | 19 +++++++------------ .../VSTHRD103UseAsyncOptionAnalyzerTests.cs | 5 ----- .../VSTHRD104OfferAsyncOptionAnalyzerTests.cs | 8 ++------ ...plicitTaskSchedulerCurrentAnalyzerTests.cs | 5 ----- ...eInvokeAsyncForAsyncEventsAnalyzerTests.cs | 4 ---- ...tTaskWithinUsingExpressionAnalyzerTests.cs | 18 +++++++----------- ...rtThreadRequirementUnconditionallyTests.cs | 16 ++++++---------- ...9AvoidAssertInAsyncMethodsAnalyzerTests.cs | 4 ---- ...0ObserveResultOfAsyncCallsAnalyzerTests.cs | 5 ----- ...VSTHRD111UseConfigureAwaitAnalyzerTests.cs | 5 ----- ...mentSystemIAsyncDisposableAnalyzerTests.cs | 4 ---- ...kForSystemIAsyncDisposableAnalyzerTests.cs | 4 ---- ...D114AvoidReturningNullTaskAnalyzerTests.cs | 4 ---- ...RD114AvoidReturningNullTaskCodeFixTests.cs | 4 ---- ...00UseAsyncNamingConventionAnalyzerTests.cs | 6 ------ 32 files changed, 41 insertions(+), 172 deletions(-) create mode 100644 test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Usings.cs diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2+Test.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2+Test.cs index 219effcd1..ffb4daf5a 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2+Test.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2+Test.cs @@ -2,21 +2,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Immutable; using System.IO; using System.Linq; using System.Reflection; -using System.Runtime.CompilerServices; -using System.Threading.Tasks; #if WINDOWS using System.Windows.Threading; #endif -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CSharp; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; using Microsoft.CodeAnalysis.Text; -using Xunit; using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2.cs index 91cc3de5f..bd605653f 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/CSharpCodeFixVerifier`2.cs @@ -1,12 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.Testing; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/ReferencesHelper.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/ReferencesHelper.cs index 2943dfbbe..77095c232 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/ReferencesHelper.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/ReferencesHelper.cs @@ -3,7 +3,6 @@ using System.Collections.Immutable; using System.Net; -using Microsoft.CodeAnalysis.Testing; namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2+Test.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2+Test.cs index 976fe1c2a..fb0d49708 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2+Test.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2+Test.cs @@ -2,19 +2,16 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; -using System.Collections.Immutable; using System.IO; using System.Linq; using System.Reflection; #if WINDOWS using System.Windows.Threading; #endif -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Testing.Verifiers; using Microsoft.CodeAnalysis.Text; using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.CodeAnalysis.VisualBasic.Testing; -using Xunit; using IOleServiceProvider = Microsoft.VisualStudio.OLE.Interop.IServiceProvider; namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2.cs index 377473909..489890d2e 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Helpers/VisualBasicCodeFixVerifier`2.cs @@ -1,11 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Testing; using Microsoft.CodeAnalysis.Testing.Verifiers; using Microsoft.CodeAnalysis.VisualBasic.Testing; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/MultiAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/MultiAnalyzerTests.cs index 19438d321..b052dbc59 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/MultiAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/MultiAnalyzerTests.cs @@ -5,14 +5,9 @@ using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; -using Microsoft.CodeAnalysis.Testing; -using Xunit; -using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.MultiAnalyzerTests.Verifier; - -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; +using Microsoft.VisualStudio.Threading.Analyzers.Tests; +using CSVerify = MultiAnalyzerTests.Verifier; public class MultiAnalyzerTests { diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Usings.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Usings.cs new file mode 100644 index 000000000..d38229f3d --- /dev/null +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/Usings.cs @@ -0,0 +1,9 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +global using System.Threading.Tasks; +global using Microsoft; +global using Microsoft.CodeAnalysis; +global using Microsoft.CodeAnalysis.Testing; +global using Microsoft.VisualStudio.Threading.Analyzers; +global using Xunit; diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD001UseSwitchToMainThreadAsyncAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD001UseSwitchToMainThreadAsyncAnalyzerTests.cs index 0030faa58..c2387b687 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD001UseSwitchToMainThreadAsyncAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD001UseSwitchToMainThreadAsyncAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD001UseSwitchToMainThreadAsyncAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs index 173bbf1aa..d57285e35 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD002UseJtfRunAnalyzerTests.cs @@ -1,14 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD002UseJtfRunAnalyzerTests { /// diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD003UseJtfRunAsyncAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD003UseJtfRunAsyncAnalyzerTests.cs index 870a0bb7e..213a7441e 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD003UseJtfRunAsyncAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD003UseJtfRunAsyncAnalyzerTests.cs @@ -1,17 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Diagnostics.Tracing; -using System.Linq; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD003UseJtfRunAsyncAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD004AwaitSwitchToMainThreadAsyncAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD004AwaitSwitchToMainThreadAsyncAnalyzerTests.cs index 3120a34d4..1271292de 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD004AwaitSwitchToMainThreadAsyncAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD004AwaitSwitchToMainThreadAsyncAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD004AwaitSwitchToMainThreadAsyncAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs index 11048aea2..01c3a3a5c 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD010MainThreadUsageAnalyzerTests.cs @@ -1,14 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using static Microsoft.VisualStudio.Threading.Analyzers.VSTHRD010MainThreadUsageAnalyzer; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD010MainThreadUsageAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD011UseAsyncLazyAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD011UseAsyncLazyAnalyzerTests.cs index 19ae3b689..c58a2b281 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD011UseAsyncLazyAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD011UseAsyncLazyAnalyzerTests.cs @@ -1,14 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD011UseAsyncLazyAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD012SpecifyJtfWhereAllowedTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD012SpecifyJtfWhereAllowedTests.cs index ab361cc79..dce0000a1 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD012SpecifyJtfWhereAllowedTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD012SpecifyJtfWhereAllowedTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD012SpecifyJtfWhereAllowedTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodAnalyzerTests.cs index ef848194c..d84e0e61a 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD100AsyncVoidMethodAnalyzerTests { [Fact] @@ -20,7 +16,7 @@ async void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -38,7 +34,7 @@ async void F() {} } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 20); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 20); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -53,7 +49,7 @@ async void F(object sender, object e) { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -68,7 +64,7 @@ async void F(string sender, EventArgs e) { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -91,7 +87,7 @@ async System.Threading.Tasks.Task F(object sender, EventArgs e) { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -118,7 +114,7 @@ async System.Threading.Tasks.Task F(object sender, MyEventArgs e) { class MyEventArgs : EventArgs {} "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodCodeFixTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodCodeFixTests.cs index 071b8ed2f..0501ce8dc 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodCodeFixTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD100AsyncVoidMethodCodeFixTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD100AsyncVoidMethodCodeFixTests { [Fact] @@ -30,7 +26,7 @@ async System.Threading.Tasks.Task F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(5, 16); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -57,7 +53,7 @@ async Task F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(6, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(6, 16); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD101AsyncVoidLambdaAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD101AsyncVoidLambdaAnalyzerTests.cs index ebd2415f2..9ab1b841a 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD101AsyncVoidLambdaAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD101AsyncVoidLambdaAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD101AsyncVoidLambdaAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD102AvoidJtfRunInNonPublicMembersAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD102AvoidJtfRunInNonPublicMembersAnalyzerTests.cs index 91486115d..cbe31a6c0 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD102AvoidJtfRunInNonPublicMembersAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD102AvoidJtfRunInNonPublicMembersAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD102AvoidJtfRunInNonPublicMembersAnalyzerTests { [Fact] @@ -24,7 +19,7 @@ public void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -78,7 +73,7 @@ protected void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -113,7 +108,7 @@ internal void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -131,7 +126,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -178,7 +173,7 @@ void IFoo.F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(13, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(13, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -201,7 +196,7 @@ public void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(13, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(13, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -263,7 +258,7 @@ public Test() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(8, 13); await CSVerify.VerifyAnalyzerAsync(test, expected); } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD103UseAsyncOptionAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD103UseAsyncOptionAnalyzerTests.cs index b5221a695..f8f54deb3 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD103UseAsyncOptionAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD103UseAsyncOptionAnalyzerTests.cs @@ -1,14 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using static Microsoft.VisualStudio.Threading.Analyzers.VSTHRD103UseAsyncOptionAnalyzer; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD103UseAsyncOptionAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD104OfferAsyncOptionAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD104OfferAsyncOptionAnalyzerTests.cs index faa1f1660..8b0acc4eb 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD104OfferAsyncOptionAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD104OfferAsyncOptionAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD104OfferAsyncOptionAnalyzerTests { [Fact] @@ -27,7 +23,7 @@ public void Foo() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 13, 9, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 13, 9, 16); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -99,7 +95,7 @@ internal async Task FooAsync() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 13, 9, 16); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 13, 9, 16); await CSVerify.VerifyAnalyzerAsync(test, expected); } } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD105AvoidImplicitTaskSchedulerCurrentAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD105AvoidImplicitTaskSchedulerCurrentAnalyzerTests.cs index faa14decb..ffeae6a29 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD105AvoidImplicitTaskSchedulerCurrentAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD105AvoidImplicitTaskSchedulerCurrentAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD105AvoidImplicitTaskSchedulerCurrentAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD106UseInvokeAsyncForAsyncEventsAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD106UseInvokeAsyncForAsyncEventsAnalyzerTests.cs index 87ac9993e..a22af86b8 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD106UseInvokeAsyncForAsyncEventsAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD106UseInvokeAsyncForAsyncEventsAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD106UseInvokeAsyncForAsyncEventsAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD107AwaitTaskWithinUsingExpressionAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD107AwaitTaskWithinUsingExpressionAnalyzerTests.cs index 11966d8b3..2656c456b 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD107AwaitTaskWithinUsingExpressionAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD107AwaitTaskWithinUsingExpressionAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD107AwaitTaskWithinUsingExpressionAnalyzerTests { [Fact] @@ -39,7 +35,7 @@ async Task FAsync() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -77,7 +73,7 @@ async Task FAsync() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -113,7 +109,7 @@ async Task F() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -147,7 +143,7 @@ async Task F() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(8, 16, 8, 32); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -183,7 +179,7 @@ async Task F() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 24); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 24); await CSVerify.VerifyCodeFixAsync(test, expected, withFix); } @@ -225,7 +221,7 @@ async Task F() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 27); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 27); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -247,7 +243,7 @@ void F() { } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 19); + DiagnosticResult expected = CSVerify.Diagnostic().WithSpan(9, 16, 9, 19); await CSVerify.VerifyAnalyzerAsync(test, expected); } } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD108AssertThreadRequirementUnconditionallyTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD108AssertThreadRequirementUnconditionallyTests.cs index 758afb9d0..da099f90e 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD108AssertThreadRequirementUnconditionallyTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD108AssertThreadRequirementUnconditionallyTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD108AssertThreadRequirementUnconditionallyTests { [Fact] @@ -43,7 +39,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -89,7 +85,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -111,7 +107,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -133,7 +129,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -171,7 +167,7 @@ void F() { } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } @@ -195,7 +191,7 @@ private void ThrowIfNot(bool expr) } } "; - CodeAnalysis.Testing.DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); + DiagnosticResult expected = CSVerify.Diagnostic().WithLocation(0); await CSVerify.VerifyAnalyzerAsync(test, expected); } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD109AvoidAssertInAsyncMethodsAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD109AvoidAssertInAsyncMethodsAnalyzerTests.cs index af9ec2064..b9f2ea635 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD109AvoidAssertInAsyncMethodsAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD109AvoidAssertInAsyncMethodsAnalyzerTests.cs @@ -1,12 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD109AvoidAssertInAsyncMethodsAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs index d37158985..a2b2d4120 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD111UseConfigureAwaitAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD111UseConfigureAwaitAnalyzerTests.cs index ffcc93e75..4bac72047 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD111UseConfigureAwaitAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD111UseConfigureAwaitAnalyzerTests.cs @@ -1,13 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD111UseConfigureAwaitAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD112ImplementSystemIAsyncDisposableAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD112ImplementSystemIAsyncDisposableAnalyzerTests.cs index 2962a15a6..7e2ac40cf 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD112ImplementSystemIAsyncDisposableAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD112ImplementSystemIAsyncDisposableAnalyzerTests.cs @@ -1,13 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; using VBVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.VisualBasicCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD112ImplementSystemIAsyncDisposableAnalyzerTests { private const string Preamble = @" diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD113CheckForSystemIAsyncDisposableAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD113CheckForSystemIAsyncDisposableAnalyzerTests.cs index 65e921445..31ff51ed2 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD113CheckForSystemIAsyncDisposableAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD113CheckForSystemIAsyncDisposableAnalyzerTests.cs @@ -1,13 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; using VBVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.VisualBasicCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD113CheckForSystemIAsyncDisposableAnalyzerTests { private const string Preamble = @" diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskAnalyzerTests.cs index 649d66c38..63822876f 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskAnalyzerTests.cs @@ -1,13 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; using VerifyVB = Microsoft.VisualStudio.Threading.Analyzers.Tests.VisualBasicCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD114AvoidReturningNullTaskAnalyzerTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskCodeFixTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskCodeFixTests.cs index 2edb0cac5..0aba86b77 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskCodeFixTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD114AvoidReturningNullTaskCodeFixTests.cs @@ -1,13 +1,9 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; using VerifyVB = Microsoft.VisualStudio.Threading.Analyzers.Tests.VisualBasicCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD114AvoidReturningNullTaskCodeFixTests { [Fact] diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD200UseAsyncNamingConventionAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD200UseAsyncNamingConventionAnalyzerTests.cs index f7ea5d252..6033b321f 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD200UseAsyncNamingConventionAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD200UseAsyncNamingConventionAnalyzerTests.cs @@ -1,14 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.Testing; -using Xunit; using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; -namespace Microsoft.VisualStudio.Threading.Analyzers.Tests; - public class VSTHRD200UseAsyncNamingConventionAnalyzerTests { private static readonly DiagnosticDescriptor AddSuffixDescriptor = VSTHRD200UseAsyncNamingConventionAnalyzer.AddAsyncDescriptor; From c7ceed01d1c73d7d5f2f6c0dd427245b3c7c8d96 Mon Sep 17 00:00:00 2001 From: Andrew Arnott Date: Wed, 7 Dec 2022 16:58:57 -0700 Subject: [PATCH 2/2] Fix perf issue with VSTHRD110 This also converts the analyzer to an IOperation analyzer and makes it work for VB. Fix #971 --- .../CSharpUtils.cs | 13 + ...HRD110ObserveResultOfAsyncCallsAnalyzer.cs | 13 + ...HRD110ObserveResultOfAsyncCallsAnalyzer.cs | 63 - .../VisualBasicUtils.cs | 3 + ...HRD110ObserveResultOfAsyncCallsAnalyzer.cs | 13 + ...HRD110ObserveResultOfAsyncCallsAnalyzer.cs | 70 + .../CommonInterest.cs | 217 +++- .../DiagnosticAnalyzerState.cs | 131 -- .../LanguageUtils.cs | 2 + .../Strings.Designer.cs | 1138 ++++++++--------- .../Strings.resx | 2 +- ...THRD200UseAsyncNamingConventionAnalyzer.cs | 90 +- ...0ObserveResultOfAsyncCallsAnalyzerTests.cs | 90 +- 13 files changed, 1005 insertions(+), 840 deletions(-) create mode 100644 src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs delete mode 100644 src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs create mode 100644 src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs create mode 100644 src/Microsoft.VisualStudio.Threading.Analyzers/AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs delete mode 100644 src/Microsoft.VisualStudio.Threading.Analyzers/DiagnosticAnalyzerState.cs diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs index faf7549af..386927675 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpUtils.cs @@ -262,6 +262,19 @@ internal override bool MethodReturnsNullableReferenceType(IMethodSymbol methodSy return returnType is not null && returnType.IsKind(SyntaxKind.NullableType); } + internal override bool IsAsyncMethod(SyntaxNode syntaxNode) + { + SyntaxTokenList? modifiers = syntaxNode switch + { + MethodDeclarationSyntax methodDeclaration => methodDeclaration.Modifiers, + SimpleLambdaExpressionSyntax lambda => lambda.Modifiers, + AnonymousMethodExpressionSyntax anonMethod => anonMethod.Modifiers, + ParenthesizedLambdaExpressionSyntax lambda => lambda.Modifiers, + _ => null, + }; + return modifiers?.Any(SyntaxKind.AsyncKeyword) is true; + } + internal readonly struct ContainingFunctionData { internal ContainingFunctionData(CSharpSyntaxNode function, bool isAsync, ParameterListSyntax? parameterList, CSharpSyntaxNode? blockOrExpression, Func bodyReplacement) diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs new file mode 100644 index 000000000..4f64498fd --- /dev/null +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/CSharpVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.VisualStudio.Threading.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.CSharp)] +public sealed class CSharpVSTHRD110ObserveResultOfAsyncCallsAnalyzer : AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer +{ + private protected override LanguageUtils LanguageUtils => CSharpUtils.Instance; +} diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs deleted file mode 100644 index 63f205adc..000000000 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.CSharp/VSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs +++ /dev/null @@ -1,63 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System.Collections.Immutable; -using Microsoft.CodeAnalysis; -using Microsoft.CodeAnalysis.CSharp; -using Microsoft.CodeAnalysis.CSharp.Syntax; -using Microsoft.CodeAnalysis.Diagnostics; - -namespace Microsoft.VisualStudio.Threading.Analyzers; - -/// -/// Report errors when async methods calls are not awaited or the result used in some way within a synchronous method. -/// -[DiagnosticAnalyzer(LanguageNames.CSharp)] -public class VSTHRD110ObserveResultOfAsyncCallsAnalyzer : DiagnosticAnalyzer -{ - public const string Id = "VSTHRD110"; - - internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor( - id: Id, - title: new LocalizableResourceString(nameof(Strings.VSTHRD110_Title), Strings.ResourceManager, typeof(Strings)), - messageFormat: new LocalizableResourceString(nameof(Strings.VSTHRD110_MessageFormat), Strings.ResourceManager, typeof(Strings)), - helpLinkUri: Utils.GetHelpLink(Id), - category: "Usage", - defaultSeverity: DiagnosticSeverity.Warning, - isEnabledByDefault: true); - - /// - public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptor); - - /// - public override void Initialize(AnalysisContext context) - { - context.EnableConcurrentExecution(); - context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); - - context.RegisterSyntaxNodeAction(Utils.DebuggableWrapper(new PerCompilation().AnalyzeInvocation), SyntaxKind.InvocationExpression); - } - - private class PerCompilation : DiagnosticAnalyzerState - { - internal void AnalyzeInvocation(SyntaxNodeAnalysisContext context) - { - var invocation = (InvocationExpressionSyntax)context.Node; - - // Only consider invocations that are direct statements. Otherwise, we assume their - // result is awaited, assigned, or otherwise consumed. - if (invocation.Parent is ExpressionStatementSyntax || invocation.Parent is ConditionalAccessExpressionSyntax) - { - var methodSymbol = context.SemanticModel.GetSymbolInfo(context.Node).Symbol as IMethodSymbol; - if (this.IsAwaitableType(methodSymbol?.ReturnType, context.Compilation, context.CancellationToken)) - { - if (!CSharpUtils.GetContainingFunction(invocation).IsAsync) - { - Location? location = (CSharpUtils.IsolateMethodName(invocation) ?? invocation.Expression).GetLocation(); - context.ReportDiagnostic(Diagnostic.Create(Descriptor, location)); - } - } - } - } - } -} diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicUtils.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicUtils.cs index 71bdd2feb..dc2c2a787 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicUtils.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicUtils.cs @@ -5,6 +5,7 @@ using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Operations; +using Microsoft.CodeAnalysis.VisualBasic; using Microsoft.CodeAnalysis.VisualBasic.Syntax; namespace Microsoft.VisualStudio.Threading.Analyzers; @@ -93,4 +94,6 @@ internal override bool MethodReturnsNullableReferenceType(IMethodSymbol methodSy // VB.NET doesn't support nullable reference types return false; } + + internal override bool IsAsyncMethod(SyntaxNode syntaxNode) => syntaxNode is MethodBlockSyntax methodDeclaration && methodDeclaration.BlockStatement.Modifiers.Any(SyntaxKind.AsyncKeyword); } diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs new file mode 100644 index 000000000..3b6110b0f --- /dev/null +++ b/src/Microsoft.VisualStudio.Threading.Analyzers.VisualBasic/VisualBasicVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs @@ -0,0 +1,13 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; + +namespace Microsoft.VisualStudio.Threading.Analyzers; + +[DiagnosticAnalyzer(LanguageNames.VisualBasic)] +public sealed class VisualBasicVSTHRD110ObserveResultOfAsyncCallsAnalyzer : AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer +{ + private protected override LanguageUtils LanguageUtils => VisualBasicUtils.Instance; +} diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs new file mode 100644 index 000000000..720d7f525 --- /dev/null +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer.cs @@ -0,0 +1,70 @@ +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT license. See LICENSE file in the project root for full license information. + +using System.Collections.Generic; +using System.Collections.Immutable; +using Microsoft.CodeAnalysis; +using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; + +namespace Microsoft.VisualStudio.Threading.Analyzers; + +/// +/// Report errors when async methods calls are not awaited or the result used in some way within a synchronous method. +/// +public abstract class AbstractVSTHRD110ObserveResultOfAsyncCallsAnalyzer : DiagnosticAnalyzer +{ + public const string Id = "VSTHRD110"; + + internal static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor( + id: Id, + title: new LocalizableResourceString(nameof(Strings.VSTHRD110_Title), Strings.ResourceManager, typeof(Strings)), + messageFormat: new LocalizableResourceString(nameof(Strings.VSTHRD110_MessageFormat), Strings.ResourceManager, typeof(Strings)), + helpLinkUri: Utils.GetHelpLink(Id), + category: "Usage", + defaultSeverity: DiagnosticSeverity.Warning, + isEnabledByDefault: true); + + /// + public override ImmutableArray SupportedDiagnostics => ImmutableArray.Create(Descriptor); + + private protected abstract LanguageUtils LanguageUtils { get; } + + /// + public override void Initialize(AnalysisContext context) + { + context.EnableConcurrentExecution(); + context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); + + context.RegisterCompilationStartAction(context => + { + CommonInterest.AwaitableTypeTester awaitableTypes = CommonInterest.CollectAwaitableTypes(context.Compilation, context.CancellationToken); + context.RegisterOperationAction(Utils.DebuggableWrapper(context => this.AnalyzeInvocation(context, awaitableTypes)), OperationKind.Invocation); + }); + } + + private void AnalyzeInvocation(OperationAnalysisContext context, CommonInterest.AwaitableTypeTester awaitableTypes) + { + var operation = (IInvocationOperation)context.Operation; + if (operation.Type is null) + { + return; + } + + if (operation.GetContainingFunction() is { } function && this.LanguageUtils.IsAsyncMethod(function.Syntax)) + { + // CS4014 should already take care of this case. + return; + } + + // Only consider invocations that are direct statements. Otherwise, we assume their + // result is awaited, assigned, or otherwise consumed. + if (operation.Parent is IExpressionStatementOperation || operation.Parent is IConditionalAccessOperation) + { + if (awaitableTypes.IsAwaitableType(operation.Type)) + { + context.ReportDiagnostic(Diagnostic.Create(Descriptor, operation.Syntax.GetLocation())); + } + } + } +} diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs index 33beb7da1..5a82d0b0a 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/CommonInterest.cs @@ -14,6 +14,7 @@ using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; +using Microsoft.CodeAnalysis.Operations; using Microsoft.CodeAnalysis.Text; namespace Microsoft.VisualStudio.Threading.Analyzers; @@ -63,6 +64,8 @@ internal static class CommonInterest private const RegexOptions FileNamePatternRegexOptions = RegexOptions.IgnoreCase | RegexOptions.Singleline; + private const string GetAwaiterMethodName = "GetAwaiter"; + private static readonly TimeSpan RegexMatchTimeout = TimeSpan.FromSeconds(5); // Prevent expensive CPU hang in Regex.Match if backtracking occurs due to pathological input (see #485). private static readonly Regex NegatableTypeOrMemberReferenceRegex = new Regex(@"^(?!)?\[(?[^\[\]\:]+)+\](?:\:\:(?\S+))?\s*$", RegexOptions.Singleline | RegexOptions.CultureInvariant, RegexMatchTimeout); @@ -124,10 +127,10 @@ internal static IEnumerable ReadAdditionalFiles(AnalyzerOptions analyzer } IEnumerable? docs = from file in analyzerOptions.AdditionalFiles.OrderBy(x => x.Path, StringComparer.Ordinal) - let fileName = Path.GetFileName(file.Path) - where fileNamePattern.IsMatch(fileName) - let text = file.GetText(cancellationToken) - select text; + let fileName = Path.GetFileName(file.Path) + where fileNamePattern.IsMatch(fileName) + let text = file.GetText(cancellationToken) + select text; return docs.SelectMany(ReadLinesFromAdditionalFile); } @@ -166,6 +169,159 @@ internal static bool Contains(this ImmutableArray types, [NotNull return !matching.IsEmpty && !matching.InvertedLogic; } + internal static CommonInterest.AwaitableTypeTester CollectAwaitableTypes(Compilation compilation, CancellationToken cancellationToken) + { + HashSet awaitableTypes = new(SymbolEqualityComparer.Default); + void AddAwaitableType(ITypeSymbol type) + { + if (type is INamedTypeSymbol { IsGenericType: true, IsUnboundGenericType: false } genericType) + { + awaitableTypes.Add(genericType.ConstructUnboundGenericType()); + } + else + { + awaitableTypes.Add(type); + } + } + + foreach (ISymbol getAwaiterMember in compilation.GetSymbolsWithName(GetAwaiterMethodName, SymbolFilter.Member, cancellationToken)) + { + if (TryGetAwaitableType(getAwaiterMember, out ITypeSymbol? awaitableType)) + { + AddAwaitableType(awaitableType); + } + } + + foreach (IAssemblySymbol referenceAssembly in compilation.Assembly.Modules.First().ReferencedAssemblySymbols) + { + CollectNamespace(referenceAssembly.GlobalNamespace); + + void CollectNamespace(INamespaceOrTypeSymbol nsOrType) + { + if (nsOrType is INamespaceSymbol ns) + { + foreach (INamespaceSymbol nestedNs in ns.GetNamespaceMembers()) + { + CollectNamespace(nestedNs); + } + } + + foreach (INamedTypeSymbol nestedType in nsOrType.GetTypeMembers()) + { + CollectNamespace(nestedType); + } + + foreach (ISymbol getAwaiterMember in nsOrType.GetMembers(GetAwaiterMethodName)) + { + if (TryGetAwaitableType(getAwaiterMember, out ITypeSymbol? awaitableType)) + { + AddAwaitableType(awaitableType); + } + } + } + } + + bool TryGetAwaitableType(ISymbol getAwaiterMember, [NotNullWhen(true)] out ITypeSymbol? awaitableType) + { + if (getAwaiterMember is IMethodSymbol getAwaiterMethod && compilation.IsSymbolAccessibleWithin(getAwaiterMember, compilation.Assembly) && TestGetAwaiterMethod(getAwaiterMethod)) + { + awaitableType = getAwaiterMethod.IsExtensionMethod ? getAwaiterMethod.Parameters[0].Type : getAwaiterMethod.ContainingType; + return true; + } + + awaitableType = null; + return false; + } + + return new AwaitableTypeTester(awaitableTypes); + } + + internal static bool IsAwaitable(this ITypeSymbol? typeSymbol) + { + if (typeSymbol is null) + { + return false; + } + + foreach (ISymbol symbol in typeSymbol.GetMembers(GetAwaiterMethodName)) + { + if (symbol is IMethodSymbol getAwaiterMethod && TestGetAwaiterMethod(getAwaiterMethod)) + { + return true; + } + } + + return false; + } + + internal static bool IsAwaitable(this ITypeSymbol? typeSymbol, SemanticModel semanticModel, int position) + { + if (typeSymbol is null) + { + return false; + } + + // We're able to do a more comprehensive job by detecting extension methods as well when we have a semantic model. + foreach (ISymbol symbol in semanticModel.LookupSymbols(position, typeSymbol, name: GetAwaiterMethodName, includeReducedExtensionMethods: true)) + { + if (symbol is IMethodSymbol getAwaiterMethod && TestGetAwaiterMethod(getAwaiterMethod)) + { + return true; + } + } + + return false; + } + + internal static IOperation? GetContainingFunction(this IOperation? operation) + { + while (operation?.Parent is not null) + { + if (operation.Parent is IAnonymousFunctionOperation or IMethodBodyOperation) + { + return operation.Parent; + } + + if (operation.Language == LanguageNames.VisualBasic) + { + if (operation.Parent is IBlockOperation) + { + return operation.Parent; + } + } + + operation = operation.Parent; + } + + return null; + } + + internal static bool ConformsToAwaiterPattern(ITypeSymbol typeSymbol) + { + if (typeSymbol is null) + { + return false; + } + + var hasGetResultMethod = false; + var hasOnCompletedMethod = false; + var hasIsCompletedProperty = false; + + foreach (ISymbol? member in typeSymbol.GetMembers()) + { + hasGetResultMethod |= member.Name == nameof(TaskAwaiter.GetResult) && member is IMethodSymbol m && m.Parameters.IsEmpty; + hasOnCompletedMethod |= member.Name == nameof(TaskAwaiter.OnCompleted) && member is IMethodSymbol; + hasIsCompletedProperty |= member.Name == nameof(TaskAwaiter.IsCompleted) && member is IPropertySymbol; + + if (hasGetResultMethod && hasOnCompletedMethod && hasIsCompletedProperty) + { + return true; + } + } + + return false; + } + internal static IEnumerable ReadLinesFromAdditionalFile(SourceText text) { if (text is null) @@ -208,6 +364,31 @@ internal static QualifiedMember ParseAdditionalFileMethodLine(string line) return new QualifiedMember(containingType, methodName); } + private static bool TestGetAwaiterMethod(IMethodSymbol getAwaiterMethod) + { + if (getAwaiterMethod.IsExtensionMethod) + { + if (getAwaiterMethod.Parameters.Length != 1) + { + return false; + } + } + else + { + if (!getAwaiterMethod.Parameters.IsEmpty) + { + return false; + } + } + + if (!CommonInterest.ConformsToAwaiterPattern(getAwaiterMethod.ReturnType)) + { + return false; + } + + return true; + } + internal readonly struct TypeMatchSpec { internal TypeMatchSpec(QualifiedType type, QualifiedMember member, bool inverted) @@ -339,4 +520,32 @@ public SyncBlockingMethod(QualifiedMember method, string? asyncAlternativeMethod public IReadOnlyList? ExtensionMethodNamespace { get; } } + + internal class AwaitableTypeTester + { + private readonly HashSet awaitableTypes; + + internal AwaitableTypeTester(HashSet awaitableTypes) + { + this.awaitableTypes = awaitableTypes; + } + + internal bool IsAwaitableType(ITypeSymbol typeSymbol) + { + if (this.awaitableTypes.Contains(typeSymbol)) + { + return true; + } + + if (typeSymbol is INamedTypeSymbol { IsGenericType: true } genericTypeSymbol) + { + if (this.awaitableTypes.Contains(genericTypeSymbol.ConstructUnboundGenericType())) + { + return true; + } + } + + return false; + } + } } diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/DiagnosticAnalyzerState.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/DiagnosticAnalyzerState.cs deleted file mode 100644 index 71c6ada4c..000000000 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/DiagnosticAnalyzerState.cs +++ /dev/null @@ -1,131 +0,0 @@ -// Copyright (c) Microsoft Corporation. All rights reserved. -// Licensed under the MIT license. See LICENSE file in the project root for full license information. - -using System; -using System.Collections.Concurrent; -using System.Collections.Generic; -using System.Collections.Immutable; -using System.Linq; -using System.Runtime.CompilerServices; -using System.Threading; -using System.Threading.Tasks; -using Microsoft.CodeAnalysis; - -namespace Microsoft.VisualStudio.Threading.Analyzers; - -/// -/// A class for our analyzers that provide per-compilation caching by way of its private fields -/// to support common utility methods. -/// -internal abstract class DiagnosticAnalyzerState -{ - private const string GetAwaiterMethodName = nameof(Task.GetAwaiter); - - private readonly ConcurrentDictionary customAwaitableTypes = new ConcurrentDictionary(SymbolEqualityComparer.Default); - - internal bool IsAwaitableType(ITypeSymbol? typeSymbol, Compilation compilation, CancellationToken cancellationToken) - { - if (typeSymbol is null) - { - return false; - } - - if (!this.customAwaitableTypes.TryGetValue(typeSymbol, out bool isAwaitable)) - { - IMethodSymbol? getAwaiterMethod = typeSymbol.GetMembers(nameof(Task.GetAwaiter)).OfType().FirstOrDefault(m => m.Parameters.IsEmpty); - if (getAwaiterMethod is object) - { - isAwaitable = ConformsToAwaiterPattern(getAwaiterMethod.ReturnType); - } - else - { - IEnumerable? awaitableTypesFromThisAssembly = from candidateAwaiterMethod in compilation.GetSymbolsWithName(m => m == GetAwaiterMethodName, SymbolFilter.Member, cancellationToken).OfType() - where candidateAwaiterMethod.IsExtensionMethod && !candidateAwaiterMethod.Parameters.IsEmpty - where ConformsToAwaiterPattern(candidateAwaiterMethod.ReturnType) - select candidateAwaiterMethod.Parameters[0].Type; - IEnumerable? awaitableTypesPerAssembly = from assembly in compilation.Assembly.Modules.First().ReferencedAssemblySymbols - from awaitableType in GetAwaitableTypes(assembly) - select awaitableType; - isAwaitable = awaitableTypesFromThisAssembly.Concat(awaitableTypesPerAssembly).Contains(typeSymbol, SymbolEqualityComparer.Default); - } - - this.customAwaitableTypes.TryAdd(typeSymbol, isAwaitable); - } - - return isAwaitable; - } - - private static bool ConformsToAwaiterPattern(ITypeSymbol typeSymbol) - { - if (typeSymbol is null) - { - return false; - } - - var hasGetResultMethod = false; - var hasOnCompletedMethod = false; - var hasIsCompletedProperty = false; - - foreach (ISymbol? member in typeSymbol.GetMembers()) - { - hasGetResultMethod |= member.Name == nameof(TaskAwaiter.GetResult) && member is IMethodSymbol m && m.Parameters.IsEmpty; - hasOnCompletedMethod |= member.Name == nameof(TaskAwaiter.OnCompleted) && member is IMethodSymbol; - hasIsCompletedProperty |= member.Name == nameof(TaskAwaiter.IsCompleted) && member is IPropertySymbol; - - if (hasGetResultMethod && hasOnCompletedMethod && hasIsCompletedProperty) - { - return true; - } - } - - return false; - } - - private static IEnumerable GetAwaitableTypes(IAssemblySymbol assembly) - { - if (assembly is null) - { - throw new ArgumentNullException(nameof(assembly)); - } - - if (!assembly.MightContainExtensionMethods) - { - return Enumerable.Empty(); - } - - return GetAwaitableTypes(assembly.GlobalNamespace); - } - - private static IEnumerable GetAwaitableTypes(INamespaceOrTypeSymbol namespaceOrTypeSymbol) - { - if (namespaceOrTypeSymbol is null || namespaceOrTypeSymbol.DeclaredAccessibility != Accessibility.Public) - { - yield break; - } - - foreach (ISymbol? member in namespaceOrTypeSymbol.GetMembers()) - { - switch (member) - { - case INamespaceOrTypeSymbol nsOrType: - foreach (ITypeSymbol? nested in GetAwaitableTypes(nsOrType)) - { - yield return nested; - } - - break; - case IMethodSymbol method: - if (method.DeclaredAccessibility == Accessibility.Public && - method.IsExtensionMethod && - method.Name == GetAwaiterMethodName && - !method.Parameters.IsEmpty && - ConformsToAwaiterPattern(method.ReturnType)) - { - yield return method.Parameters[0].Type; - } - - break; - } - } - } -} diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/LanguageUtils.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/LanguageUtils.cs index a48261e63..c97085c26 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/LanguageUtils.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/LanguageUtils.cs @@ -16,4 +16,6 @@ internal abstract class LanguageUtils internal abstract SyntaxNode IsolateMethodName(IObjectCreationOperation objectCreation); internal abstract bool MethodReturnsNullableReferenceType(IMethodSymbol method); + + internal abstract bool IsAsyncMethod(SyntaxNode syntaxNode); } diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.Designer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.Designer.cs index 3ac90eeb4..0e0d5f400 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.Designer.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.Designer.cs @@ -8,642 +8,642 @@ // //------------------------------------------------------------------------------ -namespace Microsoft.VisualStudio.Threading.Analyzers; -using System; -using System.Reflection; - - -/// -/// A strongly-typed resource class, for looking up localized strings, etc. -/// -// This class was auto-generated by the StronglyTypedResourceBuilder -// class via a tool like ResGen or Visual Studio. -// To add or remove a member, edit your .ResX file then rerun ResGen -// with the /str option, or rebuild your VS project. -[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] -[global::System.Diagnostics.DebuggerNonUserCodeAttribute()] -[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] -internal class Strings { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Strings() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.VisualStudio.Threading.Analyzers.Strings", typeof(Strings).GetTypeInfo().Assembly); - resourceMan = temp; +namespace Microsoft.VisualStudio.Threading.Analyzers { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Strings { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Strings() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Microsoft.VisualStudio.Threading.Analyzers.Strings", typeof(Strings).Assembly); + resourceMan = temp; + } + return resourceMan; } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; } - set { - resourceCulture = value; + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } } - } - - /// - /// Looks up a localized string similar to Await {0} instead. - /// - internal static string AwaitXInstead { - get { - return ResourceManager.GetString("AwaitXInstead", resourceCulture); + + /// + /// Looks up a localized string similar to Await {0} instead. + /// + internal static string AwaitXInstead { + get { + return ResourceManager.GetString("AwaitXInstead", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to The System.IAsyncDisposable interface is defined in the Microsoft.Bcl.AsyncInterfaces NuGet package.. - /// - internal static string SystemIAsyncDisposablePackageNote { - get { - return ResourceManager.GetString("SystemIAsyncDisposablePackageNote", resourceCulture); + + /// + /// Looks up a localized string similar to The System.IAsyncDisposable interface is defined in the Microsoft.Bcl.AsyncInterfaces NuGet package.. + /// + internal static string SystemIAsyncDisposablePackageNote { + get { + return ResourceManager.GetString("SystemIAsyncDisposablePackageNote", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use await instead. - /// - internal static string UseAwaitInstead { - get { - return ResourceManager.GetString("UseAwaitInstead", resourceCulture); + + /// + /// Looks up a localized string similar to Use await instead. + /// + internal static string UseAwaitInstead { + get { + return ResourceManager.GetString("UseAwaitInstead", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Await JoinableTaskFactory.SwitchToMainThreadAsync() to switch to the UI thread instead of APIs that can deadlock or require specifying a priority. - /// - internal static string VSTHRD001_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD001_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Await JoinableTaskFactory.SwitchToMainThreadAsync() to switch to the UI thread instead of APIs that can deadlock or require specifying a priority. + /// + internal static string VSTHRD001_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD001_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid legacy thread switching APIs. - /// - internal static string VSTHRD001_Title { - get { - return ResourceManager.GetString("VSTHRD001_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid legacy thread switching APIs. + /// + internal static string VSTHRD001_Title { + get { + return ResourceManager.GetString("VSTHRD001_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use await instead. - /// - internal static string VSTHRD002_CodeFix_Await_Title { - get { - return ResourceManager.GetString("VSTHRD002_CodeFix_Await_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Use await instead. + /// + internal static string VSTHRD002_CodeFix_Await_Title { + get { + return ResourceManager.GetString("VSTHRD002_CodeFix_Await_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Synchronously waiting on tasks or awaiters may cause deadlocks. Use await or JoinableTaskFactory.Run instead.. - /// - internal static string VSTHRD002_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD002_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Synchronously waiting on tasks or awaiters may cause deadlocks. Use await or JoinableTaskFactory.Run instead.. + /// + internal static string VSTHRD002_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD002_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid problematic synchronous waits. - /// - internal static string VSTHRD002_Title { - get { - return ResourceManager.GetString("VSTHRD002_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid problematic synchronous waits. + /// + internal static string VSTHRD002_Title { + get { + return ResourceManager.GetString("VSTHRD002_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid awaiting or returning a Task representing work that was not started within your context as that can lead to deadlocks. - ///Start the work within this context, or use JoinableTaskFactory.RunAsync to start the task and await the returned JoinableTask instead.. - /// - internal static string VSTHRD003_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD003_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid awaiting or returning a Task representing work that was not started within your context as that can lead to deadlocks. + ///Start the work within this context, or use JoinableTaskFactory.RunAsync to start the task and await the returned JoinableTask instead.. + /// + internal static string VSTHRD003_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD003_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid awaiting foreign Tasks. - /// - internal static string VSTHRD003_Title { - get { - return ResourceManager.GetString("VSTHRD003_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid awaiting foreign Tasks. + /// + internal static string VSTHRD003_Title { + get { + return ResourceManager.GetString("VSTHRD003_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Calls to JoinableTaskFactory.SwitchToMainThreadAsync() must be awaited. - /// - internal static string VSTHRD004_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD004_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Calls to JoinableTaskFactory.SwitchToMainThreadAsync() must be awaited. + /// + internal static string VSTHRD004_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD004_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Await SwitchToMainThreadAsync. - /// - internal static string VSTHRD004_Title { - get { - return ResourceManager.GetString("VSTHRD004_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Await SwitchToMainThreadAsync. + /// + internal static string VSTHRD004_Title { + get { + return ResourceManager.GetString("VSTHRD004_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Accessing "{0}" should only be done on the main thread. Await JoinableTaskFactory.SwitchToMainThreadAsync() first.. - /// - internal static string VSTHRD010_MessageFormat_Async { - get { - return ResourceManager.GetString("VSTHRD010_MessageFormat_Async", resourceCulture); + + /// + /// Looks up a localized string similar to Accessing "{0}" should only be done on the main thread. Await JoinableTaskFactory.SwitchToMainThreadAsync() first.. + /// + internal static string VSTHRD010_MessageFormat_Async { + get { + return ResourceManager.GetString("VSTHRD010_MessageFormat_Async", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Accessing "{0}" should only be done on the main thread. Call {1}() first.. - /// - internal static string VSTHRD010_MessageFormat_Sync { - get { - return ResourceManager.GetString("VSTHRD010_MessageFormat_Sync", resourceCulture); + + /// + /// Looks up a localized string similar to Accessing "{0}" should only be done on the main thread. Call {1}() first.. + /// + internal static string VSTHRD010_MessageFormat_Sync { + get { + return ResourceManager.GetString("VSTHRD010_MessageFormat_Sync", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Invoke single-threaded types on Main thread. - /// - internal static string VSTHRD010_Title { - get { - return ResourceManager.GetString("VSTHRD010_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Invoke single-threaded types on Main thread. + /// + internal static string VSTHRD010_Title { + get { + return ResourceManager.GetString("VSTHRD010_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Lazy<Task<T>>.Value can deadlock. Use AsyncLazy<T> instead.. - /// - internal static string VSTHRD011_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD011_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Lazy<Task<T>>.Value can deadlock. Use AsyncLazy<T> instead.. + /// + internal static string VSTHRD011_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD011_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use AsyncLazy<T>. - /// - internal static string VSTHRD011_Title { - get { - return ResourceManager.GetString("VSTHRD011_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Use AsyncLazy<T>. + /// + internal static string VSTHRD011_Title { + get { + return ResourceManager.GetString("VSTHRD011_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Invoking or blocking on async code in a Lazy<T> value factory can deadlock. Use AsyncLazy<T> instead.. - /// - internal static string VSTHRD011b_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD011b_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Invoking or blocking on async code in a Lazy<T> value factory can deadlock. Use AsyncLazy<T> instead.. + /// + internal static string VSTHRD011b_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD011b_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Provide an instance of JoinableTaskFactory in this call (or another overload) to avoid deadlocks with the main thread. - /// - internal static string VSTHRD012_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD012_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Provide an instance of JoinableTaskFactory in this call (or another overload) to avoid deadlocks with the main thread. + /// + internal static string VSTHRD012_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD012_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Provide JoinableTaskFactory where allowed. - /// - internal static string VSTHRD012_Title { - get { - return ResourceManager.GetString("VSTHRD012_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Provide JoinableTaskFactory where allowed. + /// + internal static string VSTHRD012_Title { + get { + return ResourceManager.GetString("VSTHRD012_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Change return type to Task. - /// - internal static string VSTHRD100_CodeFix_Title { - get { - return ResourceManager.GetString("VSTHRD100_CodeFix_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Change return type to Task. + /// + internal static string VSTHRD100_CodeFix_Title { + get { + return ResourceManager.GetString("VSTHRD100_CodeFix_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid "async void" methods, because any exceptions not handled by the method will crash the process. - /// - internal static string VSTHRD100_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD100_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid "async void" methods, because any exceptions not handled by the method will crash the process. + /// + internal static string VSTHRD100_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD100_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid async void methods. - /// - internal static string VSTHRD100_Title { - get { - return ResourceManager.GetString("VSTHRD100_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid async void methods. + /// + internal static string VSTHRD100_Title { + get { + return ResourceManager.GetString("VSTHRD100_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid using async lambda for a void returning delegate type, because any exceptions not handled by the delegate will crash the process. - /// - internal static string VSTHRD101_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD101_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid using async lambda for a void returning delegate type, because any exceptions not handled by the delegate will crash the process. + /// + internal static string VSTHRD101_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD101_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid unsupported async delegates. - /// - internal static string VSTHRD101_Title { - get { - return ResourceManager.GetString("VSTHRD101_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid unsupported async delegates. + /// + internal static string VSTHRD101_Title { + get { + return ResourceManager.GetString("VSTHRD101_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Limit use of synchronously blocking method calls such as JoinableTaskFactory.Run or Task.Result to public entrypoint members where you must be synchronous. Using it for internal members can needlessly add synchronous frames between asynchronous frames, leading to threadpool exhaustion.. - /// - internal static string VSTHRD102_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD102_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Limit use of synchronously blocking method calls such as JoinableTaskFactory.Run or Task.Result to public entrypoint members where you must be synchronous. Using it for internal members can needlessly add synchronous frames between asynchronous frames, leading to threadpool exhaustion.. + /// + internal static string VSTHRD102_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD102_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Implement internal logic asynchronously. - /// - internal static string VSTHRD102_Title { - get { - return ResourceManager.GetString("VSTHRD102_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Implement internal logic asynchronously. + /// + internal static string VSTHRD102_Title { + get { + return ResourceManager.GetString("VSTHRD102_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to {0} synchronously blocks. Await {1} instead.. - /// - internal static string VSTHRD103_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD103_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to {0} synchronously blocks. Await {1} instead.. + /// + internal static string VSTHRD103_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD103_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to {0} synchronously blocks. Use await instead.. - /// - internal static string VSTHRD103_MessageFormat_UseAwaitInstead { - get { - return ResourceManager.GetString("VSTHRD103_MessageFormat_UseAwaitInstead", resourceCulture); + + /// + /// Looks up a localized string similar to {0} synchronously blocks. Use await instead.. + /// + internal static string VSTHRD103_MessageFormat_UseAwaitInstead { + get { + return ResourceManager.GetString("VSTHRD103_MessageFormat_UseAwaitInstead", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Call async methods when in an async method. - /// - internal static string VSTHRD103_Title { - get { - return ResourceManager.GetString("VSTHRD103_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Call async methods when in an async method. + /// + internal static string VSTHRD103_Title { + get { + return ResourceManager.GetString("VSTHRD103_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Expose an async version of this method that does not synchronously block. Then simplify this method to call that async method within a JoinableTaskFactory.Run delegate.. - /// - internal static string VSTHRD104_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD104_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Expose an async version of this method that does not synchronously block. Then simplify this method to call that async method within a JoinableTaskFactory.Run delegate.. + /// + internal static string VSTHRD104_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD104_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Offer async methods. - /// - internal static string VSTHRD104_Title { - get { - return ResourceManager.GetString("VSTHRD104_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Offer async methods. + /// + internal static string VSTHRD104_Title { + get { + return ResourceManager.GetString("VSTHRD104_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid method overloads that assume TaskScheduler.Current. Use an overload that accepts a TaskScheduler and specify TaskScheduler.Default (or any other) explicitly.. - /// - internal static string VSTHRD105_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD105_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid method overloads that assume TaskScheduler.Current. Use an overload that accepts a TaskScheduler and specify TaskScheduler.Default (or any other) explicitly.. + /// + internal static string VSTHRD105_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD105_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid method overloads that assume TaskScheduler.Current. - /// - internal static string VSTHRD105_Title { - get { - return ResourceManager.GetString("VSTHRD105_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid method overloads that assume TaskScheduler.Current. + /// + internal static string VSTHRD105_Title { + get { + return ResourceManager.GetString("VSTHRD105_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to AsyncEventHandler delegates should be invoked via the extension method "TplExtensions.InvokeAsync()" defined in Microsoft.VisualStudio.Threading assembly. - /// - internal static string VSTHRD106_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD106_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to AsyncEventHandler delegates should be invoked via the extension method "TplExtensions.InvokeAsync()" defined in Microsoft.VisualStudio.Threading assembly. + /// + internal static string VSTHRD106_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD106_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use InvokeAsync to raise async events. - /// - internal static string VSTHRD106_Title { - get { - return ResourceManager.GetString("VSTHRD106_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Use InvokeAsync to raise async events. + /// + internal static string VSTHRD106_Title { + get { + return ResourceManager.GetString("VSTHRD106_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Await using expression. - /// - internal static string VSTHRD107_CodeFix_Title { - get { - return ResourceManager.GetString("VSTHRD107_CodeFix_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Await using expression. + /// + internal static string VSTHRD107_CodeFix_Title { + get { + return ResourceManager.GetString("VSTHRD107_CodeFix_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Missing await operator for "using" expression. - /// - internal static string VSTHRD107_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD107_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Missing await operator for "using" expression. + /// + internal static string VSTHRD107_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD107_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Await Task within using expression. - /// - internal static string VSTHRD107_Title { - get { - return ResourceManager.GetString("VSTHRD107_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Await Task within using expression. + /// + internal static string VSTHRD107_Title { + get { + return ResourceManager.GetString("VSTHRD107_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Thread affinity checks should be unconditional. - /// - internal static string VSTHRD108_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD108_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Thread affinity checks should be unconditional. + /// + internal static string VSTHRD108_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD108_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Assert thread affinity unconditionally. - /// - internal static string VSTHRD108_Title { - get { - return ResourceManager.GetString("VSTHRD108_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Assert thread affinity unconditionally. + /// + internal static string VSTHRD108_Title { + get { + return ResourceManager.GetString("VSTHRD108_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid throwing when not on the main thread while in an async or Task-returning method. Switch to the thread required instead.. - /// - internal static string VSTHRD109_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD109_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid throwing when not on the main thread while in an async or Task-returning method. Switch to the thread required instead.. + /// + internal static string VSTHRD109_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD109_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Switch instead of assert in async methods. - /// - internal static string VSTHRD109_Title { - get { - return ResourceManager.GetString("VSTHRD109_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Switch instead of assert in async methods. + /// + internal static string VSTHRD109_Title { + get { + return ResourceManager.GetString("VSTHRD109_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Observe the awaitable result of this method call by awaiting it, assigning to a variable, or passing it to another method.. - /// - internal static string VSTHRD110_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD110_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Observe the awaitable result of this method call by awaiting it, assigning to a variable, or passing it to another method. + /// + internal static string VSTHRD110_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD110_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Observe result of async calls. - /// - internal static string VSTHRD110_Title { - get { - return ResourceManager.GetString("VSTHRD110_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Observe result of async calls. + /// + internal static string VSTHRD110_Title { + get { + return ResourceManager.GetString("VSTHRD110_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Add .ConfigureAwait(false). - /// - internal static string VSTHRD111_CodeFix_False_Title { - get { - return ResourceManager.GetString("VSTHRD111_CodeFix_False_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Add .ConfigureAwait(false). + /// + internal static string VSTHRD111_CodeFix_False_Title { + get { + return ResourceManager.GetString("VSTHRD111_CodeFix_False_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Add .ConfigureAwait(true). - /// - internal static string VSTHRD111_CodeFix_True_Title { - get { - return ResourceManager.GetString("VSTHRD111_CodeFix_True_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Add .ConfigureAwait(true). + /// + internal static string VSTHRD111_CodeFix_True_Title { + get { + return ResourceManager.GetString("VSTHRD111_CodeFix_True_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Add .ConfigureAwait(bool) to your await expression. - /// - internal static string VSTHRD111_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD111_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Add .ConfigureAwait(bool) to your await expression. + /// + internal static string VSTHRD111_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD111_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use ConfigureAwait(bool). - /// - internal static string VSTHRD111_Title { - get { - return ResourceManager.GetString("VSTHRD111_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Use ConfigureAwait(bool). + /// + internal static string VSTHRD111_Title { + get { + return ResourceManager.GetString("VSTHRD111_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Add implementation of System.IAsyncDisposable.. - /// - internal static string VSTHRD112_CodeFix_Title { - get { - return ResourceManager.GetString("VSTHRD112_CodeFix_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Add implementation of System.IAsyncDisposable.. + /// + internal static string VSTHRD112_CodeFix_Title { + get { + return ResourceManager.GetString("VSTHRD112_CodeFix_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Implement the System.IAsyncDisposable interface when implementing the obsolete Microsoft.VisualStudio.Threading.IAsyncDisposable interface. - /// - internal static string VSTHRD112_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD112_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Implement the System.IAsyncDisposable interface when implementing the obsolete Microsoft.VisualStudio.Threading.IAsyncDisposable interface. + /// + internal static string VSTHRD112_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD112_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Implement System.IAsyncDisposable. - /// - internal static string VSTHRD112_Title { - get { - return ResourceManager.GetString("VSTHRD112_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Implement System.IAsyncDisposable. + /// + internal static string VSTHRD112_Title { + get { + return ResourceManager.GetString("VSTHRD112_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Add a check for System.IAsyncDisposable in the same code block that checks for Microsoft.VisualStudio.Threading.IAsyncDisposable that behaves similarly. - /// - internal static string VSTHRD113_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD113_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Add a check for System.IAsyncDisposable in the same code block that checks for Microsoft.VisualStudio.Threading.IAsyncDisposable that behaves similarly. + /// + internal static string VSTHRD113_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD113_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Check for System.IAsyncDisposable. - /// - internal static string VSTHRD113_Title { - get { - return ResourceManager.GetString("VSTHRD113_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Check for System.IAsyncDisposable. + /// + internal static string VSTHRD113_Title { + get { + return ResourceManager.GetString("VSTHRD113_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use 'Task.CompletedTask' instead. - /// - internal static string VSTHRD114_CodeFix_CompletedTask { - get { - return ResourceManager.GetString("VSTHRD114_CodeFix_CompletedTask", resourceCulture); + + /// + /// Looks up a localized string similar to Use 'Task.CompletedTask' instead. + /// + internal static string VSTHRD114_CodeFix_CompletedTask { + get { + return ResourceManager.GetString("VSTHRD114_CodeFix_CompletedTask", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use 'Task.FromResult' instead. - /// - internal static string VSTHRD114_CodeFix_FromResult { - get { - return ResourceManager.GetString("VSTHRD114_CodeFix_FromResult", resourceCulture); + + /// + /// Looks up a localized string similar to Use 'Task.FromResult' instead. + /// + internal static string VSTHRD114_CodeFix_FromResult { + get { + return ResourceManager.GetString("VSTHRD114_CodeFix_FromResult", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid returning null from a Task-returning method. - /// - internal static string VSTHRD114_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD114_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid returning null from a Task-returning method. + /// + internal static string VSTHRD114_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD114_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid returning a null Task. - /// - internal static string VSTHRD114_Title { - get { - return ResourceManager.GetString("VSTHRD114_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid returning a null Task. + /// + internal static string VSTHRD114_Title { + get { + return ResourceManager.GetString("VSTHRD114_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use "Async" suffix in names of methods that return an awaitable type. - /// - internal static string VSTHRD200_AddAsync_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD200_AddAsync_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Use "Async" suffix in names of methods that return an awaitable type. + /// + internal static string VSTHRD200_AddAsync_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD200_AddAsync_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Rename to {0}. - /// - internal static string VSTHRD200_CodeFix_Title { - get { - return ResourceManager.GetString("VSTHRD200_CodeFix_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Rename to {0}. + /// + internal static string VSTHRD200_CodeFix_Title { + get { + return ResourceManager.GetString("VSTHRD200_CodeFix_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Avoid "Async" suffix in names of methods that do not return an awaitable type. - /// - internal static string VSTHRD200_RemoveAsync_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD200_RemoveAsync_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Avoid "Async" suffix in names of methods that do not return an awaitable type. + /// + internal static string VSTHRD200_RemoveAsync_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD200_RemoveAsync_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Use "Async" suffix for async methods. - /// - internal static string VSTHRD200_Title { - get { - return ResourceManager.GetString("VSTHRD200_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Use "Async" suffix for async methods. + /// + internal static string VSTHRD200_Title { + get { + return ResourceManager.GetString("VSTHRD200_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Call ThrowIfCancellationRequested(). - /// - internal static string VSTHRD201_CodeFix_Title { - get { - return ResourceManager.GetString("VSTHRD201_CodeFix_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Call ThrowIfCancellationRequested(). + /// + internal static string VSTHRD201_CodeFix_Title { + get { + return ResourceManager.GetString("VSTHRD201_CodeFix_Title", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Check for cancellation after calling SwitchToMainThreadAsync(CancellationToken).. - /// - internal static string VSTHRD201_MessageFormat { - get { - return ResourceManager.GetString("VSTHRD201_MessageFormat", resourceCulture); + + /// + /// Looks up a localized string similar to Check for cancellation after calling SwitchToMainThreadAsync(CancellationToken).. + /// + internal static string VSTHRD201_MessageFormat { + get { + return ResourceManager.GetString("VSTHRD201_MessageFormat", resourceCulture); + } } - } - - /// - /// Looks up a localized string similar to Check cancellation after SwitchToMainThreadAsync. - /// - internal static string VSTHRD201_Title { - get { - return ResourceManager.GetString("VSTHRD201_Title", resourceCulture); + + /// + /// Looks up a localized string similar to Check cancellation after SwitchToMainThreadAsync. + /// + internal static string VSTHRD201_Title { + get { + return ResourceManager.GetString("VSTHRD201_Title", resourceCulture); + } } } } diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.resx b/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.resx index 236a96b45..40b76e27f 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.resx +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/Strings.resx @@ -271,7 +271,7 @@ Start the work within this context, or use JoinableTaskFactory.RunAsync to start Do not translate either of these. The first is a keyword, the second is a method name. - Observe the awaitable result of this method call by awaiting it, assigning to a variable, or passing it to another method. + Observe the awaitable result of this method call by awaiting it, assigning to a variable, or passing it to another method Observe result of async calls diff --git a/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD200UseAsyncNamingConventionAnalyzer.cs b/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD200UseAsyncNamingConventionAnalyzer.cs index b09811dea..9e5c92b5e 100644 --- a/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD200UseAsyncNamingConventionAnalyzer.cs +++ b/src/Microsoft.VisualStudio.Threading.Analyzers/VSTHRD200UseAsyncNamingConventionAnalyzer.cs @@ -2,8 +2,11 @@ // Licensed under the MIT license. See LICENSE file in the project root for full license information. using System; +using System.Collections.Concurrent; +using System.Collections.Generic; using System.Collections.Immutable; using System.Linq; +using System.Threading; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.Diagnostics; @@ -47,60 +50,61 @@ public override void Initialize(AnalysisContext context) context.EnableConcurrentExecution(); context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze); - context.RegisterSymbolAction(Utils.DebuggableWrapper(new PerCompilation().AnalyzeNode), SymbolKind.Method); + context.RegisterCompilationStartAction(context => + { + CommonInterest.AwaitableTypeTester awaitableTypes = CommonInterest.CollectAwaitableTypes(context.Compilation, context.CancellationToken); + context.RegisterSymbolAction(Utils.DebuggableWrapper(context => this.AnalyzeNode(context, awaitableTypes)), SymbolKind.Method); + }); } - private class PerCompilation : DiagnosticAnalyzerState + private void AnalyzeNode(SymbolAnalysisContext context, CommonInterest.AwaitableTypeTester awaitableTypes) { - internal void AnalyzeNode(SymbolAnalysisContext context) + var methodSymbol = (IMethodSymbol)context.Symbol; + if (methodSymbol.AssociatedSymbol is IPropertySymbol) + { + // Skip accessor methods associated with properties. + return; + } + + // Skip entrypoint methods since their name is non-negotiable. + if (Utils.IsEntrypointMethod(methodSymbol, context.Compilation, context.CancellationToken)) { - var methodSymbol = (IMethodSymbol)context.Symbol; - if (methodSymbol.AssociatedSymbol is IPropertySymbol) + return; + } + + bool hasAsyncFocusedReturnType = Utils.HasAsyncCompatibleReturnType(methodSymbol); + + bool actuallyEndsWithAsync = methodSymbol.Name.EndsWith(MandatoryAsyncSuffix, StringComparison.CurrentCulture); + + if (hasAsyncFocusedReturnType != actuallyEndsWithAsync) + { + // Now that we have done the cheap checks to find that this method may deserve a diagnostic, + // Do deeper checks to skip over methods that implement API contracts that are controlled elsewhere. + if (methodSymbol.FindInterfacesImplemented().Any() || methodSymbol.IsOverride) { - // Skip accessor methods associated with properties. return; } - // Skip entrypoint methods since their name is non-negotiable. - if (Utils.IsEntrypointMethod(methodSymbol, context.Compilation, context.CancellationToken)) + if (hasAsyncFocusedReturnType) { - return; + // We actively encourage folks to use the Async keyword only for clearly async-focused types. + // Not just any awaitable, since some stray extension method shouldn't change the world for everyone. + ImmutableDictionary? properties = ImmutableDictionary.Empty + .Add(NewNameKey, methodSymbol.Name + MandatoryAsyncSuffix); + context.ReportDiagnostic(Diagnostic.Create( + AddAsyncDescriptor, + methodSymbol.Locations[0], + properties)); } - - bool hasAsyncFocusedReturnType = Utils.HasAsyncCompatibleReturnType(methodSymbol); - - bool actuallyEndsWithAsync = methodSymbol.Name.EndsWith(MandatoryAsyncSuffix, StringComparison.CurrentCulture); - - if (hasAsyncFocusedReturnType != actuallyEndsWithAsync) + else if (!awaitableTypes.IsAwaitableType(methodSymbol.ReturnType)) { - // Now that we have done the cheap checks to find that this method may deserve a diagnostic, - // Do deeper checks to skip over methods that implement API contracts that are controlled elsewhere. - if (methodSymbol.FindInterfacesImplemented().Any() || methodSymbol.IsOverride) - { - return; - } - - if (hasAsyncFocusedReturnType) - { - // We actively encourage folks to use the Async keyword only for clearly async-focused types. - // Not just any awaitable, since some stray extension method shouldn't change the world for everyone. - ImmutableDictionary? properties = ImmutableDictionary.Empty - .Add(NewNameKey, methodSymbol.Name + MandatoryAsyncSuffix); - context.ReportDiagnostic(Diagnostic.Create( - AddAsyncDescriptor, - methodSymbol.Locations[0], - properties)); - } - else if (!this.IsAwaitableType(methodSymbol.ReturnType, context.Compilation, context.CancellationToken)) - { - // Only warn about abusing the Async suffix if the return type is not awaitable. - ImmutableDictionary? properties = ImmutableDictionary.Empty - .Add(NewNameKey, methodSymbol.Name.Substring(0, methodSymbol.Name.Length - MandatoryAsyncSuffix.Length)); - context.ReportDiagnostic(Diagnostic.Create( - RemoveAsyncDescriptor, - methodSymbol.Locations[0], - properties)); - } + // Only warn about abusing the Async suffix if the return type is not awaitable. + ImmutableDictionary? properties = ImmutableDictionary.Empty + .Add(NewNameKey, methodSymbol.Name.Substring(0, methodSymbol.Name.Length - MandatoryAsyncSuffix.Length)); + context.ReportDiagnostic(Diagnostic.Create( + RemoveAsyncDescriptor, + methodSymbol.Locations[0], + properties)); } } } diff --git a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs index a2b2d4120..7169b44df 100644 --- a/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs +++ b/test/Microsoft.VisualStudio.Threading.Analyzers.Tests/VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests.cs @@ -1,7 +1,8 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT license. See LICENSE file in the project root for full license information. -using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; +using CSVerify = Microsoft.VisualStudio.Threading.Analyzers.Tests.CSharpCodeFixVerifier; +using VerifyVB = Microsoft.VisualStudio.Threading.Analyzers.Tests.VisualBasicCodeFixVerifier; public class VSTHRD110ObserveResultOfAsyncCallsAnalyzerTests { @@ -14,15 +15,34 @@ public async Task SyncMethod_ProducesDiagnostic() class Test { void Foo() { - BarAsync(); + [|BarAsync()|]; } Task BarAsync() => null; } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 9, 8); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); + } + + [Fact] + public async Task SyncMethod_ProducesDiagnostic_VB() + { + var test = @" +Imports System.Threading.Tasks + +Class Test + Sub Foo + [|BarAsync()|] + End Sub + + Function BarAsync() As Task + Return Nothing + End Function +End Class +"; + + await VerifyVB.VerifyAnalyzerAsync(test); } [Fact] @@ -35,7 +55,7 @@ class Test { async Task Foo() { await Task.Run(delegate { - BarAsync(); + [|BarAsync()|]; }); } @@ -43,8 +63,7 @@ await Task.Run(delegate { } "; - DiagnosticResult expected = this.CreateDiagnostic(8, 13, 8); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -158,7 +177,7 @@ public async Task ContinueWith_ProducesDiagnostic() class Test { void Foo() { - BarAsync().ContinueWith(_ => { }); // ContinueWith returns the dropped task + [|BarAsync().ContinueWith(_ => { })|]; // ContinueWith returns the dropped task } Task BarAsync() => null; @@ -167,8 +186,7 @@ void OtherMethod(Task t) { } } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 20, 12); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -190,6 +208,26 @@ async Task FooAsync() await CSVerify.VerifyAnalyzerAsync(test); // CS4014 should already take care of this case. } + [Fact] + public async Task AsyncMethod_ProducesNoDiagnostic_VB() + { + var test = @" +Imports System.Threading.Tasks + +Class Test + Async Function Foo() As Task + BarAsync() + End Function + + Function BarAsync() As Task + Return Nothing + End Function +End Class +"; + + await VerifyVB.VerifyAnalyzerAsync(test); // CS4014 should already take care of this case. + } + [Fact] public async Task CallToNonExistentMethod() { @@ -218,15 +256,14 @@ public async Task ConfigureAwait_ProducesDiagnostics() class Test { void Foo() { - BarAsync().ConfigureAwait(false); + [|BarAsync().ConfigureAwait(false)|]; } Task BarAsync() => Task.CompletedTask; } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 20, nameof(Task.ConfigureAwait).Length); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -238,15 +275,14 @@ public async Task ConfigureAwaitGenerics_ProducesDiagnostics() class Test { void Foo() { - BarAsync().ConfigureAwait(false); + [|BarAsync().ConfigureAwait(false)|]; } Task BarAsync() => Task.FromResult(0); } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 20, nameof(Task.ConfigureAwait).Length); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -259,7 +295,7 @@ public async Task CustomAwaitable_ProducesDiagnostics() class Test { void Foo() { - BarAsync(); + [|BarAsync()|]; } CustomTask BarAsync() => new CustomTask(); @@ -283,8 +319,7 @@ public void GetResult() } } "; - DiagnosticResult expected = this.CreateDiagnostic(8, 9, 8); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -327,15 +362,14 @@ public async Task SyncMethodWithValueTask_ProducesDiagnostic() class Test { void Foo() { - BarAsync(); + [|BarAsync()|]; } ValueTask BarAsync() => default; } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 9, 8); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -347,15 +381,14 @@ public async Task ConfigureAwaitValueTask_ProducesDiagnostics() class Test { void Foo() { - BarAsync().ConfigureAwait(false); + [|BarAsync().ConfigureAwait(false)|]; } ValueTask BarAsync() => default; } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 20, nameof(Task.ConfigureAwait).Length); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -367,15 +400,14 @@ public async Task ConditionalAccess_ProducesDiagnostic() class Test { void Foo(Test? tester) { - tester?.BarAsync(); + tester?[|.BarAsync()|]; } Task BarAsync() => null; } "; - DiagnosticResult expected = this.CreateDiagnostic(7, 17, 8); - await CSVerify.VerifyAnalyzerAsync(test, expected); + await CSVerify.VerifyAnalyzerAsync(test); } [Fact] @@ -408,7 +440,7 @@ public class Test : IAsyncDisposable { ~Test() { - Task.[|Run|](async () => await DisposeAsync().ConfigureAwait(false)); + [|Task.Run(async () => await DisposeAsync().ConfigureAwait(false))|]; } public async ValueTask DisposeAsync()