Skip to content

Commit 7fdffd3

Browse files
committed
Merge pull request #2168 from pdelvo/fix-2159
Fix that SA1115 is reported on multi-line parameters/arguments.
2 parents 0bdc1f8 + d50f66a commit 7fdffd3

2 files changed

Lines changed: 72 additions & 122 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.Test/ReadabilityRules/SA1115UnitTests.cs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1244,6 +1244,32 @@ public void TestMethod()
12441244
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
12451245
}
12461246

1247+
[Fact]
1248+
public async Task TestMethodArgumentsWithAttributeAsync()
1249+
{
1250+
var testCode = @"
1251+
[System.AttributeUsage(System.AttributeTargets.Parameter, AllowMultiple = true)]
1252+
public class MyAttribute : System.Attribute
1253+
{
1254+
}
1255+
1256+
class Foo
1257+
{
1258+
public static void DoWork(
1259+
[MyAttribute]
1260+
string param1,
1261+
[MyAttribute]
1262+
string param2,
1263+
[MyAttribute]
1264+
string param3,
1265+
[MyAttribute]
1266+
string param4)
1267+
{
1268+
}
1269+
}";
1270+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
1271+
}
1272+
12471273
protected override IEnumerable<DiagnosticAnalyzer> GetCSharpDiagnosticAnalyzers()
12481274
{
12491275
yield return new SA1115ParameterMustFollowComma();

StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1115ParameterMustFollowComma.cs

Lines changed: 46 additions & 122 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ namespace StyleCop.Analyzers.ReadabilityRules
55
{
66
using System;
77
using System.Collections.Immutable;
8-
using System.Linq;
98
using Microsoft.CodeAnalysis;
109
using Microsoft.CodeAnalysis.CSharp;
1110
using Microsoft.CodeAnalysis.CSharp.Syntax;
@@ -103,91 +102,52 @@ private static void HandleImplicitElementAccess(SyntaxNodeAnalysisContext contex
103102
{
104103
var implicitElementAccess = (ImplicitElementAccessSyntax)context.Node;
105104

106-
AnalyzeArgumentList(context, implicitElementAccess.ArgumentList);
105+
if (implicitElementAccess.ArgumentList != null)
106+
{
107+
AnalyzeSyntaxList(context, implicitElementAccess.ArgumentList.Arguments);
108+
}
107109
}
108110

109111
private static void HandleElementBindingExpression(SyntaxNodeAnalysisContext context)
110112
{
111113
var elementBinding = (ElementBindingExpressionSyntax)context.Node;
112-
113-
AnalyzeArgumentList(context, elementBinding.ArgumentList);
114+
AnalyzeSyntaxList(context, elementBinding.ArgumentList.Arguments);
114115
}
115116

116117
private static void HandleConstructorInitializer(SyntaxNodeAnalysisContext context)
117118
{
118119
var constructorInitializer = (ConstructorInitializerSyntax)context.Node;
119-
120-
AnalyzeArgumentList(context, constructorInitializer.ArgumentList);
120+
AnalyzeSyntaxList(context, constructorInitializer.ArgumentList.Arguments);
121121
}
122122

123123
private static void HandleDelegateDeclaration(SyntaxNodeAnalysisContext context)
124124
{
125125
var delegateDeclaration = (DelegateDeclarationSyntax)context.Node;
126-
127-
AnalyzeParameterList(context, delegateDeclaration.ParameterList);
126+
AnalyzeSyntaxList(context, delegateDeclaration.ParameterList.Parameters);
128127
}
129128

130129
private static void HandleParenthesizedLambdaExpression(SyntaxNodeAnalysisContext context)
131130
{
132131
var lambda = (ParenthesizedLambdaExpressionSyntax)context.Node;
133-
134-
AnalyzeParameterList(context, lambda.ParameterList);
132+
AnalyzeSyntaxList(context, lambda.ParameterList.Parameters);
135133
}
136134

137135
private static void HandleAnonymousMethodExpression(SyntaxNodeAnalysisContext context)
138136
{
139137
var anonymousMethod = (AnonymousMethodExpressionSyntax)context.Node;
140-
141-
AnalyzeParameterList(context, anonymousMethod.ParameterList);
138+
AnalyzeSyntaxList(context, anonymousMethod.ParameterList?.Parameters ?? default(SeparatedSyntaxList<ParameterSyntax>));
142139
}
143140

144141
private static void HandleAttributeList(SyntaxNodeAnalysisContext context)
145142
{
146143
var attributeList = (AttributeListSyntax)context.Node;
147-
148-
if (attributeList.Attributes.Count < 2)
149-
{
150-
return;
151-
}
152-
153-
var previousLine = attributeList.Attributes[0].GetLineSpan().EndLinePosition.Line;
154-
for (int i = 1; i < attributeList.Attributes.Count; i++)
155-
{
156-
var currentAttribute = attributeList.Attributes[i];
157-
var lineSpan = currentAttribute.GetLineSpan();
158-
var currentLine = lineSpan.StartLinePosition.Line;
159-
if (currentLine - previousLine > 1)
160-
{
161-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentAttribute.GetLocation()));
162-
}
163-
164-
previousLine = lineSpan.EndLinePosition.Line;
165-
}
144+
AnalyzeSyntaxList(context, attributeList.Attributes);
166145
}
167146

168147
private static void HandleAttribute(SyntaxNodeAnalysisContext context)
169148
{
170149
var attribute = (AttributeSyntax)context.Node;
171-
172-
if (attribute.ArgumentList == null
173-
|| attribute.ArgumentList.Arguments.Count < 2)
174-
{
175-
return;
176-
}
177-
178-
var previousLine = attribute.ArgumentList.Arguments[0].GetLineSpan().EndLinePosition.Line;
179-
for (int i = 1; i < attribute.ArgumentList.Arguments.Count; i++)
180-
{
181-
var currentArgument = attribute.ArgumentList.Arguments[i];
182-
var lineSpan = currentArgument.GetLineSpan();
183-
var currentLine = lineSpan.StartLinePosition.Line;
184-
if (currentLine - previousLine > 1)
185-
{
186-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentArgument.GetLocation()));
187-
}
188-
189-
previousLine = lineSpan.EndLinePosition.Line;
190-
}
150+
AnalyzeSyntaxList(context, attribute.ArgumentList?.Arguments ?? default(SeparatedSyntaxList<AttributeArgumentSyntax>));
191151
}
192152

