Skip to content
This repository was archived by the owner on Nov 8, 2018. It is now read-only.

Commit cbb8b98

Browse files
committed
Implement diagnostic IncludeCancellationParameter
1 parent 7fee02b commit cbb8b98

File tree

6 files changed

+554
-1
lines changed

6 files changed

+554
-1
lines changed

AsyncUsageAnalyzers/AsyncUsageAnalyzers.Test/AsyncUsageAnalyzers.Test.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@
123123
<Compile Include="Naming\AvoidAsyncSuffixUnitTests.cs" />
124124
<Compile Include="Naming\UseAsyncSuffixUnitTests.cs" />
125125
<Compile Include="Reliability\AvoidAsyncVoidUnitTests.cs" />
126+
<Compile Include="Usage\IncludeCancellationParameterUnitTests.cs" />
126127
<Compile Include="Usage\UseConfigureAwaitUnitTests.cs" />
127128
<Compile Include="Verifiers\CodeFixVerifier.cs" />
128129
<Compile Include="Verifiers\DiagnosticVerifier.cs" />
Lines changed: 310 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,310 @@
1+
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
2+
// Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information.
3+
4+
namespace AsyncUsageAnalyzers.Test.Usage
5+
{
6+
using System.Collections.Generic;
7+
using System.Threading;
8+
using System.Threading.Tasks;
9+
using AsyncUsageAnalyzers.Usage;
10+
using Microsoft.CodeAnalysis.Diagnostics;
11+
using TestHelper;
12+
using Xunit;
13+
14+
public class IncludeCancellationParameterUnitTests : DiagnosticVerifier
15+
{
16+
public static IEnumerable<object[]> AsynchronousUnitTestWithReturnValue
17+
{
18+
get
19+
{
20+
yield return new[] { " public Task MethodAsync(string param1, string param2) { return null; }", "TestMethod" };
21+
yield return new[] { " public Task MethodAsync(string param1, string param2) { return null; }", "Fact" };
22+
yield return new[] { " public Task MethodAsync(string param1, string param2) { return null; }", "Theory" };
23+
yield return new[] { " public Task MethodAsync(string param1, string param2) { return null; }", "Test" };
24+
yield return new[] { " public Task<int> MethodAsync(string param1, string param2) { return null; }", "TestMethod" };
25+
yield return new[] { " public Task<int> MethodAsync(string param1, string param2) { return null; }", "Fact" };
26+
yield return new[] { " public Task<int> MethodAsync(string param1, string param2) { return null; }", "Theory" };
27+
yield return new[] { " public Task<int> MethodAsync(string param1, string param2) { return null; }", "Test" };
28+
yield return new[] { " public TASK MethodAsync(string param1, string param2) { return null; }", "TestMethod" };
29+
yield return new[] { " public TASK MethodAsync(string param1, string param2) { return null; }", "Fact" };
30+
yield return new[] { " public TASK MethodAsync(string param1, string param2) { return null; }", "Theory" };
31+
yield return new[] { " public TASK MethodAsync(string param1, string param2) { return null; }", "Test" };
32+
}
33+
}
34+
35+
[Fact]
36+
public async Task TestPropertyAsync()
37+
{
38+
string testCode = @"
39+
using System.Threading.Tasks;
40+
class ClassName
41+
{
42+
Task PropertyName { get; set; }
43+
}
44+
";
45+
46+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
47+
}
48+
49+
[Fact]
50+
public async Task TestPrivateMemberAsync()
51+
{
52+
string testCode = @"
53+
using System.Threading.Tasks;
54+
class ClassName
55+
{
56+
async Task Method1Async() { }
57+
private async Task Method2Async() { }
58+
}
59+
";
60+
61+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
62+
}
63+
64+
[Fact]
65+
public async Task TestCancellationTokenInStructureAsync()
66+
{
67+
string testCode = @"
68+
using System.Threading;
69+
using System.Threading.Tasks;
70+
class ClassName
71+
{
72+
public async Task MethodAsync(Context context) { }
73+
}
74+
75+
struct Context
76+
{
77+
public CancellationToken CancellationToken { get; }
78+
}
79+
";
80+
81+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
82+
}
83+
84+
[Fact]
85+
public async Task TestContextStructureUsesMethodAsync()
86+
{
87+
string testCode = @"
88+
using System.Threading;
89+
using System.Threading.Tasks;
90+
class ClassName
91+
{
92+
public async Task MethodAsync(Context context) { }
93+
}
94+
95+
struct Context
96+
{
97+
public CancellationToken CancellationToken() => default(CancellationToken);
98+
}
99+
";
100+
101+
var expected = this.CSharpDiagnostic().WithArguments("MethodAsync").WithLocation(6, 23);
102+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
103+
}
104+
105+
[Fact]
106+
public async Task TestContextStructurePropertyIsNotPublicAsync()
107+
{
108+
string testCode = @"
109+
using System.Threading;
110+
using System.Threading.Tasks;
111+
class ClassName
112+
{
113+
public async Task MethodAsync(Context context) { }
114+
}
115+
116+
struct Context
117+
{
118+
internal CancellationToken CancellationToken { get; }
119+
}
120+
";
121+
122+
var expected = this.CSharpDiagnostic().WithArguments("MethodAsync").WithLocation(6, 23);
123+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
124+
}
125+
126+
[Fact]
127+
public async Task TestContextStructurePropertyHasWrongNameAsync()
128+
{
129+
string testCode = @"
130+
using System.Threading;
131+
using System.Threading.Tasks;
132+
class ClassName
133+
{
134+
public async Task MethodAsync(Context context) { }
135+
}
136+
137+
struct Context
138+
{
139+
public CancellationToken Token { get; }
140+
}
141+
";
142+
143+
var expected = this.CSharpDiagnostic().WithArguments("MethodAsync").WithLocation(6, 23);
144+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
145+
}
146+
147+
[Fact]
148+
public async Task TestContextStructurePropertyReturnsAnotherTypeAsync()
149+
{
150+
string testCode = @"
151+
using System.Threading;
152+
using System.Threading.Tasks;
153+
class ClassName
154+
{
155+
public async Task MethodAsync(Context context) { }
156+
}
157+
158+
struct Context
159+
{
160+
public int CancellationToken { get; }
161+
}
162+
";
163+
164+
var expected = this.CSharpDiagnostic().WithArguments("MethodAsync").WithLocation(6, 23);
165+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
166+
}
167+
168+
[Fact]
169+
public async Task TestCancellationTokenInInterfaceAsync()
170+
{
171+
string testCode = @"
172+
using System.Threading;
173+
using System.Threading.Tasks;
174+
class ClassName
175+
{
176+
public async Task MethodAsync(IContext context) { }
177+
}
178+
179+
interface IContext
180+
{
181+
CancellationToken CancellationToken { get; }
182+
}
183+
";
184+
185+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
186+
}
187+
188+
[Fact]
189+
public async Task TestAsyncVoidMethodAsync()
190+
{
191+
string testCode = @"
192+
class ClassName
193+
{
194+
public async void Method1Async() { }
195+
}
196+
";
197+
198+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
199+
}
200+
201+
[Fact]
202+
public async Task TestMethodsWithCancellationTokenAsync()
203+
{
204+
string testCode = @"
205+
using System.Threading;
206+
using System.Threading.Tasks;
207+
using CT = System.Threading.CancellationToken;
208+
class ClassName
209+
{
210+
public async Task Method1Async(CancellationToken cancellationToken) { }
211+
public async Task Method2Async(CT cancellationToken) { }
212+
public async Task<int> Method3Async(CancellationToken cancellationToken) { return 0; }
213+
public async Task<int> Method4Async(CT cancellationToken) { return 0; }
214+
public Task Method5Async(CancellationToken cancellationToken) { return Task.FromResult(0); }
215+
public Task Method6Async(CT cancellationToken) { return Task.FromResult(0); }
216+
public Task<int> Method7Async(CancellationToken cancellationToken) { return Task.FromResult(0); }
217+
public Task<int> Method8Async(CT cancellationToken) { return Task.FromResult(0); }
218+
}
219+
";
220+
221+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
222+
}
223+
224+
[Fact]
225+
public async Task TestMethodsWithoutCancellationTokenAsync()
226+
{
227+
string testCode = @"
228+
using System.Threading.Tasks;
229+
class ClassName
230+
{
231+
public async Task Method1Async() { }
232+
public async Task<int> Method2Async() { return 0; }
233+
public Task Method3Async() { return Task.FromResult(0); }
234+
public Task<int> Method4Async() { return Task.FromResult(0); }
235+
}
236+
";
237+
238+
DiagnosticResult[] expected =
239+
{
240+
this.CSharpDiagnostic().WithArguments("Method1Async").WithLocation(5, 23),
241+
this.CSharpDiagnostic().WithArguments("Method2Async").WithLocation(6, 28),
242+
this.CSharpDiagnostic().WithArguments("Method3Async").WithLocation(7, 17),
243+
this.CSharpDiagnostic().WithArguments("Method4Async").WithLocation(8, 22),
244+
};
245+
246+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
247+
}
248+
249+
[Fact]
250+
public async Task TestMethodsWithWrongCancellationTokenAsync()
251+
{
252+
string testCode = @"
253+
using System.Threading.Tasks;
254+
using CT = CancellationToken;
255+
class ClassName
256+
{
257+
public async Task Method1Async(CancellationToken cancellationToken) { }
258+
public async Task Method2Async(CT cancellationToken) { }
259+
public async Task<int> Method3Async(CancellationToken cancellationToken) { return 0; }
260+
public async Task<int> Method4Async(CT cancellationToken) { return 0; }
261+
public Task Method5Async(CancellationToken cancellationToken) { return Task.FromResult(0); }
262+
public Task Method6Async(CT cancellationToken) { return Task.FromResult(0); }
263+
public Task<int> Method7Async(CancellationToken cancellationToken) { return Task.FromResult(0); }
264+
public Task<int> Method8Async(CT cancellationToken) { return Task.FromResult(0); }
265+
}
266+
267+
struct CancellationToken
268+
{
269+
}
270+
";
271+
272+
DiagnosticResult[] expected =
273+
{
274+
this.CSharpDiagnostic().WithArguments("Method1Async").WithLocation(6, 23),
275+
this.CSharpDiagnostic().WithArguments("Method2Async").WithLocation(7, 23),
276+
this.CSharpDiagnostic().WithArguments("Method3Async").WithLocation(8, 28),
277+
this.CSharpDiagnostic().WithArguments("Method4Async").WithLocation(9, 28),
278+
this.CSharpDiagnostic().WithArguments("Method5Async").WithLocation(10, 17),
279+
this.CSharpDiagnostic().WithArguments("Method6Async").WithLocation(11, 17),
280+
this.CSharpDiagnostic().WithArguments("Method7Async").WithLocation(12, 22),
281+
this.CSharpDiagnostic().WithArguments("Method8Async").WithLocation(13, 22),
282+
};
283+
284+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
285+
}
286+
287+
[Theory]
288+
[MemberData(nameof(AsynchronousUnitTestWithReturnValue))]
289+
public async Task TestAsynchronousUnitTestMethodAsync(string declaration, string testAttribute)
290+
{
291+
var testCode = @"
292+
using System.Threading.Tasks;
293+
using TASK = System.Threading.Tasks.Task<int>;
294+
public class ClassName
295+
{
296+
[##]
297+
$$
298+
}
299+
internal sealed class ##Attribute : System.Attribute { }
300+
";
301+
302+
await this.VerifyCSharpDiagnosticAsync(testCode.Replace("$$", declaration).Replace("##", testAttribute), EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
303+
}
304+
305+
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
306+
{
307+
yield return new IncludeCancellationParameterAnalyzer();
308+
}
309+
}
310+
}

AsyncUsageAnalyzers/AsyncUsageAnalyzers/AsyncUsageAnalyzers.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
<DesignTime>True</DesignTime>
7878
<DependentUpon>Resources.resx</DependentUpon>
7979
</Compile>
80+
<Compile Include="Usage\IncludeCancellationParameterAnalyzer.cs" />
8081
<Compile Include="Usage\UsageResources.Designer.cs">
8182
<AutoGen>True</AutoGen>
8283
<DesignTime>True</DesignTime>

0 commit comments

Comments
 (0)