From 5f003810ca000dce32be5c342d34dc017d63a985 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Hellander?= Date: Wed, 20 Mar 2024 22:16:56 +0100 Subject: [PATCH] Update SA1111 to also check the primary constructor argument list in a base list #3785 --- .../SA1111CSharp9UnitTests.cs | 56 +++++++++++++++++++ ...gParenthesisMustBeOnLineOfLastParameter.cs | 8 +++ 2 files changed, 64 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1111CSharp9UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1111CSharp9UnitTests.cs index c90302f9f..5e0b146ff 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1111CSharp9UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp9/ReadabilityRules/SA1111CSharp9UnitTests.cs @@ -49,6 +49,52 @@ public async Task TestPrimaryConstructorWithoutParameterAsync(string typeKeyword await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); } + [Theory] + [MemberData(nameof(CommonMemberData.ReferenceTypeKeywordsWhichSupportPrimaryConstructors), MemberType = typeof(CommonMemberData))] + [WorkItem(3785, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3785")] + public async Task TestPrimaryConstructorBaseListWithArgumentsAsync(string typeKeyword) + { + var testCode = $@" +{typeKeyword} Foo(int x) +{{ +}} + +{typeKeyword} Bar(int x) : Foo(x + {{|#0:)|}} +{{ +}}"; + + var fixedCode = $@" +{typeKeyword} Foo(int x) +{{ +}} + +{typeKeyword} Bar(int x) : Foo(x) +{{ +}}"; + + var expected = this.GetExpectedResultTestPrimaryConstructorBaseList(); + await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); + } + + [Theory] + [MemberData(nameof(CommonMemberData.ReferenceTypeKeywordsWhichSupportPrimaryConstructors), MemberType = typeof(CommonMemberData))] + [WorkItem(3785, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3785")] + public async Task TestPrimaryConstructorBaseListWithoutArgumentsAsync(string typeKeyword) + { + var testCode = $@" +{typeKeyword} Foo() +{{ +}} + +{typeKeyword} Bar(int x) : Foo( + ) +{{ +}}"; + + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } + protected virtual DiagnosticResult[] GetExpectedResultTestPrimaryConstructorWithParameter() { return new[] @@ -58,5 +104,15 @@ protected virtual DiagnosticResult[] GetExpectedResultTestPrimaryConstructorWith Diagnostic().WithLocation(0), }; } + + protected virtual DiagnosticResult[] GetExpectedResultTestPrimaryConstructorBaseList() + { + return new[] + { + // Diagnostic issued twice because of https://github.com/dotnet/roslyn/issues/70488 + Diagnostic().WithLocation(0), + Diagnostic().WithLocation(0), + }; + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1111ClosingParenthesisMustBeOnLineOfLastParameter.cs b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1111ClosingParenthesisMustBeOnLineOfLastParameter.cs index df560cf69..d348346ec 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1111ClosingParenthesisMustBeOnLineOfLastParameter.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/ReadabilityRules/SA1111ClosingParenthesisMustBeOnLineOfLastParameter.cs @@ -61,6 +61,7 @@ internal class SA1111ClosingParenthesisMustBeOnLineOfLastParameter : DiagnosticA SyntaxKind.ConversionOperatorDeclaration); private static readonly Action TypeDeclarationAction = HandleTypeDeclaration; + private static readonly Action PrimaryConstructorBaseTypeAction = HandlePrimaryConstructorBaseType; private static readonly Action BaseMethodDeclarationAction = HandleBaseMethodDeclaration; private static readonly Action LocalFunctionStatementAction = HandleLocalFunctionStatement; private static readonly Action InvocationExpressionAction = HandleInvocationExpression; @@ -84,6 +85,7 @@ public override void Initialize(AnalysisContext context) context.EnableConcurrentExecution(); context.RegisterSyntaxNodeAction(TypeDeclarationAction, SyntaxKinds.TypeDeclaration); + context.RegisterSyntaxNodeAction(PrimaryConstructorBaseTypeAction, SyntaxKindEx.PrimaryConstructorBaseType); context.RegisterSyntaxNodeAction(BaseMethodDeclarationAction, HandledMethodSyntaxKinds); context.RegisterSyntaxNodeAction(LocalFunctionStatementAction, SyntaxKindEx.LocalFunctionStatement); context.RegisterSyntaxNodeAction(InvocationExpressionAction, SyntaxKind.InvocationExpression); @@ -224,6 +226,12 @@ private static void HandleTypeDeclaration(SyntaxNodeAnalysisContext context) CheckParameterList(context, typeDeclarationSyntax.ParameterList()); } + private static void HandlePrimaryConstructorBaseType(SyntaxNodeAnalysisContext context) + { + var typeDeclarationSyntax = (PrimaryConstructorBaseTypeSyntaxWrapper)context.Node; + CheckArgumentList(context, typeDeclarationSyntax.ArgumentList); + } + private static void CheckParameterList(SyntaxNodeAnalysisContext context, ParameterListSyntax parameterList) { if (parameterList == null || parameterList.IsMissing || !parameterList.Parameters.Any())