StyleBro vs StyleCop.Analyzers¶
For a team deciding whether to switch. Measured numbers only; each one says where it comes from. As of
2026-10-05 (StyleBro's main; StyleCop.Analyzers 1.2.0-beta.556, its latest release).
Summary¶
| StyleCop.Analyzers 1.2.0-beta.556 | StyleBro (main, 2026-10-05) |
|
|---|---|---|
Fixes under dotnet format |
Many rules have no fix, no Fix All, or a fix that misbehaves there (below) | Every rule has a fix with Fix All; one run converges |
| StyleCop's 197 diagnostics | All | 106 by StyleBro rules, 45 by the .NET SDK's rules, 42 dropped by design, 4 variants or not applicable |
| Rules beyond StyleCop | None | 26 (most from Roslynator, Meziantou, Sonar or StyleCop's own tracker) |
| Analyzer time, Newtonsoft.Json (242 files) | 1,291-2,171 ms (182 analyzers) | 411-687 ms (66 analyzers); 3.1-3.4x faster in each of 3 runs (Speed) |
| StyleCop's open bugs on the replaced rules | 54 checked | 34 not shared, 8 shared (7 fixed, 1 kept on purpose), 12 not applicable or the same by design |
| Moving a StyleCop-clean repo | (the starting point) | Files changed after stylebro-migrate --write + dotnet format: Polly 1, OpenTelemetry 1, a private app 7; only 1 of those 9 is a StyleBro fix (Migration) |
| Baseline (fail only on new violations) | No | Yes (stylebro-migrate baseline) |
| Multi-targeted projects | Not measured | Fix All merges each target framework's copy itself (no conflict markers in Newtonsoft.Json, 8 frameworks); stylebro-migrate format works around the SDK's IDE0055 crash |
| Release status | 1.2.0-beta.556 (beta for years; last stable 1.1.118) | 0.7.0-alpha.1 on nuget.org (129 rules), a prerelease |
What it is¶
StyleBro is a set of Roslyn analyzers whose every rule has a code fix that dotnet format applies, with Fix All, so
dotnet format fixes everything StyleBro reports. Fixes are deterministic and idempotent: after one run, a second run
changes nothing (the CI check for this repository and the real-world check both test that). Where a fix
could be unsafe (it would change behavior, lose a comment, or depend on #if code), StyleBro skips the case instead of
reporting something it can't fix.
Formatting the SDK already handles (spacing, indentation, using order, modifier order, ...) isn't duplicated: StyleBro's
preset sets the SDK's options and stylebro-migrate init turns the SDK rules on.
StyleCop's fixes, run under dotnet format, from differences-from-stylecop.md:
- No fix, or none that works there: SA1108, SA1114, SA1115, SA1117, SA1125, SA1612/SA1613/SA1620/SA1621/SA1627; SA1141's fix has no Fix All and SA1142's throws.
- Renames: the naming rules (SA1300-SA1314) lower or remove only the first letter or prefix (
MAX_VALUE->MAXVALUE), and underdotnet formatapply part of the renames per run or nothing; SA1316 renames the declaration only, so every use breaks the build. - Fixes that lose or mangle code: SA1132 keeps attributes on the first field only (
[Obsolete]disappears from the others); SA1501/SA1502 write{at column 1 in nested blocks and CRLF into LF files; SA1504 collapses or expands the accessors of every property in the project the same way; SA1633 deletes a plain comment header (license text) when it writes the XML header. - More runs: nested initializers need several runs for SA1413 (StyleCop issue #3953: three); SA1120 and SA1103 leave work for the next run.
Coverage¶
StyleCop 1.2 has 197 diagnostics (stylecop-mapping.md, backlog.md):
| Diagnostics | ||
|---|---|---|
| StyleBro rule | 106 | 92 BRO rules replace them; differences listed in differences-from-stylecop.md |
| .NET SDK rule | 45 | Spacing, indentation, using order, modifier order and more: the preset sets the options, stylebro-migrate init the severities |
| Dropped: no safe automatic fix | 32 | skipped-rules.md |
| Dropped: StyleCop never reports it | 10 | SA1109, SA1126, SA1301, SA1409, SA1628, SA1630-SA1632, SA1644, SA1650 |
| Variants, not applicable | 4 | SA1119_p, SX1309S, SA0001, SA0002 |
Why the 32 are dropped (skipped-rules.md has every one, with what revisiting would take):
- They need text only a person can write. Missing documentation (SA1601, SA1602, SA1604-SA1611, SA1614-SA1616,
SA1618, SA1619, SA1622): the only automatic fix is placeholder text, which satisfies the rule and documents nothing
(SA1600 alone: ~28,000 findings in the three surveyed StyleCop repos). StyleBro adds
/// <inheritdoc/>to overrides and interface implementations, where that's a real fix (BRO1601). - They need code moved between files or files renamed (SA1402, SA1403, SA1649), which
dotnet formatcan't do. - They have no deterministic fix: SA1118 (where to break a multi-line argument), SA1401 (fields should be private), SA1404-SA1406 (justification and message text), SA1414 (tuple element names), SA1625, SA1645-SA1648 and others.
Speed¶
Measured 2026-10-05 with scripts/benchmark in compare mode on Newtonsoft.Json's main
project (Src/Newtonsoft.Json at 52fa3ae, 242 files): both analyzer DLLs load into one process and take turns on
freshly parsed sources (which goes first alternates, garbage collection before each), single-threaded, compiler
telemetry per analyzer, each analyzer's fastest of 20-30 runs, summed. StyleCop: StyleCop.Analyzers.dll from the
StyleCop.Analyzers.Unstable 1.2.0.556 package (what StyleCop.Analyzers 1.2.0-beta.556 installs). StyleBro: a Release
build of src/StyleBro.Analyzers from main (fb430c4). Each tool runs with its default rule set and no
configuration.
| Run | StyleCop.Analyzers (182 analyzers, 197 diagnostics) | StyleBro (66 analyzers, 118 rules) | Ratio |
|---|---|---|---|
| 1 | 2,171 ms | 687 ms | 3.2x |
| 2 | 1,467 ms | 435 ms | 3.4x |
| 3 | 1,291 ms | 411 ms | 3.1x |
Other builds were running on the machine at the same time, so the totals swing by up to 70 % between runs; the alternation exposes both tools to the same noise, and the ratio held. StyleCop's slowest: SA1121 (159 ms), SA1101 (143 ms), SA1027 (109 ms). StyleBro's: FieldNamingAnalyzer (72 ms), DocumentationAnalyzer (66 ms), CommentSpacingAnalyzer (59 ms) (run 1).
Not the same work: StyleCop's number includes spacing and indentation rules that StyleBro leaves to the SDK (IDE0055 and
the other rules init turns on), whose cost isn't in StyleBro's number. In a real build analyzers run concurrently with
the compiler, so the wall-clock difference is smaller: a private app built in the same time with and without StyleBro
(9-12 s either way), Newtonsoft.Json 8.4 -> ~11.8 s with every StyleBro rule (CLAUDE.md, 2026-10-02, alpha.8). An
earlier figure of 1,671 ms for StyleCop came from the benchmark before it parsed fresh sources per run and isn't
comparable.
Correctness¶
- StyleCop's open bugs (differences-from-stylecop.md,
2026-10-04): every open issue on a rule StyleBro replaces was read; the 54 that describe behavior StyleBro could share
were run against StyleBro. 34 aren't shared, for example: SA1201's fix moves a method into
#if DEBUG(#1588), SA1309's rename doesn't compile (#2939), SA1135 crashes onusing X = string;(#3882), fixes write CRLF into LF files (#3656). 8 were shared: 7 fixed, 1 kept like StyleCop by the owner's decision. - Parity with StyleCop: 42 parity sets run both tools on edge-case files and compare positions and fixed output;
every difference must be a documented deviation (scripts/stylecop-survey). StyleCop's
unreleased
masterwas compared too: where it fixed a gap, StyleBro follows it. - Real-world check on every pull request: every rule on 8 public repositories (FFMpegCore, Polly, OpenTelemetry,
Newtonsoft.Json, Serilog, Jellyfin, FluentValidation, CsvHelper;
scripts/realworld/repos.psd1). A pull request fails on an analyzer crash, a new compile error, a merge conflict marker, more than 2dotnet formatruns to converge, or a test that passed on the untouched code and fails after the fixes. Running the tests found what compiling didn't: renames that broke reflection and serialization, member sorting that changed serialized JSON order. Those cases are now skipped; one known failure is left (Newtonsoft.Json'sMemberSearchFlagsserializes an attribute-less class's private fields by reflection, in declaration order). - Mutation testing: 320 guards (
scripts/mutation/entries/) are each broken on purpose; a test must fail for every one. - Unit tests: 842, including every example on every rule page (before compiles and is reported, one Fix All pass gives exactly the after, the after is clean).
Migration¶
stylebro-migrate (migrating.md) reads a repository's StyleCop setup (rulesets, global configs,
.editorconfig files, stylecop.json, the StyleCop version) and writes StyleBro and SDK settings that match it, carries
#pragma warning disable SA..., [SuppressMessage] and <NoWarn> suppressions over to the replacing rules, and
reports the StyleCop rules nothing enforces any more.
Files dotnet format changes after stylebro-migrate --write on repositories that were StyleCop-clean (CLAUDE.md,
"Migration re-measured with the SDK replacements", 2026-10-03; scripts/stylecop-survey/Measure-MigrationDelta.ps1):
| Repository | Files changed | What |
|---|---|---|
| Polly | 1 | A file plain dotnet format already breaks (conflict markers in a multi-targeted file), not StyleBro |
| OpenTelemetry | 1 | A line ending in a file with mixed line endings |
| A private app | 7 | 6 line-ending-only, 1 BRO1104 on a target-typed new(), which the older StyleCop version used there misses (1.2 reports it) |
The rules StyleCop doesn't have are turned off by the migration, so they change nothing there.
- Baseline (baseline.md):
stylebro-migrate baselinerecords today's violations; the build, the IDE anddotnet formatignore them and only new or edited lines count. On FFMpegCore with every rule: 820 violations on 759 lines baselined, then 0 StyleBro errors in the build anddotnet format --verify-no-changesclean (2026-10-02). Whitespace formatting can't be baselined. - Multi-targeted projects: StyleBro's Fix All merges each target framework's copy of a file itself, so its fixes
write no conflict markers (Newtonsoft.Json, 8 frameworks). The SDK's IDE0055 fix crashes plain
dotnet formatthere (reported upstream as dotnet/roslyn#86000 and dotnet/roslyn#86001);stylebro-migrate formatrunsdotnet formatonce per target framework (Serilog: 505 IDE0055 findings -> 0 in one run, 2026-10-03; ci.md).
Beyond StyleCop¶
26 rules StyleCop doesn't have (differences-from-stylecop.md,
chosen in beyond-stylecop.md from Roslynator, Meziantou, Sonar and StyleCop's issue tracker),
each with a fix like every other rule. For example: null checks in one form (BRO1133), operator placement when an
expression wraps (BRO1520), split call chains one call per line (BRO1523), no $/@ a plain string doesn't need
(BRO1138), generic crefs in braces (BRO1617), no else after a jump (BRO1143, off by default). The preset turns 22
of them on; stylebro-migrate turns them off, so migrating changes nothing until you opt in.
stylebro-migrate init --modernize (modernizing.md) turns on the SDK's own rules for newer C# and
APIs in tiers, and StyleBro's multi-target guard hides a newer-API rule in a project where one target framework lacks
the API.
Limits¶
What StyleBro doesn't do:
- Report missing documentation (SA1600 and friends), except overrides and implementations. If you rely on SA1600 to make people write docs, keep StyleCop's SA1600 for reporting or use the compiler's CS1591.
- Move types into their own files or rename files (SA1402, SA1403, SA1649).
- Line length. Neither does StyleCop; there's no deterministic fix (where to break).
- Baseline whitespace formatting.
- Rename everything it reports: a field whose name appears in a string elsewhere (reflection, serialization) keeps its name and its warning (Newtonsoft.Json: 49 such names, 2026-10-01).
Where it deliberately differs from StyleCop's defaults (differences-from-stylecop.md):
no this. prefix, usings outside the namespace, region removal (BRO1112) and namespace-name casing (BRO1312) off, and the
XML file header only once a company is configured. stylebro-migrate keeps a team's own settings instead.
Checked and not checked:
- Visual Studio 2022 (17.13): build, light bulb fixes, Fix All and live squiggles checked by the owner (2026-10-05, backlog.md). Rider: not checked.
- Needs Roslyn 4.8 (.NET 8 SDK, Visual Studio 17.8) or newer.
- Prerelease: 0.7.0-alpha.1 on nuget.org; versions and behavior can still change between prereleases.