Skip to content

Commit b0e5f48

Browse files
author
Dirk Lemstra
committed
SA1413 now also checks enum members.
1 parent 0325dd1 commit b0e5f48

3 files changed

Lines changed: 122 additions & 0 deletions

File tree

StyleCop.Analyzers/StyleCop.Analyzers.CodeFixes/MaintainabilityRules/SA1413CodeFixProvider.cs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@ namespace StyleCop.Analyzers.MaintainabilityRules
1616
using Microsoft.CodeAnalysis.CodeFixes;
1717
using Microsoft.CodeAnalysis.CSharp;
1818
using Microsoft.CodeAnalysis.CSharp.Syntax;
19+
using Microsoft.CodeAnalysis.Text;
1920

2021
/// <summary>
2122
/// Implements a code fix for <see cref="SA1413UseTrailingCommasInMultiLineInitializers"/>.
@@ -68,6 +69,11 @@ private static async Task<Document> GetTransformedDocumentAsync(Document documen
6869
newParent = RewriteAnonymousObjectInitializer((AnonymousObjectCreationExpressionSyntax)parent);
6970
break;
7071

72+
case SyntaxKind.EnumDeclaration:
73+
var text = await document.GetTextAsync(cancellationToken).ConfigureAwait(false);
74+
TextChange textChange = GetEnumMemberTextChange(diagnostic, syntaxRoot);
75+
return document.WithText(text.WithChanges(textChange));
76+
7177
default:
7278
throw new InvalidOperationException("Unknown initializer type: " + parent.Kind());
7379
}
@@ -115,5 +121,11 @@ private static SyntaxNode RewriteAnonymousObjectInitializer(AnonymousObjectCreat
115121
var fixedInitializer = initializer.WithInitializers(newInitializerExpressions);
116122
return fixedInitializer;
117123
}
124+
125+
private static TextChange GetEnumMemberTextChange(Diagnostic diagnostic, SyntaxNode syntaxRoot)
126+
{
127+
var member = (EnumMemberDeclarationSyntax)syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
128+
return new TextChange(diagnostic.Location.SourceSpan, member.ToString() + ",");
129+
}
118130
}
119131
}

StyleCop.Analyzers/StyleCop.Analyzers.Test/MaintainabilityRules/SA1413UnitTests.cs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -425,6 +425,98 @@ void Foo()
425425
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
426426
}
427427

428+
/// <summary>
429+
/// Verifies that the last value of an empty enum does not produce a diagnostic.
430+
/// </summary>
431+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
432+
[Fact]
433+
public async Task VerifyEmptyEnumAsync()
434+
{
435+
var testCode = @"enum EmptyEnum
436+
{
437+
}
438+
";
439+
440+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
441+
}
442+
443+
/// <summary>
444+
/// Verifies that the last value of an enum with a trailing comma does not produce a diagnostic.
445+
/// </summary>
446+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
447+
[Fact]
448+
public async Task VerifyEnumWithTrailingCommaAsync()
449+
{
450+
var testCode = @"enum TestEnum
451+
{
452+
One,
453+
Two,
454+
}
455+
";
456+
457+
await this.VerifyCSharpDiagnosticAsync(testCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
458+
}
459+
460+
/// <summary>
461+
/// Verifies that the last value of an enum without a trailing comma produces a diagnostic.
462+
/// </summary>
463+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
464+
[Fact]
465+
public async Task VerifyEnumWithoutTrailingCommaAsync()
466+
{
467+
var testCode = @"enum TestEnum
468+
{
469+
One,
470+
Two
471+
}
472+
";
473+
474+
var fixedTestCode = @"enum TestEnum
475+
{
476+
One,
477+
Two,
478+
}
479+
";
480+
481+
DiagnosticResult[] expected =
482+
{
483+
this.CSharpDiagnostic().WithLocation(4, 5),
484+
};
485+
486+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
487+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
488+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
489+
}
490+
491+
/// <summary>
492+
/// Verifies that the last value of an enum without a trailing comma produces a diagnostic.
493+
/// </summary>
494+
/// <returns>A <see cref="Task"/> representing the asynchronous unit test.</returns>
495+
[Fact]
496+
public async Task VerifyEnumWithValueWithoutTrailingCommaAsync()
497+
{
498+
var testCode = @"enum TestEnum
499+
{
500+
One = 2
501+
}
502+
";
503+
504+
var fixedTestCode = @"enum TestEnum
505+
{
506+
One = 2,
507+
}
508+
";
509+
510+
DiagnosticResult[] expected =
511+
{
512+
this.CSharpDiagnostic().WithLocation(3, 5),
513+
};
514+
515+
await this.VerifyCSharpDiagnosticAsync(testCode, expected, CancellationToken.None).ConfigureAwait(false);
516+
await this.VerifyCSharpDiagnosticAsync(fixedTestCode, EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false);
517+
await this.VerifyCSharpFixAsync(testCode, fixedTestCode).ConfigureAwait(false);
518+
}
519+
428520
/// <inheritdoc/>
429521
protected override CodeFixProvider GetCSharpCodeFixProvider()
430522
{

StyleCop.Analyzers/StyleCop.Analyzers/MaintainabilityRules/SA1413UseTrailingCommasInMultiLineInitializers.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.MaintainabilityRules
55
{
66
using System;
77
using System.Collections.Immutable;
8+
using System.Linq;
89
using Helpers;
910
using Microsoft.CodeAnalysis;
1011
using Microsoft.CodeAnalysis.CSharp;
@@ -73,6 +74,23 @@ public override void Initialize(AnalysisContext context)
7374

7475
context.RegisterSyntaxNodeAction(HandleObjectInitializerAction, ObjectInitializerKinds);
7576
context.RegisterSyntaxNodeAction(HandleAnonymousObjectInitializerAction, SyntaxKind.AnonymousObjectCreationExpression);
77+
context.RegisterSyntaxNodeAction(HandleEnumMemberDeclarationAction, SyntaxKind.EnumDeclaration);
78+
}
79+
80+
private static void HandleEnumMemberDeclarationAction(SyntaxNodeAnalysisContext context)
81+
{
82+
var initializer = (EnumDeclarationSyntax)context.Node;
83+
var lastMember = initializer.Members.LastOrDefault();
84+
if (lastMember == null)
85+
{
86+
return;
87+
}
88+
89+
var commas = initializer.ChildNodesAndTokens().OfType<SyntaxNodeOrToken>().Where(token => token.IsKind(SyntaxKind.CommaToken));
90+
if (initializer.Members.Count() != commas.Count())
91+
{
92+
context.ReportDiagnostic(Diagnostic.Create(Descriptor, lastMember.GetLocation()));
93+
}
7694
}
7795

7896
private static void HandleObjectInitializer(SyntaxNodeAnalysisContext context)

0 commit comments

Comments
 (0)