Skip to content

Commit 352a301

Browse files
committed
Implement support for local functions in SA1112
1 parent 20b8fca commit 352a301

2 files changed

Lines changed: 88 additions & 9 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp7/ReadabilityRules/SA1112CSharp7UnitTests.cs

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

44
namespace StyleCop.Analyzers.Test.CSharp7.ReadabilityRules
55
{
6+
using System.Threading;
7+
using System.Threading.Tasks;
68
using StyleCop.Analyzers.Test.ReadabilityRules;
9+
using TestHelper;
10+
using Xunit;
711

812
public class SA1112CSharp7UnitTests : SA1112UnitTests
913
{
14+
[Fact]
15+
public async Task TestLocalFunctionWithNoParametersClosingParenthesisOnTheNextLineAsync()
16+
{
17+
var testCode = @"
18+
class Foo
19+
{
20+
public void Method()
21+
{
22+
void Bar(
23+
)
24+
{
25+
26+
}
27+
}
28+
}";
29+
var fixedCode = @"
30+
class Foo
31+
{
32+
public void Method()
33+
{
34+
void Bar()
35+
{
36+
37+
}
38+
}
39+
}";
40+
41+
DiagnosticResult expected = this.CSharpDiagnostic().WithLocation(7, 1);
42+
43+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
44+
await this.VerifyCSharpDiagnosticAsync(fixedCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
45+
await this.VerifyCSharpFixAsync(testCode, fixedCode, cancellationToken: CancellationToken.None).ConfigureAwait(false);
46+
}
47+
48+
[Fact]
49+
public async Task TestLocalFunctionWithNoParametersClosingParenthesisOnTheSameLineAsync()
50+
{
51+
var testCode = @"
52+
class Foo
53+
{
54+
public void Method()
55+
{
56+
void Bar()
57+
{
58+
59+
}
60+
}
61+
}";
62+
63+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
64+
}
65+
66+
[Fact]
67+
public async Task TestLocalFunctionWithParametersClosingParenthesisOnTheNextLineAsync()
68+
{
69+
var testCode = @"
70+
class Foo
71+
{
72+
public void Method()
73+
{
74+
void Bar(
75+
string s)
76+
{
77+
78+
}
79+
}
80+
}";
81+
82+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
83+
}
1084
}
1185
}

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1112ClosingParenthesisMustBeOnLineOfOpeningParenthesis.cs

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
namespace StyleCop.Analyzers.ReadabilityRules
55
{
66
using System;
7-
using System.Collections.Generic;
87
using System.Collections.Immutable;
98
using Microsoft.CodeAnalysis;
109
using Microsoft.CodeAnalysis.CSharp;
1110
using Microsoft.CodeAnalysis.CSharp.Syntax;
1211
using Microsoft.CodeAnalysis.Diagnostics;
13-
using SpacingRules;
1412
using StyleCop.Analyzers.Helpers;
13+
using StyleCop.Analyzers.Lightup;
14+
using StyleCop.Analyzers.SpacingRules;
1515

1616
/// <summary>
1717
/// The closing parenthesis or bracket in a call to a C# method or indexer, or the declaration of a method or
@@ -45,6 +45,7 @@ internal class SA1112ClosingParenthesisMustBeOnLineOfOpeningParenthesis : Diagno
4545
new DiagnosticDescriptor(DiagnosticId, Title, MessageFormat, AnalyzerCategory.ReadabilityRules, DiagnosticSeverity.Warning, AnalyzerConstants.EnabledByDefault, Description, HelpLink);
4646

4747
private static readonly Action<SyntaxNodeAnalysisContext> MethodDeclarationAction = HandleMethodDeclaration;
48+
private static readonly Action<SyntaxNodeAnalysisContext> LocalFunctionStatementAction = HandleLocalFunctionStatement;
4849
private static readonly Action<SyntaxNodeAnalysisContext> ConstructorDeclarationAction = HandleConstructorDeclaration;
4950
private static readonly Action<SyntaxNodeAnalysisContext> InvocationExpressionAction = HandleInvocationExpression;
5051
private static readonly Action<SyntaxNodeAnalysisContext> ObjectCreationExpressionAction = HandleObjectCreationExpression;
@@ -60,6 +61,7 @@ public override void Initialize(AnalysisContext context)
6061
context.EnableConcurrentExecution();
6162

6263
context.RegisterSyntaxNodeAction(MethodDeclarationAction, SyntaxKind.MethodDeclaration);
64+
context.RegisterSyntaxNodeAction(LocalFunctionStatementAction, SyntaxKindEx.LocalFunctionStatement);
6365
context.RegisterSyntaxNodeAction(ConstructorDeclarationAction, SyntaxKind.ConstructorDeclaration);
6466
context.RegisterSyntaxNodeAction(InvocationExpressionAction, SyntaxKind.InvocationExpression);
6567
context.RegisterSyntaxNodeAction(ObjectCreationExpressionAction, SyntaxKind.ObjectCreationExpression);
@@ -108,22 +110,25 @@ private static void HandleInvocationExpression(SyntaxNodeAnalysisContext context
108110
private static void HandleConstructorDeclaration(SyntaxNodeAnalysisContext context)
109111
{
110112
var constructotDeclarationSyntax = (ConstructorDeclarationSyntax)context.Node;
111-
HandleBaseMethodDeclaration(context, constructotDeclarationSyntax);
113+
HandleParameterList(context, constructotDeclarationSyntax.ParameterList);
112114
}
113115

114116
private static void HandleMethodDeclaration(SyntaxNodeAnalysisContext context)
115117
{
116118
var methodDeclaration = (MethodDeclarationSyntax)context.Node;
117-
HandleBaseMethodDeclaration(context, methodDeclaration);
119+
HandleParameterList(context, methodDeclaration.ParameterList);
118120
}
119121

120-
private static void HandleBaseMethodDeclaration(
121-
SyntaxNodeAnalysisContext context,
122-
BaseMethodDeclarationSyntax baseMethodDeclarationSyntax)
122+
private static void HandleLocalFunctionStatement(SyntaxNodeAnalysisContext context)
123123
{
124-
var parameterListSyntax =
125-
baseMethodDeclarationSyntax.ParameterList;
124+
var localFunctionStatement = (LocalFunctionStatementSyntaxWrapper)context.Node;
125+
HandleParameterList(context, localFunctionStatement.ParameterList);
126+
}
126127

128+
private static void HandleParameterList(
129+
SyntaxNodeAnalysisContext context,
130+
ParameterListSyntax parameterListSyntax)
131+
{
127132
if (parameterListSyntax != null && !parameterListSyntax.Parameters.Any())
128133
{
129134
if (!parameterListSyntax.OpenParenToken.IsMissing &&

0 commit comments

Comments
 (0)