Skip to content

Commit c33ff28

Browse files
authored
Merge pull request #2395 from sharwell/csharp7-layout
Update layout rules for C# 7
2 parents 02b3f63 + 2143ed5 commit c33ff28

26 files changed

Lines changed: 1043 additions & 8 deletions

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/LayoutRules/SA1502CodeFixProvider.cs

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,13 +8,14 @@ namespace StyleCop.Analyzers.LayoutRules
88
using System.Composition;
99
using System.Threading;
1010
using System.Threading.Tasks;
11-
using Helpers;
1211
using Microsoft.CodeAnalysis;
1312
using Microsoft.CodeAnalysis.CodeActions;
1413
using Microsoft.CodeAnalysis.CodeFixes;
1514
using Microsoft.CodeAnalysis.CSharp;
1615
using Microsoft.CodeAnalysis.CSharp.Syntax;
17-
using Settings.ObjectModel;
16+
using StyleCop.Analyzers.Helpers;
17+
using StyleCop.Analyzers.Lightup;
18+
using StyleCop.Analyzers.Settings.ObjectModel;
1819

1920
/// <summary>
2021
/// Implements a code fix for <see cref="SA1502ElementMustNotBeOnASingleLine"/>.
@@ -77,7 +78,15 @@ private Document CreateCodeFix(Document document, IndentationSettings indentatio
7778
break;
7879

7980
case SyntaxKind.Block:
80-
newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationSettings);
81+
if (node.Parent.IsKind(SyntaxKindEx.LocalFunctionStatement))
82+
{
83+
newSyntaxRoot = this.RegisterLocalFunctionStatementCodeFix(syntaxRoot, (LocalFunctionStatementSyntaxWrapper)node.Parent, indentationSettings);
84+
}
85+
else
86+
{
87+
newSyntaxRoot = this.RegisterMethodLikeDeclarationCodeFix(syntaxRoot, (BaseMethodDeclarationSyntax)node.Parent, indentationSettings);
88+
}
89+
8190
break;
8291

8392
case SyntaxKind.NamespaceDeclaration:
@@ -103,6 +112,11 @@ private SyntaxNode RegisterMethodLikeDeclarationCodeFix(SyntaxNode syntaxRoot, B
103112
return this.ReformatElement(syntaxRoot, node, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentationSettings);
104113
}
105114

