Skip to content

Commit

Permalink
Add support for collection expressions in MA0007 (#658)
Browse files Browse the repository at this point in the history
  • Loading branch information
meziantou authored Dec 1, 2023
1 parent bc37dac commit 07c2fea
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 37 deletions.
1 change: 0 additions & 1 deletion src/Meziantou.Analyzer/Internals/ContextExtensions.g.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@


#nullable enable
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
Expand Down
1 change: 0 additions & 1 deletion src/Meziantou.Analyzer/Internals/ContextExtensions.tt
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
<#@ import namespace="System.Linq" #>

#nullable enable
using System;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Diagnostics;
Expand Down
67 changes: 32 additions & 35 deletions src/Meziantou.Analyzer/Rules/CommaAnalyzer.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using System.Collections.Immutable;
using System.Collections.Immutable;
using Meziantou.Analyzer.Internals;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
Expand All @@ -23,10 +22,6 @@ public sealed class CommaAnalyzer : DiagnosticAnalyzer

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(s_rule);

private static readonly Action<SyntaxNodeAnalysisContext> s_handleObjectInitializerAction = HandleObjectInitializer;
private static readonly Action<SyntaxNodeAnalysisContext> s_handleAnonymousObjectInitializerAction = HandleAnonymousObjectInitializer;
private static readonly Action<SyntaxNodeAnalysisContext> s_handleEnumDeclarationAction = HandleEnumDeclaration;

private static readonly ImmutableArray<SyntaxKind> s_objectInitializerKinds = ImmutableArray.Create(SyntaxKind.ObjectInitializerExpression, SyntaxKind.ArrayInitializerExpression, SyntaxKind.CollectionInitializerExpression);

/// <inheritdoc/>
Expand All @@ -35,47 +30,49 @@ public override void Initialize(AnalysisContext context)
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterSyntaxNodeAction(s_handleObjectInitializerAction, s_objectInitializerKinds);
context.RegisterSyntaxNodeAction(s_handleAnonymousObjectInitializerAction, SyntaxKind.AnonymousObjectCreationExpression);
context.RegisterSyntaxNodeAction(s_handleEnumDeclarationAction, SyntaxKind.EnumDeclaration);
context.RegisterSyntaxNodeAction(HandleObjectInitializer, s_objectInitializerKinds);
context.RegisterSyntaxNodeAction(HandleAnonymousObjectInitializer, SyntaxKind.AnonymousObjectCreationExpression);
context.RegisterSyntaxNodeAction(HandleEnumDeclaration, SyntaxKind.EnumDeclaration);
#if CSHARP12_OR_GREATER
context.RegisterSyntaxNodeAction(HandleCollectionExpression, SyntaxKind.CollectionExpression);
#endif
}

private static void HandleEnumDeclaration(SyntaxNodeAnalysisContext context)
private static void HandleSeparatedList<T>(SyntaxNodeAnalysisContext context, SyntaxNode node, SeparatedSyntaxList<T> elements) where T : SyntaxNode
{
var initializer = (EnumDeclarationSyntax)context.Node;
var lastMember = initializer.Members.LastOrDefault();
if (lastMember == null || !initializer.SpansMultipleLines(context.CancellationToken))
{
if (elements.Count == 0)
return;

if (elements.Count == elements.SeparatorCount || !node.SpansMultipleLines(context.CancellationToken))
return;
}

if (initializer.Members.Count != initializer.Members.SeparatorCount)
{
context.ReportDiagnostic(s_rule, lastMember);
}
var lastMember = elements[^1];
context.ReportDiagnostic(s_rule, lastMember);
}

private static void HandleObjectInitializer(SyntaxNodeAnalysisContext context)
#if CSHARP12_OR_GREATER
private void HandleCollectionExpression(SyntaxNodeAnalysisContext context)
{
var initializer = (InitializerExpressionSyntax)context.Node;
if (initializer == null || !initializer.SpansMultipleLines(context.CancellationToken))
return;
var node = (CollectionExpressionSyntax)context.Node;
HandleSeparatedList(context, node, node.Elements);
}
#endif

if (initializer.Expressions.SeparatorCount < initializer.Expressions.Count)
{
context.ReportDiagnostic(s_rule, initializer.Expressions.Last());
}
private static void HandleEnumDeclaration(SyntaxNodeAnalysisContext context)
{
var node = (EnumDeclarationSyntax)context.Node;
HandleSeparatedList(context, node, node.Members);
}

private static void HandleAnonymousObjectInitializer(SyntaxNodeAnalysisContext context)
private static void HandleObjectInitializer(SyntaxNodeAnalysisContext context)
{
var initializer = (AnonymousObjectCreationExpressionSyntax)context.Node;
if (initializer == null || !initializer.SpansMultipleLines(context.CancellationToken))
return;
var node = (InitializerExpressionSyntax)context.Node;
HandleSeparatedList(context, node, node.Expressions);
}

if (initializer.Initializers.SeparatorCount < initializer.Initializers.Count)
{
context.ReportDiagnostic(s_rule, initializer.Initializers.Last());
}
private static void HandleAnonymousObjectInitializer(SyntaxNodeAnalysisContext context)
{
var node = (AnonymousObjectCreationExpressionSyntax)context.Node;
HandleSeparatedList(context, node, node.Initializers);
}
}
36 changes: 36 additions & 0 deletions tests/Meziantou.Analyzer.Test/Rules/CommaAnalyzerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -223,4 +223,40 @@ await CreateProjectBuilder()
.ShouldFixCodeWith(CodeFix)
.ValidateAsync();
}

#if CSHARP12_OR_GREATER
[Fact]
public async Task CollectionExpressionWithoutLeadingComma()
{
const string SourceCode = @"
class TypeName
{
public void Test()
{
int[] a =
[
1,
[||]2
];
}
}";
const string CodeFix = @"
class TypeName
{
public void Test()
{
int[] a =
[
1,
2,
];
}
}";
await CreateProjectBuilder()
.WithLanguageVersion(Microsoft.CodeAnalysis.CSharp.LanguageVersion.CSharp12)
.WithSourceCode(SourceCode)
.ShouldFixCodeWith(CodeFix)
.ValidateAsync();
}
#endif
}

0 comments on commit 07c2fea

Please sign in to comment.