Skip to content

Fix collection expression bracket layout in SA1500 and SA1137 - #4396

Merged
AArnott merged 3 commits into
masterfrom
aarnott-fictional-lamp
Nov 3, 2026
Merged

AArnott merged 3 commits into
masterfrom
aarnott-fictional-lamp

Conversation

@AArnott

@AArnott AArnott commented Nov 3, 2026

Copy link
Copy Markdown
Contributor

Multiline C# 12 collection expressions could leave the closing bracket beside the last element, even after adding a trailing comma. SA1500 did not inspect collection expressions, and SA1137 skipped closing-bracket alignment when the opening bracket followed an assignment or other code.

Changes

  • Extend SA1500 to require the first element to start after the opening bracket's line and the closing bracket to start on its own line. Keep opening brackets after assignments or other code valid.
  • Extend the SA1500 code fix to preserve comments and handle nested collections and Fix All.
  • Make SA1137 align a standalone closing bracket with the indentation of the opening bracket's line, rather than its column after preceding code.
  • Update English, Czech, Russian, and Simplified Chinese rule documentation.

Behavior change: Multiline collection expressions now produce SA1500 diagnostics for shared element/bracket lines, and SA1137 diagnostics for misaligned closing brackets after inline opening brackets. Single-line collections remain valid. SA1413 and its code fix are unchanged in this PR.

Validation

Regression tests first reproduced the missing SA1500 diagnostics and the missing SA1137 diagnostic for inline opening brackets before the corresponding analyzer changes. The reported opening-bracket/first-element layout already triggered SA1137 for its misaligned closing bracket; a regression preserves that behavior.

  • Debug build of the C# 15 test project and its dependencies: zero warnings and errors.
  • Complete SA1500 and SA1137 suites passed in the base and C# 12, 13, 14, and 15 projects.
  • Coverage includes nested Fix All, optional trailing commas, comments, spread elements, tabs, LF/CRLF, and valid layouts.
  • Targeted documentation-source localization checks passed. The full documentation suite requires generated site/status artifacts not present locally.

Performance

SA1500 adds a narrowly registered collection-expression callback using syntax/token line checks only. SA1137's additional source-text indentation scan is limited to multiline collection expressions with inline opening brackets and standalone closing brackets. No semantic-model calls or whole-tree walks are added; code without collection expressions retains its existing analysis path. Performance was not benchmarked.

AArnott and others added 2 commits November 3, 2026 12:15
Require elements to start after the opening bracket and closing brackets to start their own lines. Preserve inline opening brackets, comments, and nested Fix All behavior.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Anchor closing bracket indentation to the opening bracket's line when it follows an assignment or return. Preserve standalone bracket checks and add regressions for comments, tabs, and line endings.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The code fix can introduce SA1137 by indenting a nested collection’s opening bracket without adjusting its matching closing bracket, requiring an indentation fix and regression coverage.

1 open issue
What changed in this PR

This PR extends StyleCop’s SA1500 and SA1137 rules to handle multiline C# 12 collection-expression brackets while preserving valid inline opening brackets and single-line collections.

Changes:

  • Add collection-expression layout checks and extend the SA1500 code fix.
  • Align standalone closing brackets with the opening line’s indentation, with regression coverage for layout and trivia handling.
  • Update both rules’ documentation in English, Czech, Russian, and Simplified Chinese.
File Description
test/​StyleCop.Analyzers.Test.CSharp12/​ReadabilityRules/​SA1137CSharp12UnitTests.cs Tests inline-opening bracket alignment and valid layouts.
test/​StyleCop.Analyzers.Test.CSharp12/​LayoutRules/​SA1500CSharp12UnitTests.cs Adds collection layout, comment preservation, and nested Fix All tests.
src/​StyleCop.Analyzers/​ReadabilityRules/​SA1137ElementsShouldHaveTheSameIndentation.cs Checks closing-bracket indentation after inline openings.
src/​StyleCop.Analyzers/​LayoutRules/​SA1500BracesForMultiLineStatementsMustNotShareLine.cs Adds multiline collection-expression bracket checks.
src/​StyleCop.Analyzers.CodeFixes/​LayoutRules/​SA1500CodeFixProvider.cs Extends bracket placement and nested indentation fixes.
documentation/​zh-cn/​SA1500.md Documents collection layout in Simplified Chinese.
documentation/​zh-cn/​SA1137.md Documents bracket alignment in Simplified Chinese.
documentation/​SA1500.md Explains collection-expression layout requirements.
documentation/​SA1137.md Explains collection bracket and element indentation.
documentation/​ru-ru/​SA1500.md Documents collection layout in Russian.
documentation/​ru-ru/​SA1137.md Documents bracket alignment in Russian.
documentation/​cs-cz/​SA1500.md Documents collection layout in Czech.
documentation/​cs-cz/​SA1137.md Documents bracket alignment in Czech.

Review effort: Balanced

@codecov

codecov Bot commented Nov 3, 2026 •

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 98.99749% with 4 lines in your changes missing coverage. Please review.
✅ Project coverage is 97.64%. Comparing base (d4fdfe5) to head (4bff882).
⚠️ Report is 4 commits behind head on master.

Additional details and impacted files
@@           Coverage Diff            @@
##           master    #4396    +/-   ##
========================================
  Coverage   97.64%   97.64%            
========================================
  Files        1349     1350     +1     
  Lines      153329   153725   +396     
  Branches     5272     5286    +14     
========================================
+ Hits       149719   150110   +391     
  Misses       2280     2280            
- Partials     1330     1335     +5     
🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

Keep matching standalone closing brackets aligned when moving nested collection opening brackets, even when the inner collection has no SA1500 diagnostic. Preserve comments and single-line collections.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

The code fix can introduce SA1137 by leaving closing brackets misaligned when moving mixed initializer/collection expressions or nested cast/parenthesized collections, affecting both single fixes and Fix All.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Realign closing brackets inside moved cast expressions

src/​StyleCop.Analyzers.CodeFixes/​LayoutRules/​SA1500CodeFixProvider.cs:156

For int[][] values = [(int[])[ with the element and both closing brackets on later lines, and both brackets aligned at four spaces, fixing the outer [ moves (int[])[ to eight spaces but leaves the inner ] at four. Both the single fix and Fix All introduce SA1137 because this adjustment only handles an immediately following [, not a collection inside the moved cast or parenthesized expression. Realign matching closing brackets for those moved collection openings, and add cast/parenthesized regressions.

Medium severity Fix All misaligns closing bracket after initializer moves

src/​StyleCop.Analyzers.CodeFixes/​LayoutRules/​SA1500CodeFixProvider.cs:264

For int[][] values = new int[][] {[ with 1], on the next line and }; below it, Fix All moves [ one indentation level inward but leaves the separately fixed ] at the original indentation, introducing SA1137. The closing-bracket calculation accounts for a preceding [ but not the initializer { being fixed. Account for the initializer's movement when calculating bracket indentation, and add a mixed initializer/collection Fix All regression.

1 resolved since last review

Review effort: Balanced

@AArnott
AArnott marked this pull request as ready for review November 3, 2026 20:19
@AArnott
AArnott enabled auto-merge November 3, 2026 20:20
@AArnott
AArnott merged commit 986988b into master Nov 3, 2026
29 of 30 checks passed
@AArnott
AArnott deleted the aarnott-fictional-lamp branch November 3, 2026 20:21
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants