Skip to content

Commit b2ea895

Browse files
Merge pull request #4 from MattFromRVA/SA1001_Change
Skip Warnings for Commas After Conditional Directives
2 parents d322b2c + cc13c5a commit b2ea895

File tree

3 files changed

+144
-1
lines changed

3 files changed

+144
-1
lines changed

StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1001UnitTests.cs

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -349,6 +349,114 @@ public void TestMethod()
349349
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
350350
}
351351

352+
[Fact]
353+
[WorkItem(3816, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3816")]
354+
public async Task TestCommaFollowingPreprocessorDirectiveAsync()
355+
{
356+
var testCode = @"
357+
interface IFormattable {}
358+
interface ISpanFormattable {}
359+
partial struct Money : IFormattable
360+
#if true
361+
, ISpanFormattable
362+
#endif
363+
{
364+
}
365+
";
366+
367+
var expected = DiagnosticResult.EmptyDiagnosticResults;
368+
369+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
370+
}
371+
372+
[Fact]
373+
public async Task TestCommaFollowingElifDirectiveAsync()
374+
{
375+
var testCode = @"
376+
interface IFormattable {}
377+
interface ISpanFormattable {}
378+
partial struct Money : IFormattable
379+
#if false
380+
#elif true
381+
, ISpanFormattable
382+
#endif
383+
{
384+
}
385+
";
386+
387+
var expected = DiagnosticResult.EmptyDiagnosticResults;
388+
389+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
390+
}
391+
392+
[Fact]
393+
public async Task TestCommaFollowingElseDirectiveAsync()
394+
{
395+
var testCode = @"
396+
interface IFormattable {}
397+
interface ISpanFormattable {}
398+
partial struct Money : IFormattable
399+
#if false
400+
#else
401+
, ISpanFormattable
402+
#endif
403+
{
404+
}
405+
";
406+
407+
var expected = DiagnosticResult.EmptyDiagnosticResults;
408+
409+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
410+
}
411+
412+
[Fact]
413+
public async Task TestCommaFollowingEndIfDirectiveAsync()
414+
{
415+
var testCode = @"
416+
interface IFormattable {}
417+
interface ISpanFormattable {}
418+
partial struct Money : IFormattable
419+
#if false
420+
#endif
421+
, ISpanFormattable
422+
{
423+
}
424+
";
425+
426+
var expected = DiagnosticResult.EmptyDiagnosticResults;
427+
428+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
429+
}
430+
431+
[Fact]
432+
public async Task TestCommaNotFollowingDirectiveAsync()
433+
{
434+
var testCode = @"
435+
interface IFormattable {}
436+
interface ISpanFormattable {}
437+
partial struct Money : IFormattable
438+
{|#0:,|} ISpanFormattable
439+
{
440+
}
441+
";
442+
443+
var fixedCode = @"
444+
interface IFormattable {}
445+
interface ISpanFormattable {}
446+
partial struct Money : IFormattable,
447+
ISpanFormattable
448+
{
449+
}
450+
";
451+
452+
var expected = new[]
453+
{
454+
Diagnostic().WithLocation(0).WithArguments(" not", "preceded"),
455+
};
456+
457+
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
458+
}
459+
352460
private Task TestCommaInStatementOrDeclAsync(string originalStatement, DiagnosticResult expected, string fixedStatement)
353461
{
354462
return this.TestCommaInStatementOrDeclAsync(originalStatement, new[] { expected }, fixedStatement);

StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1001CommasMustBeSpacedCorrectly.cs

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
7676
return;
7777
}
7878

79+
// Check if the comma follows a conditional preprocessor directive.
80+
bool followsDirective = token.HasLeadingTrivia && IsPrecededByDirectiveTrivia(token.LeadingTrivia);
81+
7982
// check for a following space
8083
bool missingFollowingSpace = true;
8184

@@ -102,7 +105,7 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
102105
}
103106
}
104107

105-
if (token.IsFirstInLine() || token.IsPrecededByWhitespace(context.CancellationToken))
108+
if (!followsDirective && (token.IsFirstInLine() || token.IsPrecededByWhitespace(context.CancellationToken)))
106109
{
107110
// comma should{ not} be {preceded} by whitespace
108111
context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemovePrecedingPreserveLayout, " not", "preceded"));
@@ -120,5 +123,30 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
120123
context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveFollowing, " not", "followed"));
121124
}
122125
}
126+
127+
private static bool IsPrecededByDirectiveTrivia(SyntaxTriviaList triviaList)
128+
{
129+
int triviaIndex = triviaList.Count - 1;
130+
while (triviaIndex >= 0)
131+
{
132+
switch (triviaList[triviaIndex].Kind())
133+
{
134+
case SyntaxKind.WhitespaceTrivia:
135+
triviaIndex--;
136+
break;
137+
138+
case SyntaxKind.IfDirectiveTrivia:
139+
case SyntaxKind.ElifDirectiveTrivia:
140+
case SyntaxKind.ElseDirectiveTrivia:
141+
case SyntaxKind.EndIfDirectiveTrivia:
142+
return true;
143+
144+
default:
145+
return false;
146+
}
147+
}
148+
149+
return false;
150+
}
123151
}
124152
}

documentation/SA1001.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ A comma should be followed by a single space, except in the following cases.
2828
* A comma may appear at the end of a line
2929
* A comma should not be followed by a space when used in an open generic type in a `typeof` expression
3030
* A comma is part of a string interpolation alignment component. For example:`$"{x,3}"`
31+
* A comma follows a conditional preprocessor directive (#if, #elif, #else, #endif). For example:
32+
```csharp
33+
partial struct Money : IFormattable
34+
#if !NETSTANDARD
35+
, ISpanFormattable
36+
#endif
37+
```
3138

3239
A comma should never be preceded by a space or appear as the first token on a line.
3340

0 commit comments

Comments
 (0)