Skip to content

Fix SYSLIB1045 code fixer generating duplicate MyRegex names across partial class declarations#124698

Merged
danmoseley merged 8 commits intodotnet:mainfrom
danmoseley:fix/77409-codefixer-duplicate-namesc
Apr 10, 2026
Merged

Fix SYSLIB1045 code fixer generating duplicate MyRegex names across partial class declarations#124698
danmoseley merged 8 commits intodotnet:mainfrom
danmoseley:fix/77409-codefixer-duplicate-namesc

Conversation

@danmoseley
Copy link
Copy Markdown
Member

@danmoseley danmoseley commented Feb 21, 2026

Fixes #77409

Problem

When the SYSLIB1045 BatchFixer applies multiple code fixes concurrently to separate partial class declarations, each fix independently checks existing members via the semantic model. Since all fixers see the original compilation (before any fix is applied), they all conclude MyRegex is available and generate duplicate property names, causing CS0756.

Fix

In UpgradeToGeneratedRegexCodeFixer.CreateGeneratedRegexProperty, after finding the first available name via the semantic model, the new CountPrecedingRegexCallSites helper scans all DeclaringSyntaxReferences of the containing type for Regex constructor/static-method call sites that would also generate new property names. These are sorted deterministically (by file path, then span position). The current node's index in that sorted list determines how many names to skip, giving each concurrent fixer a unique name.

Test

Added CodeFixerGeneratesUniqueNamesAcrossPartialClassDeclarations — two new Regex(...) calls in separate partial class declarations of the same type, verifying MyRegex and MyRegex1 are generated. Verified the test fails without the fix (both declarations produce MyRegex).

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes issue #77409 where the SYSLIB1045 code fixer (which converts Regex constructor calls to GeneratedRegex) generates duplicate property names when applied to multiple partial class declarations via batch fixing. The root cause is that concurrent batch fixers all see the original compilation state before any fixes are applied, causing them to independently conclude that the same name (e.g., "MyRegex") is available.

The PR also includes two unrelated changes: a performance optimization using SetSearchValues for the regex interpreter, and a regression test for character class encoding validation.

Changes:

  • Adds CountPrecedingRegexCallSites helper to deterministically order all Regex call sites across partial declarations by file path and position, allowing each concurrent fixer to offset its name generation
  • Implements SetSearchValues optimization in the regex interpreter for vectorized character class matching
  • Adds validation for character class encoding before calling GetSetChars to prevent IndexOutOfRangeException on malformed input

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 4 comments.

Show a summary per file
File Description
src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs Adds CountPrecedingRegexCallSites helper and name offset logic to prevent duplicate names in batch fixing
src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/UpgradeToGeneratedRegexAnalyzerTests.cs Adds test validating unique name generation across partial class declarations
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreterCode.cs Adds SetSearchValues precomputation and character class encoding validation (unrelated optimization)
src/libraries/System.Text.RegularExpressions/src/System/Text/RegularExpressions/RegexInterpreter.cs Uses SetSearchValues for vectorized Set opcode matching (unrelated optimization)
src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/Regex.Match.Tests.cs Adds regression test for Multi literal resembling character class encoding (unrelated)

@danmoseley danmoseley force-pushed the fix/77409-codefixer-duplicate-namesc branch 2 times, most recently from 259abc1 to 3e46fc1 Compare February 21, 2026 05:04
Copilot AI review requested due to automatic review settings February 21, 2026 05:04
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated no new comments.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

Copilot AI review requested due to automatic review settings February 21, 2026 05:16
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 2 out of 2 changed files in this pull request and generated 2 comments.

@danmoseley danmoseley force-pushed the fix/77409-codefixer-duplicate-namesc branch from ec91456 to ca22fda Compare February 21, 2026 05:24
Copilot AI review requested due to automatic review settings February 21, 2026 05:29
@danmoseley danmoseley force-pushed the fix/77409-codefixer-duplicate-namesc branch from ca22fda to ed09d48 Compare February 21, 2026 05:29
@danmoseley danmoseley force-pushed the fix/77409-codefixer-duplicate-namesc branch from ed09d48 to b83f949 Compare February 21, 2026 05:34
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.

