Skip to content

Commit 42b14bf

Browse files
committed
Implemented allowConsecutiveUsings option
1 parent 2a966c1 commit 42b14bf

5 files changed

Lines changed: 70 additions & 3 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/LayoutRules/SA1519UnitTests.cs

Lines changed: 40 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@ namespace StyleCop.Analyzers.Test.LayoutRules
1414

1515
public class SA1519UnitTests : CodeFixVerifier
1616
{
17+
private string consecutiveUsingsSettings;
18+
1719
/// <summary>
1820
/// Gets the statements that will be used in the theory test cases.
1921
/// </summary>
@@ -120,13 +122,45 @@ public void Bar(int i)
120122
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
121123
}
122124

125+
/// <summary>
126+
/// This is a regression test for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2184.
127+
/// </summary>
128+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
129+
[Fact]
130+
public async Task TestMultipleUsingStatementsWithDefaultSettingsAsync()
131+
{
132+
var testCode = @"using System;
133+
public class Foo
134+
{
135+
public void Bar(int i)
136+
{
137+
using (default(IDisposable))
138+
using (default(IDisposable))
139+
{
140+
}
141+
}
142+
}";
143+
144+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
145+
}
146+
123147
/// <summary>
124148
/// This is a regression test for https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/2180.
125149
/// </summary>
126150
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
127151
[Fact]
128-
public async Task TestMultipleUsingStatementsAsync()
152+
public async Task TestMultipleUsingStatementsWithDisabledSettingAsync()
129153
{
154+
this.consecutiveUsingsSettings = @"
155+
{
156+
""settings"": {
157+
""layoutRules"": {
158+
""allowConsecutiveUsings"": false
159+
}
160+
}
161+
}
162+
";
163+
130164
var testCode = @"using System;
131165
public class Foo
132166
{
@@ -599,6 +633,11 @@ public void Bar(int i)
599633
await this.VerifyCSharpFixAsync(testCode, testCode).ConfigureAwait(false);
600634
}
601635

636+
protected override string GetSettings()
637+
{
638+
return this.consecutiveUsingsSettings ?? base.GetSettings();
639+
}
640+
602641
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
603642
{
604643
yield return new SA1519BracesMustNotBeOmittedFromMultiLineChildStatement();

StyleCop.Analyzers/StyleCop.Analyzers/LayoutRules/SA1519BracesMustNotBeOmittedFromMultiLineChildStatement.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ namespace StyleCop.Analyzers.LayoutRules
99
using Microsoft.CodeAnalysis.CSharp;
1010
using Microsoft.CodeAnalysis.CSharp.Syntax;
1111
using Microsoft.CodeAnalysis.Diagnostics;
12+
using Settings.ObjectModel;
1213
using StyleCop.Analyzers.Helpers;
1314

1415
/// <summary>
@@ -48,7 +49,7 @@ internal class SA1519BracesMustNotBeOmittedFromMultiLineChildStatement : Diagnos
4849
private static readonly Action<SyntaxNodeAnalysisContext> WhileStatementAction = HandleWhileStatement;
4950
private static readonly Action<SyntaxNodeAnalysisContext> ForStatementAction = HandleForStatement;
5051
private static readonly Action<SyntaxNodeAnalysisContext> ForEachStatementAction = HandleForEachStatement;
51-
private static readonly Action<SyntaxNodeAnalysisContext> UsingStatementAction = HandleUsingStatement;
52+
private static readonly Action<SyntaxNodeAnalysisContext, StyleCopSettings> UsingStatementAction = HandleUsingStatement;
5253

5354
/// <inheritdoc/>
5455
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } =
@@ -108,9 +109,15 @@ private static void HandleForEachStatement(SyntaxNodeAnalysisContext context)
108109
CheckChildStatement(context, forEachStatement.Statement);
109110
}
110111

111-
private static void HandleUsingStatement(SyntaxNodeAnalysisContext context)
112+
private static void HandleUsingStatement(SyntaxNodeAnalysisContext context, StyleCopSettings settings)
112113
{
113114
var usingStatement = (UsingStatementSyntax)context.Node;
115+
116+
if (settings.LayoutRules.AllowConsecutiveUsings && (usingStatement.Statement is UsingStatementSyntax))
117+
{
118+
return;
119+
}
120+
114121
CheckChildStatement(context, usingStatement.Statement);
115122
}
116123

StyleCop.Analyzers/StyleCop.Analyzers/Settings/ObjectModel/LayoutSettings.cs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,16 +14,23 @@ internal class LayoutSettings
1414
[JsonProperty("newlineAtEndOfFile", DefaultValueHandling = DefaultValueHandling.Include)]
1515
private EndOfFileHandling newlineAtEndOfFile;
1616

17+
[JsonProperty("allowConsecutiveUsings", DefaultValueHandling = DefaultValueHandling.Include)]
18+
private bool allowConsecutiveUsings;
19+
1720
/// <summary>
1821
/// Initializes a new instance of the <see cref="LayoutSettings"/> class during JSON deserialization.
1922
/// </summary>
2023
[JsonConstructor]
2124
protected internal LayoutSettings()
2225
{
2326
this.newlineAtEndOfFile = EndOfFileHandling.Allow;
27+
this.allowConsecutiveUsings = true;
2428
}
2529

2630
public EndOfFileHandling NewlineAtEndOfFile =>
2731
this.newlineAtEndOfFile;
32+
33+
public bool AllowConsecutiveUsings =>
34+
this.allowConsecutiveUsings;
2835
}
2936
}

StyleCop.Analyzers/StyleCop.Analyzers/Settings/stylecop.schema.json

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,11 @@
154154
"omit"
155155
],
156156
"default": "allow"
157+
},
158+
"allowConsecutiveUsings": {
159+
"type": "boolean",
160+
"description": "Specifies if SA1519 will allow consecutive using statements without braces",
161+
"default": true
157162
}
158163
}
159164
},

documentation/Configuration.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -303,6 +303,7 @@ The following properties are used to configure layout rules in StyleCop Analyzer
303303
| Property | Default Value | Summary |
304304
| --- | --- | --- |
305305
| `newlineAtEndOfFile` | `"allow"` | Specifies the handling for newline characters which appear at the end of a file |
306+
| `allowConsecutiveUsings` | `true` | Specifies if SA1519 will allow consecutive using statements without braces |
306307

307308
### Lines at End of File
308309

@@ -313,6 +314,14 @@ file are handled. The `newlineAtEndOfFile` property supports the following value
313314
* `"require"`: Files are required to end with a single newline character
314315
* `"omit"`: Files may not end with a newline character
315316

317+
### Consecutive using statements without braces
318+
319+
The behavior of [SA1519](SA1519.md) can be customized regarding the manner in which consecutive using statements without braces are treated.
320+
The `allowConsecutiveUsings` property specifies the behavior:
321+
322+
* `true`: consecutive using statements without braces will not produce diagnostics
323+
* `false`: consecutive using statements without braces will produce a SA1519 diagnostic
324+
316325
## Documentation Rules
317326

318327
This section describes the features of documentation rules which can be configured in **stylecop.json**. Each of the described properties are configured in the `documentationRules` object, which is shown in the following sample file.

0 commit comments

Comments
 (0)