From c74913b7a3de2d217aa0618a4ff71e3e9ccb95f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Hellander?= Date: Sun, 20 Jul 2025 09:44:08 +0200 Subject: [PATCH 1/2] Updated SA1008OpeningParenthesisMustBeSpacedCorrectly to disallow a leading space before a lambda in a collection expression #3931 --- .../SpacingRules/SA1008CSharp12UnitTests.cs | 22 +++++++++++++++++++ ...OpeningParenthesisMustBeSpacedCorrectly.cs | 3 ++- 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs index f0544bc37..0567790f2 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs @@ -5,6 +5,7 @@ namespace StyleCop.Analyzers.Test.CSharp12.SpacingRules { using System.Threading; using System.Threading.Tasks; + using Microsoft.CodeAnalysis.Testing; using StyleCop.Analyzers.Test.CSharp11.SpacingRules; using Xunit; @@ -28,5 +29,26 @@ public async Task TestTupleUsingAliasAsync() var expected = Diagnostic(DescriptorPreceded).WithLocation(0); await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); } + + [Fact] + [WorkItem(3931, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3931")] + public async Task TestParenthesizedLambdaInCollectionExpressionAsync() + { + var testCode = @" +class TestClass +{ + private System.Action[] actions = [ [|(|]) => {}]; +} +"; + + var fixedCode = @" +class TestClass +{ + private System.Action[] actions = [() => {}]; +} +"; + + await VerifyCSharpFixAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, fixedCode, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1008OpeningParenthesisMustBeSpacedCorrectly.cs b/StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1008OpeningParenthesisMustBeSpacedCorrectly.cs index 4f3a67fe2..be2f1051d 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1008OpeningParenthesisMustBeSpacedCorrectly.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers/SpacingRules/SA1008OpeningParenthesisMustBeSpacedCorrectly.cs @@ -248,7 +248,8 @@ private static void HandleOpenParenToken(SyntaxTreeAnalysisContext context, Synt case SyntaxKind.ParameterList: var partOfLambdaExpression = token.Parent.Parent.IsKind(SyntaxKind.ParenthesizedLambdaExpression); - haveLeadingSpace = partOfLambdaExpression; + var startOfCollectionExpression = prevToken.IsKind(SyntaxKind.OpenBracketToken) && prevToken.Parent.IsKind(SyntaxKindEx.CollectionExpression); + haveLeadingSpace = partOfLambdaExpression && !startOfCollectionExpression; break; case SyntaxKindEx.TupleType: From f76adf3eff8d956845625030f28ba258557bf917 Mon Sep 17 00:00:00 2001 From: Sam Harwell Date: Tue, 25 Nov 2025 14:08:03 -0600 Subject: [PATCH 2/2] Add additional test cases --- .../SpacingRules/SA1008CSharp12UnitTests.cs | 62 +++++++++++++++++++ .../SpacingRules/SA1008UnitTests.cs | 28 +++++++++ 2 files changed, 90 insertions(+) diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs index 0567790f2..2e740fdc5 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test.CSharp12/SpacingRules/SA1008CSharp12UnitTests.cs @@ -50,5 +50,67 @@ class TestClass await VerifyCSharpFixAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, fixedCode, CancellationToken.None).ConfigureAwait(false); } + + [Fact] + [WorkItem(3931, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3931")] + public async Task TestLambdaAfterCommaInCollectionExpressionAsync() + { + var testCode = @" +class TestClass +{ + private System.Func[] functions = [(x, y) => x + y,{|#0:(|}x, y) => x - y]; +} +"; + + var fixedCode = @" +class TestClass +{ + private System.Func[] functions = [(x, y) => x + y, (x, y) => x - y]; +} +"; + + var expected = Diagnostic(DescriptorPreceded).WithLocation(0); + await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(3931, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3931")] + public async Task TestLambdaAfterSpreadInCollectionExpressionAsync() + { + var testCode = @" +class TestClass +{ + private static System.Func[] existing = [(x, y) => x + y]; + private System.Func[] functions = [..existing,{|#0:(|}x, y) => x - y]; +} +"; + + var fixedCode = @" +class TestClass +{ + private static System.Func[] existing = [(x, y) => x + y]; + private System.Func[] functions = [..existing, (x, y) => x - y]; +} +"; + + var expected = Diagnostic(DescriptorPreceded).WithLocation(0); + await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); + } + + [Fact] + [WorkItem(3931, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3931")] + public async Task TestLambdaWithBracketOnPreviousLineAsync() + { + var testCode = @" +class TestClass +{ + private System.Func[] functions = [ + (x, y) => x + y + ]; +} +"; + + await VerifyCSharpDiagnosticAsync(testCode, DiagnosticResult.EmptyDiagnosticResults, CancellationToken.None).ConfigureAwait(false); + } } } diff --git a/StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1008UnitTests.cs b/StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1008UnitTests.cs index ef93d0f0f..43925ae15 100644 --- a/StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1008UnitTests.cs +++ b/StyleCop.Analyzers/StyleCop.Analyzers.Test/SpacingRules/SA1008UnitTests.cs @@ -1895,6 +1895,34 @@ public void TestMethod1() await VerifyCSharpFixAsync(testCode, expectedDiagnostics, fixedTestCode, CancellationToken.None).ConfigureAwait(false); } + [Fact] + [WorkItem(3931, "https://github.com/DotNetAnalyzers/StyleCopAnalyzers/issues/3931")] + public async Task TestLambdaInCollectionInitializerAsync() + { + var testCode = @" +using System; +using System.Collections.Generic; + +class TestClass +{ + private List> actions = new List>() {{|#0:(|}x, y) => { } }; +} +"; + + var fixedCode = @" +using System; +using System.Collections.Generic; + +class TestClass +{ + private List> actions = new List>() { (x, y) => { } }; +} +"; + + var expected = Diagnostic(DescriptorPreceded).WithLocation(0); + await VerifyCSharpFixAsync(testCode, expected, fixedCode, CancellationToken.None).ConfigureAwait(false); + } + /// /// Verifies that multi-line comments are handled properly. ///