Skip to content

Commit

Permalink
Update SA1111 to also check the parameter list in primary constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
bjornhellander committed Jan 30, 2024
1 parent 91b5ad8 commit 6cafeff
Show file tree
Hide file tree
Showing 4 changed files with 91 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,20 @@

namespace StyleCop.Analyzers.Test.CSharp11.ReadabilityRules
{
using Microsoft.CodeAnalysis.Testing;
using StyleCop.Analyzers.Test.CSharp10.ReadabilityRules;
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
StyleCop.Analyzers.ReadabilityRules.SA1111ClosingParenthesisMustBeOnLineOfLastParameter,
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;

public partial class SA1111CSharp11UnitTests : SA1111CSharp10UnitTests
{
protected override DiagnosticResult[] GetExpectedResultTestPrimaryConstructor()
{
return new[]
{
Diagnostic().WithLocation(0),
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,66 @@

namespace StyleCop.Analyzers.Test.CSharp9.ReadabilityRules
{
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Testing;
using StyleCop.Analyzers.Lightup;
using StyleCop.Analyzers.Test.CSharp8.ReadabilityRules;
using Xunit;
using static StyleCop.Analyzers.Test.Verifiers.StyleCopCodeFixVerifier<
StyleCop.Analyzers.ReadabilityRules.SA1111ClosingParenthesisMustBeOnLineOfLastParameter,
StyleCop.Analyzers.SpacingRules.TokenSpacingCodeFixProvider>;

public partial class SA1111CSharp9UnitTests : SA1111CSharp8UnitTests
{
public static IEnumerable<object[]> TypeKeywordsWhichSupportPrimaryConstructors
{
get
{
yield return new[] { "record" };

if (LightupHelpers.SupportsCSharp10)
{
yield return new[] { "record class" };
yield return new[] { "record struct" };
}

if (LightupHelpers.SupportsCSharp12)
{
yield return new[] { "class" };
yield return new[] { "struct" };
}
}
}

[Theory]
[MemberData(nameof(TypeKeywordsWhichSupportPrimaryConstructors))]
[WorkItem(3785, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3785")]
public async Task TestPrimaryConstructorAsync(string typeKeyword)
{
var testCode = $@"
{typeKeyword} Foo(int x
{{|#0:)|}}
{{
}}";

var fixedCode = $@"
{typeKeyword} Foo(int x)
{{
}}";

var expected = this.GetExpectedResultTestPrimaryConstructor();
await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false);
}

protected virtual DiagnosticResult[] GetExpectedResultTestPrimaryConstructor()
{
return new[]
{
Diagnostic().WithLocation(0),
Diagnostic().WithLocation(0),
};
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
namespace StyleCop.Analyzers.Lightup;

using System;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

internal static class TypeDeclarationSyntaxExtensions
Expand All @@ -19,6 +20,20 @@ static TypeDeclarationSyntaxExtensions()

public static ParameterListSyntax? ParameterList(this TypeDeclarationSyntax syntax)
{
if (!LightupHelpers.SupportsCSharp12)
{
// Prior to C# 12, the ParameterList property in RecordDeclarationSyntax did not override a base method.
switch (syntax.Kind())
{
case SyntaxKindEx.RecordDeclaration:
case SyntaxKindEx.RecordStructDeclaration:
return ((RecordDeclarationSyntaxWrapper)syntax).ParameterList;

default:
return null;
}
}

return ParameterListAccessor(syntax);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,7 @@ internal class SA1111ClosingParenthesisMustBeOnLineOfLastParameter : DiagnosticA
SyntaxKind.OperatorDeclaration,
SyntaxKind.ConversionOperatorDeclaration);

private static readonly Action<SyntaxNodeAnalysisContext> TypeDeclarationAction = HandleTypeDeclaration;
private static readonly Action<SyntaxNodeAnalysisContext> BaseMethodDeclarationAction = HandleBaseMethodDeclaration;
private static readonly Action<SyntaxNodeAnalysisContext> LocalFunctionStatementAction = HandleLocalFunctionStatement;
private static readonly Action<SyntaxNodeAnalysisContext> InvocationExpressionAction = HandleInvocationExpression;
Expand All @@ -82,6 +83,7 @@ public override void Initialize(AnalysisContext context)
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();

context.RegisterSyntaxNodeAction(TypeDeclarationAction, SyntaxKinds.TypeDeclaration);
context.RegisterSyntaxNodeAction(BaseMethodDeclarationAction, HandledMethodSyntaxKinds);
context.RegisterSyntaxNodeAction(LocalFunctionStatementAction, SyntaxKindEx.LocalFunctionStatement);
context.RegisterSyntaxNodeAction(InvocationExpressionAction, SyntaxKind.InvocationExpression);
Expand Down Expand Up @@ -216,6 +218,12 @@ private static void HandleLocalFunctionStatement(SyntaxNodeAnalysisContext conte
CheckParameterList(context, localFunctionStatementSyntax.ParameterList);
}

private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context)
{
var typeDeclarationSyntax = (TypeDeclarationSyntax)context.Node;
CheckParameterList(context, typeDeclarationSyntax.ParameterList());
}

private static void CheckParameterList(SyntaxNodeAnalysisContext context, ParameterListSyntax parameterList)
{
if (parameterList == null || parameterList.IsMissing || !parameterList.Parameters.Any())
Expand Down

0 comments on commit 6cafeff

Please sign in to comment.