Skip to content

fix(analyzers): exempt separator-disjoint regex groups and preserve fix language - #159

Merged
e128 merged 1 commit into
mainfrom
fix/generatedregex-quantifier-heuristics
Nov 12, 2026
Merged

e128 merged 1 commit into
mainfrom
fix/generatedregex-quantifier-heuristics

Conversation

@e128

@e128 e128 commented Nov 12, 2026

Copy link
Copy Markdown
Owner

Executive Summary

E128014 fired on 21 pre-existing regex sites and blocked a consumer build. A repeated group whose body starts with a mandatory separator, such as (?:/[^\s:"']+)+, cannot backtrack, so the rule treated a linear pattern as exponential. E128014 now compares the first and last consuming atoms of the group body and stays silent when they cannot match the same text. Unbounded {n,} outer quantifiers now also fire, and bounded {n}/{n,m} repeats stay silent.

The two GeneratedRegex code fixes changed what the pattern matches. The nested fix removes the outer quantifier only for a single-atom body; a multi-atom body swaps + for {1,} and * for {0,}, which keeps the language. The overlapping fix collapses \s+ to a bare \s instead of dropping a required separator. Both fixers now reuse the analyzer detection helpers and the character-class mask, so the rewrite targets the reported element. E128013 messaging now states quadratic backtracking.

Code Changes

  • GeneratedRegexHelpers: new NestedQuantifierSpan result, FindNestedQuantifierSpan, first/last-atom comparison, unbounded brace quantifier support; mask and overlap helpers made internal for fixer reuse.
  • GeneratedRegexNestedCodeFixProvider / GeneratedRegexOverlappingCodeFixProvider: rewritten on the shared detection, registration skips when the rewrite is a no-op.
  • RegexLiteralFix: added TryGetPattern so both fixers read the pattern the same way.
  • E128013 descriptor and analyzer README reworded to quadratic.
  • Version bump: E128.Analyzers 2.10.0 to 2.10.1 (patch, bug fix only).

Tests and Tooling

  • New no-fire fixtures for both real separator-disjoint patterns and the bounded brace; new fire test for (?:x+){3,}.
  • New code fix tests: multi-atom {1,} rewrite (diagnostic survives), no-fix on unbounded braces, \s+ collapse including the negated-class branch, paren-inside-class.
  • scripts/check.sh --all passed (shell, format, build, test). Targeted classes: analyzer 35/35, nested fix 6/6, overlapping fix 6/6. Release files and README rule table verified in sync.

Review Guide

The heuristic compares atom tokens without expanding character class contents; a class that can match the other atom can exempt a group. This limit is documented in the README and the lode. The multi-atom {1,} rewrite preserves the language but the diagnostic remains by design.

Rollback

Revert the single commit; no data or schema changes.

@e128
e128 merged commit 0a45bd6 into main Nov 12, 2026
2 checks passed
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.

1 participant