Skip to content

Commit 523a357

Browse files
committed
Updated code to check for trailing whitespace and extra space. Updated and added Tests
1 parent 78c2c16 commit 523a357

File tree

2 files changed

+211
-10
lines changed

2 files changed

+211
-10
lines changed

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

Lines changed: 184 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ namespace StyleCop.Analyzers.Test.SpacingRules
88
using System;
99
using System.Threading;
1010
using System.Threading.Tasks;
11+
using Microsoft;
1112
using Microsoft.CodeAnalysis.Testing;
1213
using StyleCop.Analyzers.SpacingRules;
1314
using Xunit;
@@ -358,7 +359,7 @@ interface IFormattable {}
358359
interface ISpanFormattable {}
359360
360361
partial struct Money : IFormattable
361-
#if !NETSTANDARD
362+
#if true
362363
, ISpanFormattable
363364
#endif
364365
{
@@ -370,6 +371,188 @@ partial struct Money : IFormattable
370371
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
371372
}
372373

374+
[Fact]
375+
public async Task TestCommaFollowingElifDirectiveAsync()
376+
{
377+
var testCode = @"
378+
interface IFormattable {}
379+
interface ISpanFormattable {}
380+
381+
partial struct Money : IFormattable
382+
#if false
383+
#elif true
384+
, ISpanFormattable
385+
#endif
386+
{
387+
}
388+
";
389+
390+
var expected = DiagnosticResult.EmptyDiagnosticResults;
391+
392+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
393+
}
394+
395+
[Fact]
396+
public async Task TestCommaFollowingElseDirectiveAsync()
397+
{
398+
var testCode = @"
399+
interface IFormattable {}
400+
interface ISpanFormattable {}
401+
402+
partial struct Money : IFormattable
403+
#if false
404+
#else
405+
, ISpanFormattable
406+
#endif
407+
{
408+
}
409+
";
410+
411+
var expected = DiagnosticResult.EmptyDiagnosticResults;
412+
413+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
414+
}
415+
416+
[Fact]
417+
public async Task TestCommaFollowingEndIfDirectiveAsync()
418+
{
419+
var testCode = @"
420+
interface IFormattable {}
421+
interface ISpanFormattable {}
422+
423+
partial struct Money : IFormattable
424+
#if false
425+
#endif
426+
, ISpanFormattable
427+
{
428+
}
429+
";
430+
431+
var expected = DiagnosticResult.EmptyDiagnosticResults;
432+
433+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
434+
}
435+
436+
[Fact]
437+
public async Task TestCommaNotFollowingDirectiveAsync()
438+
{
439+
var testCode = @"
440+
interface IFormattable {}
441+
interface ISpanFormattable {}
442+
443+
partial struct Money : IFormattable
444+
, ISpanFormattable
445+
{
446+
}
447+
";
448+
449+
var expected = new[]
450+
{
451+
DiagnosticResult.CompilerWarning("SA1001").WithSpan(6, 5, 6, 6).WithArguments(" not", "preceded"),
452+
};
453+
454+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
455+
}
456+
457+
[Fact]
458+
public async Task TestSpaceBeforeCommaFollowingIfDirectiveAsync()
459+
{
460+
var testCode = @"
461+
interface IFormattable {}
462+
interface ISpanFormattable {}
463+
464+
partial struct Money : IFormattable
465+
#if true
466+
467+
, ISpanFormattable
468+
#endif
469+
{
470+
}
471+
";
472+
473+
var expected = new[]
474+
{
475+
DiagnosticResult.CompilerWarning("SA1001").WithSpan(8, 5, 8, 6).WithArguments(" not", "preceded"),
476+
};
477+
478+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
479+
}
480+
481+
[Fact]
482+
public async Task TestSpaceBeforeCommaFollowingElifDirectiveAsync()
483+
{
484+
var testCode = @"
485+
interface IFormattable {}
486+
interface ISpanFormattable {}
487+
488+
partial struct Money : IFormattable
489+
#if false
490+
#elif true
491+
492+
, ISpanFormattable
493+
#endif
494+
{
495+
}
496+
";
497+
498+
var expected = new[]
499+
{
500+
DiagnosticResult.CompilerWarning("SA1001").WithSpan(9, 5, 9, 6).WithArguments(" not", "preceded"),
501+
};
502+
503+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
504+
}
505+
506+
[Fact]
507+
public async Task TestSpaceBeforeCommaFollowingElseDirectiveAsync()
508+
{
509+
var testCode = @"
510+
interface IFormattable {}
511+
interface ISpanFormattable {}
512+
513+
partial struct Money : IFormattable
514+
#if false
515+
#else
516+
517+
, ISpanFormattable
518+
#endif
519+
{
520+
}
521+
";
522+
523+
var expected = new[]
524+
{
525+
DiagnosticResult.CompilerWarning("SA1001").WithSpan(9, 5, 9, 6).WithArguments(" not", "preceded"),
526+
};
527+
528+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
529+
}
530+
531+
[Fact]
532+
public async Task TestSpaceBeforeCommaFollowingEndIfDirectiveAsync()
533+
{
534+
var testCode = @"
535+
interface IFormattable {}
536+
interface ISpanFormattable {}
537+
538+
partial struct Money : IFormattable
539+
#if false
540+
#elif true
541+
#endif
542+
543+
, ISpanFormattable
544+
{
545+
}
546+
";
547+
548+
var expected = new[]
549+
{
550+
DiagnosticResult.CompilerWarning("SA1001").WithSpan(10, 5, 10, 6).WithArguments(" not", "preceded"),
551+
};
552+
553+
await VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
554+
}
555+
373556
private Task TestCommaInStatementOrDeclAsync(string originalStatement, DiagnosticResult expected, string fixedStatement)
374557
{
375558
return this.TestCommaInStatementOrDeclAsync(originalStatement, new[] { expected }, fixedStatement);

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

Lines changed: 27 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -78,14 +78,7 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
7878
}
7979