115+
private SyntaxNode RegisterLocalFunctionStatementCodeFix(SyntaxNode syntaxRoot, LocalFunctionStatementSyntaxWrapper node, IndentationSettings indentationSettings)
116+
{
117+
return this.ReformatElement(syntaxRoot, node, node.Body.OpenBraceToken, node.Body.CloseBraceToken, indentationSettings);
118+
}
119+
106120
private SyntaxNode RegisterEnumDeclarationCodeFix(SyntaxNode syntaxRoot, EnumDeclarationSyntax node, IndentationSettings indentationSettings)
107121
{
108122
return this.ReformatElement(syntaxRoot, node, node.OpenBraceToken, node.CloseBraceToken, indentationSettings);
Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
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 StyleCop.Analyzers.Test.CSharp7.LayoutRules
5+
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
8+
using StyleCop.Analyzers.Test.LayoutRules;
9+
using TestHelper;
10+
using Xunit;
11+
12+
public class SA1500CSharp7UnitTests : SA1500UnitTests
13+
{
14+
/// <summary>
15+
/// Verifies that no diagnostics are reported for the valid local functions defined in this test.
16+
/// </summary>
17+
/// <remarks>
18+
/// These are valid for SA1500 only, some will report other diagnostics from the layout (SA15xx) series.
19+
/// </remarks>
20+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
21+
[Fact]
22+
public async Task TestLocalFunctionValidAsync()
23+
{
24+
var testCode = @"using System.Diagnostics;
25+
26+
public class Foo
27+
{
28+
public void Method()
29+
{
30+
// Valid local function #1
31+
void LocalFunction1()
32+
{
33+
}
34+
35+
// Valid local function #2
36+
void LocalFunction2()
37+
{
38+
Debug.Indent();
39+
}
40+
41+
// Valid local function #3 (Valid only for SA1500)
42+
void LocalFunction3() { }
43+
44+
// Valid local function #4 (Valid only for SA1500)
45+
void LocalFunction4() { Debug.Indent(); }
46+
47+
// Valid local function #5 (Valid only for SA1500)
48+
void LocalFunction5()
49+
{ Debug.Indent(); }
50+
}
51+
}";
52+
53+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
54+
}
55+
56+
/// <summary>
57+
/// Verifies that diagnostics will be reported for all invalid local function definitions.
58+
/// </summary>
59+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
60+
[Fact]
61+
public async Task TestLocalFunctionInvalidAsync()
62+
{
63+
var testCode = @"using System.Diagnostics;
64+
65+
public class Foo
66+
{
67+
public void Method()
68+
{
69+
// Invalid local function #1
70+
void LocalFunction1() {
71+
}
72+
73+
// Invalid local function #2
74+
void LocalFunction2() {
75+
Debug.Indent();
76+
}
77+
78+
// Invalid local function #3
79+
void LocalFunction3() {
80+
Debug.Indent(); }
81+
82+
// Invalid local function #4
83+
void LocalFunction4() { Debug.Indent();
84+
}
85+
86+
// Invalid local function #5
87+
void LocalFunction5()
88+
{
89+
Debug.Indent(); }
90+
91+
// Invalid local function #6
92+
void LocalFunction6()
93+
{ Debug.Indent();
94+
}
95+
}
96+
}";
97+
98+
var fixedTestCode = @"using System.Diagnostics;
99+
100+
public class Foo
101+
{
102+
public void Method()
103+
{
104+
// Invalid local function #1
105+
void LocalFunction1()
106+
{
107+
}
108+
109+
// Invalid local function #2
110+
void LocalFunction2()
111+
{
112+
Debug.Indent();
113+
}
114+
115+
// Invalid local function #3
116+
void LocalFunction3()
117+
{
118+
Debug.Indent();
119+
}
120+
121+
// Invalid local function #4
122+
void LocalFunction4()
123+
{
124+
Debug.Indent();
125+
}
126+
127+
// Invalid local function #5
128+
void LocalFunction5()
129+
{
130+
Debug.Indent();
131+
}
132+
133+
// Invalid local function #6
134+
void LocalFunction6()
135+
{
136+
Debug.Indent();
137+
}
138+
}
139+
}";
140+
141+
DiagnosticResult[] expectedDiagnostics =
142+
{
143+
// Invalid local function #1
144+
this.CSharpDiagnostic().WithLocation(8, 31),
145+
146+
// Invalid local function #2
147+
this.CSharpDiagnostic().WithLocation(12, 31),
148+
149+
// Invalid local function #3
150+
this.CSharpDiagnostic().WithLocation(17, 31),
151+
this.CSharpDiagnostic().WithLocation(18, 29),
152+
153+
// Invalid local function #4
154+
this.CSharpDiagnostic().WithLocation(21, 31),
155+
156+
// Invalid local function #5
157+
this.CSharpDiagnostic().WithLocation(27, 29),
158+
159+
// Invalid local function #6
160+
this.CSharpDiagnostic().WithLocation(31, 9),
161+
};
162+
163+
await this.VerifyCSharpDiagnosticAsync(testCode, expectedDiagnostics, CancellationToken.None).ConfigureAwait(false);
164+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
165+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
166+
}
167+
}
168+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
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 StyleCop.Analyzers.Test.CSharp7.LayoutRules
5+
{
6+
using StyleCop.Analyzers.Test.LayoutRules;
7+
8+
public class SA1501CSharp7UnitTests : SA1501UnitTests
9+
{
10+
}
11+
}

0 commit comments

Comments
 (0)