Skip to content

Fix SYSLIB1045: Convert Regex to GeneratedRegex source generators#46708

Draft
crutkas wants to merge 2 commits intomainfrom
fix/SYSLIB1045-generated-regex
Draft

Fix SYSLIB1045: Convert Regex to GeneratedRegex source generators#46708
crutkas wants to merge 2 commits intomainfrom
fix/SYSLIB1045-generated-regex

Conversation

@crutkas
Copy link
Copy Markdown
Member

@crutkas crutkas commented Apr 1, 2026

Convert ~115 Regex instances across 38 files to use [GeneratedRegex] source-generated regular expressions for compile-time code generation and improved performance. Dynamic patterns that cannot be source-generated are left as-is with inline comments explaining why.

Summary of the Pull Request

Convert ~115 Regex instances across 38 files to use [GeneratedRegex] source-generated regular expressions for compile-time code generation and improved performance. Classes containing [GeneratedRegex] methods have been made partial as required. Dynamic patterns whose values are constructed at runtime (and therefore cannot be source-generated) are left unchanged with inline comments. Also fixes a build error in WebSearch/Main.cs where an SA1500 StyleCop violation (brace on same line as multi-line condition) and a misplaced using System.Text.RegularExpressions; directive were introduced during the conversion.

PR Checklist

  • Closes: #xxx
  • Communication: I've discussed this with core contributors already. If the work hasn't been agreed, this work might be rejected
  • Tests: Added/updated and all pass
  • Localization: All end-user-facing strings can be localized
  • Dev docs: Added/updated
  • New binaries: Added on the required places
  • Documentation updated: If checked, please file a pull request on our docs repo and link it here: #xxx

Detailed Description of the Pull Request / Additional comments

  • All classes containing [GeneratedRegex] methods are declared partial.
  • Patterns built from runtime values (e.g. culture-specific separators, dynamic function names) are kept as new Regex(pattern) with comments explaining why they cannot be source-generated.
  • Fixed SA1500 ("Braces for multi-line statements should not share line") in WebSearch/Main.cs where the opening brace of an if block was accidentally placed on the same line as the last condition when shortening the Regex.IsMatch call.
  • Fixed misplaced using System.Text.RegularExpressions; directive in WebSearch/Main.cs (moved into the System usings group).

Validation Steps Performed

  • Verified all [GeneratedRegex]-annotated methods are in partial classes with correct private static partial Regex signatures.
  • Confirmed no constant-pattern new Regex(...) calls remain in converted files.
  • Confirmed the SA1500 brace formatting fix restores the original multi-line if structure in WebSearch/Main.cs.

Convert 115 Regex instances across 38 files to use [GeneratedRegex]
source-generated regular expressions for compile-time code generation
and improved performance.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@crutkas crutkas force-pushed the fix/SYSLIB1045-generated-regex branch from 71d4711 to 3c897e1 Compare April 1, 2026 15:32
@crutkas
Copy link
Copy Markdown
Member Author

crutkas commented Apr 1, 2026

@copilot fix build errors

Copy link
Copy Markdown
Contributor

Copilot AI commented Apr 1, 2026

@copilot fix build errors

Fixed in commit 4829b51. The build was failing due to two issues introduced in WebSearch/Main.cs during the GeneratedRegex conversion:

  1. SA1500 violation: When replacing the long System.Text.RegularExpressions.Regex.IsMatch(...) call with UriSchemeRegex().IsMatch(input)), the opening { of the if block accidentally ended up on the same line as the last condition of the multi-line statement — violating SA1500 (which is treated as an error due to TreatWarningsAsErrors=true).

  2. Using directive order: The added using System.Text.RegularExpressions; was placed in the non-System usings group instead of within the System usings group.

Warning

Firewall rules blocked me from connecting to one or more addresses (expand for details)

I tried to connect to the following addresses, but was blocked by firewall rules:

  • dev.azure.com
    • Triggering command: /usr/bin/curl curl -s REDACTED (dns block)
    • Triggering command: /usr/bin/curl curl -v REDACTED (dns block)
    • Triggering command: /home/REDACTED/work/_temp/ghcca-node/node/bin/node /home/REDACTED/work/_temp/ghcca-node/node/bin/node --enable-source-maps /home/REDACTED/work/_temp/copilot-developer-action-main/dist/index.js (dns block)
  • o3svsblobprodcus318.vsblob.vsassets.io
    • Triggering command: /usr/bin/dotnet dotnet build --no-restore (dns block)

If you need me to access, download, or install something from one of these locations, you can either:

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 2, 2026

@check-spelling-bot Report

🔴 Please review

See the 📂 files view, the 📜action log, or 📝 job summary for details.

Unrecognized words (2)

traies
udit

These words are not needed and should be removed IPREVIEW ITHUMBNAIL LPCFHOOKPROC LUMA MAXDWORD MRT suntimes timespan VSync

To accept these unrecognized words as correct and remove the previously acknowledged and now absent words, you could run the following commands

... in a clone of the git@github.com:microsoft/PowerToys.git repository
on the fix/SYSLIB1045-generated-regex branch (ℹ️ how do I use this?):

curl -s -S -L 'https://raw.githubusercontent.com/check-spelling/check-spelling/c635c2f3f714eec2fcf27b643a1919b9a811ef2e/apply.pl' |
perl - 'https://github.com/microsoft/PowerToys/actions/runs/23872413895/attempts/2' &&
git commit -m 'Update check-spelling metadata'
Warnings ⚠️ (1)

See the 📂 files view, the 📜action log, or 📝 job summary for details.

⚠️ Warnings Count
⚠️ ignored-expect-variant 5

See ⚠️ Event descriptions for more information.

If the flagged items are 🤯 false positives

If items relate to a ...

  • binary file (or some other file you wouldn't want to check at all).

    Please add a file path to the excludes.txt file matching the containing file.

    File paths are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your files.

    ^ refers to the file's path from the root of the repository, so ^README\.md$ would exclude README.md (on whichever branch you're using).

  • well-formed pattern.

    If you can write a pattern that would match it,
    try adding it to the patterns.txt file.

    Patterns are Perl 5 Regular Expressions - you can test yours before committing to verify it will match your lines.

    Note that patterns can't match multiline strings.

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 modernizes regex usage across PowerToys by converting many constant Regex patterns to [GeneratedRegex] source-generated regexes to reduce runtime overhead and address SYSLIB1045 warnings, while leaving runtime-constructed patterns as new Regex(...) with explanatory comments.

Changes:

  • Replaced many new Regex(...) / Regex.IsMatch / Regex.Replace calls with [GeneratedRegex] methods and updated call sites accordingly.
  • Updated affected types to be partial where required by [GeneratedRegex].
  • Applied a small fix in the WebSearch plugin to use a generated URI-scheme regex and normalize using System.Text.RegularExpressions;.

Reviewed changes

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

Show a summary per file
File Description
src/settings-ui/Settings.UI/SettingsXAML/OOBE/Views/ScoobeReleaseNotesPage.xaml.cs Converts release-notes parsing regexes to [GeneratedRegex].
src/settings-ui/Settings.UI.Library/SettingsBackupAndRestoreUtils.cs Uses generated regexes for backup file/folder name matching; marks class partial.
src/modules/Workspaces/WorkspacesCsharpLibrary/Models/BaseApplication.cs Replaces packaged-app path regex with [GeneratedRegex].
src/modules/registrypreview/RegistryPreviewUILib/RegistryPreviewMainPage.Utilities.cs Uses generated regex for stripping app-name suffix in window title.
src/modules/previewpane/MarkdownPreviewHandler/MarkdownPreviewHandlerControl.cs Converts image-tag detection regex to [GeneratedRegex].
src/modules/PowerOCR/PowerOCR/Helpers/StringHelpers.cs Converts multiple-spaces normalization regex to [GeneratedRegex]; marks class partial.
src/modules/PowerOCR/PowerOCR/Helpers/OcrExtensions.cs Converts OCR “space joining” detection regex to [GeneratedRegex]; marks class partial.
src/modules/peek/Peek.Common/Extensions/IFileSystemItemExtensions.cs Uses generated digits regex for parsing SVG dimensions; marks class partial.
src/modules/MouseWithoutBorders/App/Form/Settings/SetupPage2a.cs Uses generated whitespace regex when normalizing security codes.
src/modules/MouseWithoutBorders/App/Form/frmMatrix.cs Uses generated whitespace regex when normalizing encryption key input.
src/modules/MeasureTool/Tests/ScreenRuler.UITests/TestHelper.cs Converts UI-test validation regexes to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/TimeAndDateHelper.cs Converts TimeDate parsing/formatting regex fields and checks to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/SearchController.cs Converts search-term heuristics regexes to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.TimeDate/Components/AvailableResultsList.cs Converts UTC-prefix and backslash-fix regexes to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Registry/Helper/QueryHelper.cs Converts query sanitization regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/NumberTranslator.cs Converts hex tokenization regex to [GeneratedRegex]; keeps culture-based dynamic regex as new Regex(...).
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateHelper.cs Converts several expression-normalization regexes to [GeneratedRegex]; keeps dynamic patterns as new Regex(...).
src/modules/launcher/Plugins/Microsoft.PowerToys.Run.Plugin.Calculator/CalculateEngine.cs Converts division-by-zero detection regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.Plugin.Uri/UriHelper/ExtendedUriParser.cs Converts URI parsing helper regexes to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.Plugin.Program/Programs/Win32Program.cs Converts internet-shortcut URL prefix regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.Plugin.Program/ProgramArgumentParser/InferredProgramArgumentParser.cs Converts argument-prefix detection regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Microsoft.Plugin.Folder/Sources/ShellAction.cs Converts path-separator normalization regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.WebSearch/Main.cs Adds using System.Text.RegularExpressions;, converts scheme-check regex to [GeneratedRegex], marks Main partial.
src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SystemPath.cs Converts Windows-path detection regex to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.VSCodeWorkspaces/SshConfigParser/SshConfig.cs Converts SSH config parsing regexes to [GeneratedRegex]; marks class partial.
src/modules/launcher/Plugins/Community.PowerToys.Run.Plugin.UnitConverter/InputInterpreter.cs Converts split and square-unit regexes to [GeneratedRegex]; marks class partial.
src/modules/Hosts/HostsUILib/Helpers/ValidationHelper.cs Converts IP validation regexes to [GeneratedRegex]; marks class partial.
src/modules/colorPicker/ColorPickerUI/Controls/ColorPickerControl.xaml.cs Converts hex/short-hex/digits regexes to [GeneratedRegex].
src/modules/cmdpal/Microsoft.CmdPal.Common/Services/Sanitizer/FilenameMaskRuleProvider.cs Converts file-path masking regex to [GeneratedRegex]; marks class partial.
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/TimeAndDateHelper.cs Converts CmdPal TimeDate parsing/formatting regexes to [GeneratedRegex]; marks class partial.
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.TimeDate/Helpers/AvailableResultsList.cs Converts UTC-prefix/backslash-fix regexes to [GeneratedRegex]; marks class partial.
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.ClipboardHistory/Helpers/Analyzers/TextMetadataAnalyzer.cs Converts line-ending and word counting regexes to [GeneratedRegex]; marks class partial.
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/NumberTranslator.cs Converts base-number tokenization regex to [GeneratedRegex]; keeps culture-based dynamic regex as new Regex(...).
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateHelper.cs Converts multiple expression-normalization regexes to [GeneratedRegex]; keeps dynamic patterns as new Regex(...).
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Calc/Helper/CalculateEngine.cs Converts division-by-zero detection regex to [GeneratedRegex]; marks type partial.
src/modules/cmdpal/ext/Microsoft.CmdPal.Ext.Apps/Programs/Win32Program.cs Converts internet-shortcut URL prefix regex to [GeneratedRegex]; marks class partial.
src/modules/AdvancedPaste/AdvancedPaste/Helpers/MarkdownHelper.cs Converts HTML fragment and whitespace cleanup regexes to [GeneratedRegex]; marks class partial.
src/modules/AdvancedPaste/AdvancedPaste/Helpers/JsonHelper.cs Converts INI/CSV helper regexes to [GeneratedRegex]; marks class partial.
src/dsc/PowerToys.Settings.DSC.Schema.Generator/Common.cs Converts type-name splitting regex to [GeneratedRegex]; marks class partial.

(?: [A-Za-z]: )? (?: [\\/][^\\/:*?""<>|\s]+ )+ # drive-rooted or UNC-like
| [^\\/:*?""<>|\s]+ (?: [\\/][^\\/:*?""<>|\s]+ )+ # relative with at least one sep
)
""", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace)]
Copy link

Copilot AI Apr 7, 2026

Choose a reason for hiding this comment

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

FilePathRegex no longer applies the sanitizer regex match timeout (previously TimeSpan.FromMilliseconds(SanitizerDefaults.DefaultMatchTimeoutMs)). Since this rule runs on potentially untrusted/large input, dropping the timeout can reintroduce Regex DoS risks and change operational behavior. Please include SanitizerDefaults.DefaultMatchTimeoutMs in the [GeneratedRegex] attribute (and consider using SanitizerDefaults.DefaultOptions | RegexOptions.IgnorePatternWhitespace to stay consistent with the other sanitizer rule providers).

Suggested change
""", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.IgnorePatternWhitespace)]
""", SanitizerDefaults.DefaultOptions | RegexOptions.IgnorePatternWhitespace, SanitizerDefaults.DefaultMatchTimeoutMs)]

Copilot uses AI. Check for mistakes.
@crutkas crutkas marked this pull request as draft April 7, 2026 14:51
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.

3 participants