193153
private static void HandleArrayCreationExpression(SyntaxNodeAnalysisContext context)
@@ -200,128 +160,92 @@ private static void HandleArrayCreationExpression(SyntaxNodeAnalysisContext cont
200160

201161
foreach (var rankSpecifier in arrayCreation.Type.RankSpecifiers)
202162
{
203-
if (rankSpecifier.Sizes.Count < 2)
204-
{
205-
continue;
206-
}
207-
208-
var previousLine = rankSpecifier.Sizes[0].GetLineSpan().EndLinePosition.Line;
209-
for (int i = 1; i < rankSpecifier.Sizes.Count; i++)
210-
{
211-
var currentSize = rankSpecifier.Sizes[i];
212-
var lineSpan = currentSize.GetLineSpan();
213-
var currentLine = lineSpan.StartLinePosition.Line;
214-
if (currentLine - previousLine > 1)
215-
{
216-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentSize.GetLocation()));
217-
}
218-
219-
previousLine = lineSpan.EndLinePosition.Line;
220-
}
163+
AnalyzeSyntaxList(context, rankSpecifier.Sizes);
221164
}
222165
}
223166

224167
private static void HandleElementAccessExpression(SyntaxNodeAnalysisContext context)
225168
{
226169
var elementAccess = (ElementAccessExpressionSyntax)context.Node;
227170

228-
AnalyzeArgumentList(context, elementAccess.ArgumentList);
171+
if (elementAccess.ArgumentList != null)
172+
{
173+
AnalyzeSyntaxList(context, elementAccess.ArgumentList.Arguments);
174+
}
229175
}
230176

231177
private static void HandleIndexerDeclaration(SyntaxNodeAnalysisContext context)
232178
{
233179
var indexerDeclaration = (IndexerDeclarationSyntax)context.Node;
234180

235-
AnalyzeParameterList(context, indexerDeclaration.ParameterList);
181+
if (indexerDeclaration.ParameterList != null)
182+
{
183+
AnalyzeSyntaxList(context, indexerDeclaration.ParameterList.Parameters);
184+
}
236185
}
237186

238187
private static void HandleObjectCreationExpression(SyntaxNodeAnalysisContext context)
239188
{
240189
var objectCreation = (ObjectCreationExpressionSyntax)context.Node;
241190

242-
AnalyzeArgumentList(context, objectCreation.ArgumentList);
191+
if (objectCreation.ArgumentList != null)
192+
{
193+
AnalyzeSyntaxList(context, objectCreation.ArgumentList.Arguments);
194+
}
243195
}
244196

245197
private static void HandleInvocationExpression(SyntaxNodeAnalysisContext context)
246198
{
247199
var invocation = (InvocationExpressionSyntax)context.Node;
248200

249-
AnalyzeArgumentList(context, invocation.ArgumentList);
201+
if (invocation.ArgumentList != null)
202+
{
203+
AnalyzeSyntaxList(context, invocation.ArgumentList.Arguments);
204+
}
250205
}
251206

