Skip to content

Commit 5dd2127

Browse files
authored
Merge pull request #4037 from sharwell/async-streams
Support async streams from C# 8
2 parents d4ebd50 + 152c412 commit 5dd2127

File tree

7 files changed

+196
-2
lines changed

7 files changed

+196
-2
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/ReadabilityRules/SA1106CodeFixProvider.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@ private static async Task<Document> RemoveEmptyStatementAsync(Document document,
7777
case SyntaxKind.IfStatement:
7878
case SyntaxKind.ElseClause:
7979
case SyntaxKind.ForStatement:
80+
case SyntaxKind.ForEachStatement:
8081
case SyntaxKind.WhileStatement:
8182
case SyntaxKind.DoStatement:
8283
// these cases are always replaced with an empty block

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/LayoutRules/SA1503CSharp8UnitTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,41 @@ public void Method()
9494

9595
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
9696
}
97+
98+
[Fact]
99+
[WorkItem(3007, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3007")]
100+
public async Task TestAwaitForEachMustUseBracesAsync()
101+
{
102+
var testCode = @"
103+
using System.Collections.Generic;
104+
using System.Threading.Tasks;
105+
106+
public class TestClass
107+
{
108+
public async Task TestAsync(IAsyncEnumerable<int> values)
109+
{
110+
await foreach (var value in values)
111+
{|#0:_ = value;|}
112+
}
113+
}
114+
";
115+
var fixedCode = @"
116+
using System.Collections.Generic;
117+
using System.Threading.Tasks;
118+
119+
public class TestClass
120+
{
121+
public async Task TestAsync(IAsyncEnumerable<int> values)
122+
{
123+
await foreach (var value in values)
124+
{
125+
_ = value;
126+
}
127+
}
128+
}
129+
";
130+
131+
await VerifyCSharpFixAsync(testCode, Diagnostic().WithLocation(0), fixedCode, CancellationToken.None).ConfigureAwait(false);
132+
}
97133
}
98134
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/LayoutRules/SA1519CSharp8UnitTests.cs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,52 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp8.LayoutRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.CSharp7.LayoutRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
11+
StyleCop.Analyzers.LayoutRules.SA1519BracesMustNotBeOmittedFromMultiLineChildStatement,
12+
StyleCop.Analyzers.LayoutRules.SA1503CodeFixProvider>;
713

814
public partial class SA1519CSharp8UnitTests : SA1519CSharp7UnitTests
915
{
16+
[Fact]
17+
[WorkItem(3007, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3007")]
18+
public async Task TestAwaitForEachMultiLineChildRequiresBracesAsync()
19+
{
20+
var testCode = @"
21+
using System.Collections.Generic;
22+
using System.Threading.Tasks;
23+
24+
public class TestClass
25+
{
26+
public async Task TestAsync(IAsyncEnumerable<int> values)
27+
{
28+
await foreach (var value in values)
29+
{|#0:System.Console.WriteLine(
30+
value);|}
31+
}
32+
}
33+
";
34+
var fixedCode = @"
35+
using System.Collections.Generic;
36+
using System.Threading.Tasks;
37+
38+
public class TestClass
39+
{
40+
public async Task TestAsync(IAsyncEnumerable<int> values)
41+
{
42+
await foreach (var value in values)
43+
{
44+
System.Console.WriteLine(
45+
value);
46+
}
47+
}
48+
}
49+
";
50+
51+
await VerifyCSharpFixAsync(testCode, Diagnostic().WithLocation(0), fixedCode, CancellationToken.None).ConfigureAwait(false);
52+
}
1053
}
1154
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/ReadabilityRules/SA1106CSharp8UnitTests.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,39 @@ public void Method()
9494

9595
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
9696
}
97+
98+
[Fact]
99+
[WorkItem(3007, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3007")]
100+
public async Task TestAwaitForEachEmptyStatementAsync()
101+
{
102+
var testCode = @"
103+
using System.Collections.Generic;
104+
using System.Threading.Tasks;
105+
106+
public class TestClass
107+
{
108+
public async Task TestAsync(IAsyncEnumerable<int> values)
109+
{
110+
await foreach (var value in values){|#0:;|}
111+
}
112+
}
113+
";
114+
var fixedCode = @"
115+
using System.Collections.Generic;
116+
using System.Threading.Tasks;
117+
118+
public class TestClass
119+
{
120+
public async Task TestAsync(IAsyncEnumerable<int> values)
121+
{
122+
await foreach (var value in values)
123+
{
124+
}
125+
}
126+
}
127+
";
128+
129+
await VerifyCSharpFixAsync(testCode, Diagnostic().WithLocation(0), fixedCode, CancellationToken.None).ConfigureAwait(false);
130+
}
97131
}
98132
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/SpacingRules/SA1000CSharp8UnitTests.cs

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,42 @@
33

44
namespace StyleCop.Analyzers.Test.CSharp8.SpacingRules
55
{
6+
using System.Threading.Tasks;
7+
using Microsoft.CodeAnalysis.Testing;
68
using StyleCop.Analyzers.Test.CSharp7.SpacingRules;
9+
using Xunit;
10+
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
11+
StyleCop.Analyzers.SpacingRules.SA1000KeywordsMustBeSpacedCorrectly,
12+
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;
713

814
public partial class SA1000CSharp8UnitTests : SA1000CSharp7UnitTests
915
{
16+
[Fact]
17+
[WorkItem(3007, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3007")]
18+
public async Task TestAwaitForEachMissingSpaceAsync()
19+
{
20+
string statementWithoutSpace = @"await {|#0:foreach|}(var value in GetValues())
21+
{
22+
_ = value;
23+
}
24+
25+
async IAsyncEnumerable<int> GetValues()
26+
{
27+
yield return 1;
28+
}";
29+
string statementWithSpace = @"await foreach (var value in GetValues())
30+
{
31+
_ = value;
32+
}
33+
34+
async IAsyncEnumerable<int> GetValues()
35+
{
36+
yield return 1;
37+
}";
38+
39+
DiagnosticResult expected = Diagnostic().WithArguments("foreach", string.Empty, "followed").WithLocation(0);
40+
41+
await this.TestKeywordStatementAsync(statementWithoutSpace, expected, statementWithSpace, returnType: "Task", asyncMethod: true).ConfigureAwait(false);
42+
}
1043
}
1144
}

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp8/SpacingRules/SA1008CSharp8UnitTests.cs

Lines changed: 48 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,6 @@
11
// Copyright (c) Tunnel Vision Laboratories, LLC. All Rights Reserved.
22
// Licensed under the MIT License. See LICENSE in the project root for license information.
33

4-
#nullable disable
5-
64
namespace StyleCop.Analyzers.Test.CSharp8.SpacingRules
75
{
86
using System.Threading;
@@ -237,5 +235,53 @@ await VerifyCSharpFixAsync(
237235
fixedCode,
238236
CancellationToken.None).ConfigureAwait(false);
239237
}
238+
239+
[Fact]
240+
[WorkItem(3007, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3007")]
241+
public async Task TestAwaitForEachSpaceAfterParenAsync()
242+
{
243+
var testCode = @"
244+
namespace TestNamespace
245+
{
246+
using System.Collections.Generic;
247+
using System.Threading.Tasks;
248+
249+
public class TestClass
250+
{
251+
public async Task ConsumeAsync(IAsyncEnumerable<int> values)
252+
{
253+
await foreach {|#0:(|} var value in values)
254+
{
255+
_ = value;
256+
}
257+
}
258+
}
259+
}
260+
";
261+
var fixedCode = @"
262+
namespace TestNamespace
263+
{
264+
using System.Collections.Generic;
265+
using System.Threading.Tasks;
266+
267+
public class TestClass
268+
{
269+
public async Task ConsumeAsync(IAsyncEnumerable<int> values)
270+
{
271+
await foreach (var value in values)
272+
{
273+
_ = value;
274+
}
275+
}
276+
}
277+
}
278+
";
279+
280+
await VerifyCSharpFixAsync(
281+
testCode,
282+
Diagnostic(DescriptorNotFollowed).WithLocation(0),
283+
fixedCode,
284+
CancellationToken.None).ConfigureAwait(false);
285+
}
240286
}
241287
}

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1106UnitTests.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public class SA1106UnitTests
2020
[InlineData("if (true)")]
2121
[InlineData("if (true) { } else")]
2222
[InlineData("for (int i = 0; i < 10; i++)")]
23+
[InlineData("foreach (int i in new int[] { 0 })")]
2324
[InlineData("while (true)")]
2425
public async Task TestEmptyStatementAsBlockAsync(string controlFlowConstruct)
2526
{

0 commit comments

Comments
 (0)