Skip to content

Commit b8c8f6d

Browse files
committed
Update SA1503 and SA1106 for using declarations
1 parent b72b3f7 commit b8c8f6d

File tree

4 files changed

+132
-4
lines changed

4 files changed

+132
-4
lines changed

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

Lines changed: 64 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.LayoutRules
75
{
86
using System.Threading;
@@ -32,5 +30,69 @@ public void Method()
3230

3331
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
3432
}
33+
34+
[Fact]
35+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
36+
public async Task TestUsingDeclarationWithFollowingStatementAsync()
37+
{
38+
var testCode = @"
39+
using System.IO;
40+
public class Foo
41+
{
42+
public int Method()
43+
{
44+
using var stream = new MemoryStream();
45+
return stream.ReadByte();
46+
}
47+
}";
48+
49+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
50+
}
51+
52+
[Fact]
53+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
54+
public async Task TestAwaitUsingDeclarationStatementAsync()
55+
{
56+
var testCode = @"
57+
using System;
58+
using System.Threading.Tasks;
59+
60+
public class Foo
61+
{
62+
public async Task MethodAsync()
63+
{
64+
await using var resource = new AsyncDisposable();
65+
await Task.Yield();
66+
}
67+
68+
private sealed class AsyncDisposable : IAsyncDisposable
69+
{
70+
public ValueTask DisposeAsync()
71+
{
72+
return default;
73+
}
74+
}
75+
}";
76+
77+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
78+
}
79+
80+
[Fact]
81+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
82+
public async Task TestMultipleUsingDeclarationsAsync()
83+
{
84+
var testCode = @"
85+
using System.IO;
86+
public class Foo
87+
{
88+
public void Method()
89+
{
90+
using MemoryStream stream1 = new MemoryStream(), stream2 = new MemoryStream();
91+
_ = stream1.ReadByte() + stream2.ReadByte();
92+
}
93+
}";
94+
95+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
96+
}
3597
}
3698
}

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

Lines changed: 64 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.ReadabilityRules
75
{
86
using System.Threading;
@@ -32,5 +30,69 @@ public void Method()
3230

3331
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
3432
}
33+
34+
[Fact]
35+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
36+
public async Task TestUsingDeclarationWithFollowingStatementAsync()
37+
{
38+
var testCode = @"
39+
using System.IO;
40+
public class Foo
41+
{
42+
public int Method()
43+
{
44+
using var stream = new MemoryStream();
45+
return stream.ReadByte();
46+
}
47+
}";
48+
49+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
50+
}
51+
52+
[Fact]
53+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
54+
public async Task TestAwaitUsingDeclarationAsync()
55+
{
56+
var testCode = @"
57+
using System;
58+
using System.Threading.Tasks;
59+
60+
public class Foo
61+
{
62+
public async Task MethodAsync()
63+
{
64+
await using var resource = new AsyncDisposable();
65+
await Task.Yield();
66+
}
67+
68+
private sealed class AsyncDisposable : IAsyncDisposable
69+
{
70+
public ValueTask DisposeAsync()
71+
{
72+
return default;
73+
}
74+
}
75+
}";
76+
77+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
78+
}
79+
80+
[Fact]
81+
[WorkItem(3004, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3004")]
82+
public async Task TestMultipleUsingDeclarationsAsync()
83+
{
84+
var testCode = @"
85+
using System.IO;
86+
public class Foo
87+
{
88+
public void Method()
89+
{
90+
using MemoryStream stream1 = new MemoryStream(), stream2 = new MemoryStream();
91+
_ = stream1.ReadByte() + stream2.ReadByte();
92+
}
93+
}";
94+
95+
await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
96+
}
3597
}
3698
}

documentation/SA1106.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ The C# code contains an extra semicolon.
2323

2424
A violation of this rule occurs when the code contain an extra semicolon. Syntactically, this results in an extra, empty statement in the code.
2525

26+
C# 8 using declarations (e.g. `using var stream = new MemoryStream();` or `await using`) end with a required semicolon that is part of the declaration syntax. This semicolon is not considered an empty statement and does not trigger this rule.
27+
2628
## How to fix violations
2729

2830
To fix a violation of this rule, remove the unneeded semicolon.

documentation/SA1503.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ if (true)
5050
}
5151
```
5252

53+
C# 8 using declarations intentionally omit a braced block. Statements like `using var stream = new MemoryStream();` (or `await using` for `IAsyncDisposable`) are valid and will not be flagged by this rule, because wrapping them in braces would alter the lifetime of the declared resource.
54+
5355
## How to fix violations
5456

5557
To fix a violation of this rule, wrap the body of the statement in braces.

0 commit comments

Comments
 (0)