8080
// Check if the comma follows a conditional preprocessor directive
81-
if (token.HasLeadingTrivia && token.LeadingTrivia.Any(trivia =>
82-
trivia.IsKind(SyntaxKind.IfDirectiveTrivia) ||
83-
trivia.IsKind(SyntaxKind.ElifDirectiveTrivia) ||
84-
trivia.IsKind(SyntaxKind.ElseDirectiveTrivia) ||
85-
trivia.IsKind(SyntaxKind.EndIfDirectiveTrivia)))
86-
{
87-
return;
88-
}
81+
bool followsDirective = token.HasLeadingTrivia && IsPrecededByDirectiveTrivia(token.LeadingTrivia);
8982

9083
// check for a following space
9184
bool missingFollowingSpace = true;
@@ -113,7 +106,7 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
113106
}
114107
}
115108

116-
if (token.IsFirstInLine() || token.IsPrecededByWhitespace(context.CancellationToken))
109+
if (!followsDirective && (token.IsFirstInLine() || token.IsPrecededByWhitespace(context.CancellationToken)))
117110
{
118111
// comma should{ not} be {preceded} by whitespace
119112
context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemovePrecedingPreserveLayout, " not", "preceded"));
@@ -131,5 +124,30 @@ private static void HandleCommaToken(SyntaxTreeAnalysisContext context, SyntaxTo
131124
context.ReportDiagnostic(Diagnostic.Create(Descriptor, token.GetLocation(), TokenSpacingProperties.RemoveFollowing, " not", "followed"));
132125
}
133126
}
127+
128+
private static bool IsPrecededByDirectiveTrivia(SyntaxTriviaList triviaList)
129+
{
130+
int triviaIndex = triviaList.Count - 1;
131+
while (triviaIndex >= 0)
132+
{
133+
switch (triviaList[triviaIndex].Kind())
134+
{
135+
case SyntaxKind.WhitespaceTrivia:
136+
triviaIndex--;
137+
break;
138+
139+
case SyntaxKind.IfDirectiveTrivia:
140+
case SyntaxKind.ElifDirectiveTrivia:
141+
case SyntaxKind.ElseDirectiveTrivia:
142+
case SyntaxKind.EndIfDirectiveTrivia:
143+
return true;
144+
145+
default:
146+
return false;
147+
}
148+
}
149+
150+
return false;
151+
}
134152
}
135153
}

0 commit comments

Comments
 (0)