diff --git a/ChangeLog.md b/ChangeLog.md index eaf9396daa..28312b640d 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Fix analyzer [RCS1264](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1264) ([PR](https://github.com/dotnet/roslynator/pull/1666)) - Fix analyzer [RCS1229](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1229) ([PR](https://github.com/dotnet/roslynator/pull/1667)) - Fix analyzer [RCS1250](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1250) ([PR](https://github.com/dotnet/roslynator/pull/1652) by @aihnatiuk) +- Fix analyzer [RCS1260](https://josefpihrt.github.io/docs/roslynator/analyzers/RCS1260) ([PR](https://github.com/dotnet/roslynator/pull/1668)) ## [4.13.1] - 2025-02-23 diff --git a/src/Analyzers.CodeFixes/CSharp/CodeFixes/AddOrRemoveTrailingCommaCodeFixProvider.cs b/src/Analyzers.CodeFixes/CSharp/CodeFixes/AddOrRemoveTrailingCommaCodeFixProvider.cs index 0275c60d6d..5ac46f2749 100644 --- a/src/Analyzers.CodeFixes/CSharp/CodeFixes/AddOrRemoveTrailingCommaCodeFixProvider.cs +++ b/src/Analyzers.CodeFixes/CSharp/CodeFixes/AddOrRemoveTrailingCommaCodeFixProvider.cs @@ -36,6 +36,9 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) SyntaxKind.ObjectInitializerExpression, SyntaxKind.CollectionInitializerExpression, SyntaxKind.EnumDeclaration, +#if ROSLYN_4_7 + SyntaxKind.CollectionExpression, +#endif SyntaxKind.AnonymousObjectCreationExpression))) { return; @@ -69,6 +72,33 @@ public override async Task RegisterCodeFixesAsync(CodeFixContext context) context.RegisterCodeFix(codeAction, diagnostic); } } +#if ROSLYN_4_7 + if (node is CollectionExpressionSyntax collectionExpression) + { + SeparatedSyntaxList elements = collectionExpression.Elements; + + int count = elements.Count; + + if (count == elements.SeparatorCount) + { + CodeAction codeAction = CodeAction.Create( + "Remove comma", + ct => RemoveTrailingComma(document, elements.GetSeparator(count - 1), ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + } + else + { + CodeAction codeAction = CodeAction.Create( + "Add comma", + ct => AddTrailingComma(document, elements.Last(), ct), + GetEquivalenceKey(diagnostic)); + + context.RegisterCodeFix(codeAction, diagnostic); + } + } +#endif else if (node is AnonymousObjectCreationExpressionSyntax objectCreation) { SeparatedSyntaxList initializers = objectCreation.Initializers; diff --git a/src/Analyzers/CSharp/Analysis/AddOrRemoveTrailingCommaAnalyzer.cs b/src/Analyzers/CSharp/Analysis/AddOrRemoveTrailingCommaAnalyzer.cs index ed84c787cd..9ab9fc3e9a 100644 --- a/src/Analyzers/CSharp/Analysis/AddOrRemoveTrailingCommaAnalyzer.cs +++ b/src/Analyzers/CSharp/Analysis/AddOrRemoveTrailingCommaAnalyzer.cs @@ -32,6 +32,9 @@ public override void Initialize(AnalysisContext context) context.RegisterSyntaxNodeAction(f => AnalyzeEnumDeclaration(f), SyntaxKind.EnumDeclaration); context.RegisterSyntaxNodeAction(f => AnalyzeAnonymousObjectCreationExpression(f), SyntaxKind.AnonymousObjectCreationExpression); +#if ROSLYN_4_7 + context.RegisterSyntaxNodeAction(f => AnalyzeCollectionExpression(f), SyntaxKind.CollectionExpression); +#endif context.RegisterSyntaxNodeAction( f => AnalyzeInitializerExpression(f), @@ -169,6 +172,51 @@ private static void AnalyzeAnonymousObjectCreationExpression(SyntaxNodeAnalysisC } } +#if ROSLYN_4_7 + private static void AnalyzeCollectionExpression(SyntaxNodeAnalysisContext context) + { + TrailingCommaStyle style = context.GetTrailingCommaStyle(); + + if (style == TrailingCommaStyle.None) + return; + + var objectCreation = (CollectionExpressionSyntax)context.Node; + + SeparatedSyntaxList elements = objectCreation.Elements; + + if (!elements.Any()) + return; + + int count = elements.Count; + int separatorCount = elements.SeparatorCount; + + if (count == separatorCount) + { + if (style == TrailingCommaStyle.Omit) + { + ReportRemove(context, elements.GetSeparator(count - 1)); + } + else if (style == TrailingCommaStyle.OmitWhenSingleLine + && elements.IsSingleLine(cancellationToken: context.CancellationToken)) + { + ReportRemove(context, elements.GetSeparator(count - 1)); + } + } + else if (separatorCount == count - 1) + { + if (style == TrailingCommaStyle.Include) + { + ReportAdd(context, elements.Last()); + } + else if (style == TrailingCommaStyle.OmitWhenSingleLine + && !elements.IsSingleLine(cancellationToken: context.CancellationToken)) + { + ReportAdd(context, elements.Last()); + } + } + } +#endif + private static void ReportAdd(SyntaxNodeAnalysisContext context, SyntaxNode lastNode) { DiagnosticHelpers.ReportDiagnostic( diff --git a/src/Tests/Analyzers.Tests/RCS1260AddOrRemoveTrailingCommaTests.cs b/src/Tests/Analyzers.Tests/RCS1260AddOrRemoveTrailingCommaTests.cs index fc527cb0c6..f479191234 100644 --- a/src/Tests/Analyzers.Tests/RCS1260AddOrRemoveTrailingCommaTests.cs +++ b/src/Tests/Analyzers.Tests/RCS1260AddOrRemoveTrailingCommaTests.cs @@ -329,4 +329,48 @@ void M() } """, options: Options.AddConfigOption(ConfigOptionKeys.TrailingCommaStyle, ConfigOptionValues.TrailingCommaStyle_OmitWhenSingleLine)); } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.AddOrRemoveTrailingComma)] + public async Task Test_CollectionExpression_Omit() + { + await VerifyDiagnosticAndFixAsync(""" +class C +{ + void M() + { + int[] x = [1, 2, 3[|,|]]; + } +} +""", """ +class C +{ + void M() + { + int[] x = [1, 2, 3]; + } +} +""", options: Options.AddConfigOption(ConfigOptionKeys.TrailingCommaStyle, ConfigOptionValues.TrailingCommaStyle_Omit)); + } + + [Fact, Trait(Traits.Analyzer, DiagnosticIdentifiers.AddOrRemoveTrailingComma)] + public async Task Test_CollectionExpression_OmitWhenSingleLine() + { + await VerifyDiagnosticAndFixAsync(""" +class C +{ + void M() + { + int[] x = [1, 2, 3[|,|]]; + } +} +""", """ + class C + { + void M() + { + int[] x = [1, 2, 3]; + } + } + """, options: Options.AddConfigOption(ConfigOptionKeys.TrailingCommaStyle, ConfigOptionValues.TrailingCommaStyle_OmitWhenSingleLine)); + } }