252207
private static void HandleBaseMethodDeclaration(SyntaxNodeAnalysisContext context)
253208
{
254209
var constructorDeclaration = (BaseMethodDeclarationSyntax)context.Node;
255210

256-
AnalyzeParameterList(context, constructorDeclaration.ParameterList);
257-
}
258-
259-
private static void AnalyzeArgumentList(SyntaxNodeAnalysisContext context, BaseArgumentListSyntax argumentListSyntax)
260-
{
261-
if (argumentListSyntax == null
262-
|| argumentListSyntax.Arguments.Count < 2)
211+
if (constructorDeclaration.ParameterList != null)
263212
{
264-
return;
265-
}
266-
267-
var previousArgumentLine = argumentListSyntax.Arguments[0].GetLineSpan().EndLinePosition.Line;
268-
for (int i = 1; i < argumentListSyntax.Arguments.Count; i++)
269-
{
270-
var currentArgument = argumentListSyntax.Arguments[i];
271-
int currentArgumentStartLine;
272-
int currentArgumentEndLine;
273-
274-
if (currentArgument.HasLeadingTrivia && IsValidTrivia(currentArgument.GetLeadingTrivia()))
275-
{
276-
var lineSpan = currentArgument.SyntaxTree.GetLineSpan(currentArgument.FullSpan);
277-
currentArgumentStartLine = lineSpan.StartLinePosition.Line;
278-
currentArgumentEndLine = lineSpan.EndLinePosition.Line;
279-
}
280-
else
281-
{
282-
var lineSpan = currentArgument.GetLineSpan();
283-
currentArgumentStartLine = lineSpan.StartLinePosition.Line;
284-
currentArgumentEndLine = lineSpan.EndLinePosition.Line;
285-
}
286-
287-
if (currentArgumentStartLine - previousArgumentLine > 1)
288-
{
289-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentArgument.GetLocation()));
290-
}
291-
292-
previousArgumentLine = currentArgumentEndLine;
213+
AnalyzeSyntaxList(context, constructorDeclaration.ParameterList.Parameters);
293214
}
294215
}
295216

296-
private static void AnalyzeParameterList(SyntaxNodeAnalysisContext context, BaseParameterListSyntax parameterListSyntax)
217+
private static void AnalyzeSyntaxList<TNode>(SyntaxNodeAnalysisContext context, SeparatedSyntaxList<TNode> syntaxList)
218+
where TNode : SyntaxNode
297219
{
298-
if (parameterListSyntax == null
299-
|| parameterListSyntax.Parameters.Count < 2)
220+
if (syntaxList.Count < 2)
300221
{
301222
return;
302223
}
303224

304-
var previousParameterLine = parameterListSyntax.Parameters[0].GetLineSpan().EndLinePosition.Line;
305-
for (int i = 1; i < parameterListSyntax.Parameters.Count; i++)
225+
var previousItemEndLine = syntaxList[0].GetLineSpan().EndLinePosition.Line;
226+
for (int i = 1; i < syntaxList.Count; i++)
306227
{
307-
var currentParameter = parameterListSyntax.Parameters[i];
308-
int currentParameterLine;
228+
var currentItem = syntaxList[i];
229+
FileLinePositionSpan currentSpan;
309230

310-
if (currentParameter.HasLeadingTrivia && IsValidTrivia(currentParameter.GetLeadingTrivia()))
231+
if (currentItem.HasLeadingTrivia && IsValidTrivia(currentItem.GetLeadingTrivia()))
311232
{
312-
currentParameterLine = currentParameter.SyntaxTree.GetLineSpan(currentParameter.FullSpan).StartLinePosition.Line;
233+
currentSpan = currentItem.SyntaxTree.GetLineSpan(currentItem.FullSpan);
313234
}
314235
else
315236
{
316-
currentParameterLine = currentParameter.GetLineSpan().StartLinePosition.Line;
237+
currentSpan = currentItem.GetLineSpan();
317238
}
318239

319-
if (currentParameterLine - previousParameterLine > 1)
240+
int currentItemStartLine = currentSpan.StartLinePosition.Line;
241+
var currentItemEndLine = currentSpan.EndLinePosition.Line;
242+
243+
if (currentItemStartLine - previousItemEndLine > 1)
320244
{
321-
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentParameter.GetLocation()));
245+
context.ReportDiagnostic(Diagnostic.Create(Descriptor, currentItem.GetLocation()));
322246
}
323247

324-
previousParameterLine = currentParameterLine;
248+
previousItemEndLine = currentItemEndLine;
325249
}
326250
}
327251

0 commit comments

Comments
 (0)