…artial class declarations

When the BatchFixer applies multiple fixes concurrently, each fix sees the
original compilation and independently picks the same first-available name.
This causes CS0756 when two partial declarations of the same class both
contain Regex calls that need fixing.

The fix scans all partial declarations of the containing type for Regex call
sites that would generate new property names, orders them deterministically
(by file path, then position), and offsets the generated name by the current
node's index in that list.

Fixes dotnet#77409

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Extract fixable method names into shared FixableMethodNames set on the
analyzer, referenced by both the analyzer and the fixer. Add test
verifying Regex.Escape calls don't inflate the generated name offset.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley danmoseley force-pushed the fix/77409-codefixer-duplicate-namesc branch from 8af55cd to c9e46b8 Compare February 21, 2026 06:19
@danmoseley
Copy link
Copy Markdown
Member Author

Feedback addressed.

@danmoseley
Copy link
Copy Markdown
Member Author

/ba-g unrelated infra issues

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

Field and property initializer call sites are fixed via
ConvertFieldToGeneratedRegexProperty / ConvertPropertyToGeneratedRegexProperty,
which keep the original member name and don't compete for MyRegex* names.
Counting them inflated the name offset for method-body fixes (e.g., producing
MyRegex1 when MyRegex was available).

Updated AnayzerSupportsMultipleDiagnostics test to include a field initializer
between two method-body calls to cover this scenario.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@danmoseley
Copy link
Copy Markdown
Member Author

@eiriktsarpalis I reviewed yours to the regex source gen. Do you want to do this one? It's much simpler.

@danmoseley
Copy link
Copy Markdown
Member Author

/ba-g unrelated

@danmoseley danmoseley enabled auto-merge (squash) April 2, 2026 16:41
@danmoseley
Copy link
Copy Markdown
Member Author

@stephentoub you looked at this a while back -- could you sign off?

- Rename FixableMethodNames to s_fixableMethodNames (naming convention)
- Simplify name generation loop to avoid throwaway strings
- Extract shared IsFixableRegexOperation to eliminate duplication between analyzer and fixer
- Refactor analyzer to use IsFixableRegexOperation, removing AnalyzeInvocation/AnalyzeObjectCreation/GetMethodSymbolHash

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copilot AI review requested due to automatic review settings April 9, 2026 16:42
…pleDiagnostics

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a SYSLIB1045 code-fix naming collision that can occur when Roslyn’s BatchFixer applies fixes concurrently across multiple partial declarations of the same type, leading to duplicate generated member names (e.g., multiple MyRegex properties).

Changes:

  • Update the code fixer’s generated-member naming logic to derive a deterministic per-callsite suffix across all partial declarations of the containing type.
  • Refactor analyzer/fixer shared “fixable Regex call” logic into UpgradeToGeneratedRegexAnalyzer.IsFixableRegexOperation (and make ValidateParameters reusable).
  • Add/extend functional tests to validate unique naming across partial declarations (same file and separate files) and relevant edge cases.
Show a summary per file
File Description
src/libraries/System.Text.RegularExpressions/tests/FunctionalTests/UpgradeToGeneratedRegexAnalyzerTests.cs Adds/updates tests validating unique generated names across partial declarations and related naming edge cases.
src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexCodeFixer.cs Implements deterministic unique naming via CountPrecedingRegexCallSites and adjusts member insertion formatting.
src/libraries/System.Text.RegularExpressions/gen/UpgradeToGeneratedRegexAnalyzer.cs Centralizes “fixable Regex operation” logic for reuse by the code fixer and analyzer.

Copilot's findings

  • Files reviewed: 3/3 changed files
  • Comments generated: 0 new

@danmoseley
Copy link
Copy Markdown
Member Author

danmoseley commented Apr 10, 2026

/ba-g unrelated wasm

@danmoseley danmoseley merged commit 063c8ea into dotnet:main Apr 10, 2026
83 of 94 checks passed
@danmoseley danmoseley deleted the fix/77409-codefixer-duplicate-namesc branch April 10, 2026 02:37
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

SYSLIB1045 Use GeneratedRegex auto-correct causes CS0756 multiple defining declarations

3 participants