Add VSTHRD002 check for ValueTask sync blocking methods

This commit is contained in:
Andrew Arnott 2018-09-22 17:57:54 -07:00
Родитель be09861d89
Коммит 715ba29b09
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: A9B9910CDCCDA441
3 изменённых файлов: 63 добавлений и 3 удалений

Просмотреть файл

@ -1,6 +1,6 @@
# VSTHRD002 Avoid problematic synchronous waits
Synchronously waiting on `Task` objects or awaiters is dangerous and may cause dead locks.
Synchronously waiting on `Task`, `ValueTask`, or awaiters is dangerous and may cause dead locks.
## Examples of patterns that are flagged by this analyzer

Просмотреть файл

@ -61,7 +61,7 @@ class Test {
}
[Fact]
public async Task TaskResultShouldReportWarning()
public async Task Task_Result_ShouldReportWarning()
{
var test = @"
using System;
@ -89,6 +89,35 @@ class Test {
await Verify.VerifyCodeFixAsync(test, expected, withFix);
}
[Fact]
public async Task ValueTask_Result_ShouldReportWarning()
{
var test = @"
using System;
using System.Threading.Tasks;
class Test {
void F() {
ValueTask<int> task = default;
var result = task.Result;
}
}
";
var withFix = @"
using System;
using System.Threading.Tasks;
class Test {
async Task FAsync() {
ValueTask<int> task = default;
var result = await task;
}
}
";
var expected = Verify.Diagnostic().WithSpan(8, 27, 8, 33);
await Verify.VerifyCodeFixAsync(test, expected, withFix);
}
[Fact]
public async Task TaskResultShouldReportWarning_WithinAnonymousDelegate()
{
@ -142,7 +171,7 @@ class Test {
}
[Fact]
public async Task AwaiterGetResultShouldReportWarning()
public async Task Task_GetAwaiter_GetResult_ShouldReportWarning()
{
var test = @"
using System;
@ -170,6 +199,35 @@ class Test {
await Verify.VerifyCodeFixAsync(test, expected, withFix);
}
[Fact]
public async Task ValueTask_GetAwaiter_GetResult_ShouldReportWarning()
{
var test = @"
using System;
using System.Threading.Tasks;
class Test {
void F() {
ValueTask task = default;
task.GetAwaiter().GetResult();
}
}
";
var withFix = @"
using System;
using System.Threading.Tasks;
class Test {
async Task FAsync() {
ValueTask task = default;
await task;
}
}
";
var expected = Verify.Diagnostic().WithSpan(8, 27, 8, 36);
await Verify.VerifyCodeFixAsync(test, expected, withFix);
}
[Fact]
public async Task TaskResult_FixUpdatesCallers()
{

Просмотреть файл

@ -32,6 +32,7 @@ namespace Microsoft.VisualStudio.Threading.Analyzers
{
new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(Task)), nameof(Task.Wait)), null),
new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(TaskAwaiter)), nameof(TaskAwaiter.GetResult)), null),
new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemRuntimeCompilerServices, nameof(ValueTaskAwaiter)), nameof(ValueTaskAwaiter.GetResult)), null),
};
internal static readonly IEnumerable<SyncBlockingMethod> SyncBlockingMethods = JTFSyncBlockers.Concat(ProblematicSyncBlockingMethods).Concat(new[]
@ -55,6 +56,7 @@ namespace Microsoft.VisualStudio.Threading.Analyzers
internal static readonly IReadOnlyList<SyncBlockingMethod> SyncBlockingProperties = new[]
{
new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(Task)), nameof(Task<int>.Result)), null),
new SyncBlockingMethod(new QualifiedMember(new QualifiedType(Namespaces.SystemThreadingTasks, nameof(ValueTask)), nameof(ValueTask<int>.Result)), null),
};
internal static readonly IEnumerable<QualifiedMember> ThreadAffinityTestingMethods = new[]