Repository navigation
[go_router] Support nested parentheses, groups, and lookaround assertions in path parameters - #12571
Conversation
There was a problem hiding this comment.
Code Review
This pull request refactors path parameter parsing in go_router by replacing the _parameterRegExp regular expression with a custom scanner (_pathParametersOf and _closingParenIndex) to correctly handle nested parentheses, escaped characters, and character classes within parameter constraints. It introduces a _PathParameter class and updates patternToRegExp and patternToPath to use the new scanner. Unit tests are added to verify the parsing of nested groups, group constructs, and parentheses in character classes. There are no review comments, and I have no feedback to provide.
Piinks
left a comment
There was a problem hiding this comment.
Hey @MaximeRougieux thanks for contributing! One required step before we can move this forward: go_router uses the batched release process. Please add a pending changelog entry under packages/go_router/pending_changelogs/
|
Hi @Piinks, I added the pending changelog, do you want me to squash it with the other commit or is it fine like that? |
No it's fine. Everything gets squashed when merged |
Piinks
left a comment
There was a problem hiding this comment.
Thanks for working on this @MaximeRougieux!
I noticed a couple things to address:
-
The 4 tests added in
path_utils_test.dartcover non-capturing groups(?:and lookaheads(?!, but none test an actual capturing group with alternation like(FOO|BAR)or the reproduction pattern from #117307 (r'/details/:id((FOO|BAR)[0-9a-zA-Z]{10})'). Please add a test for this intest/path_utils_test.dart. -
The PR title mentions "capturing groups like (?!, (?: and (?=", but
(?:is explicitly non-capturing and(?!/(?=are zero-width lookaround assertions. Could you update the PR title to:
[go_router] Support nested parentheses, groups, and lookaround assertions in path parameters- In the description example
/tags/:slug((?!politics|economy)), lookaheads are zero-width and do not consume characters, so without a trailing segment pattern like[^/]+, it won't match/tags/culture. Updating the example to/tags/:slug((?!politics|economy)[^/]+)will avoid confusion for reviewers and future archaeologists. :)
- In the description example
-
In
packages/go_router/pending_changelogs/fix_lookahead_path_params.yaml, please adjust the entry to follow repo conventions (complete sentence ending in a period, accurate scope):changelog: | - Fixes path parameter regex parsing to support nested parentheses, grouping constructs, and lookahead assertions in GoRoute paths. version: patch
I think go_router_builder has a duplicate copy of path_utils.dart that has the same issue; would you like to follow up with an issue/PR to port this fix there as well?
|
Hey @Piinks, thanks for the review! |
|
@Piinks everything should be good now, let me know if you need anything else on these PR |
Piinks
left a comment
There was a problem hiding this comment.
It looks like there are some failing checks, can you take a look?
d695165 to
7ce8c1c
Compare
The logs are difficult to understand but it seems there was a |
|
@Piinks could you please relaunch the CI regarding this comment please? |
|
Added! |
7ce8c1c to
131f1a6
Compare
|
@Piinks it seems to have failed again on some unrelated ci change 😅 I rebased again, can you try reading the CI/CD label ? Third time will hopefully be the charm |
Have you tried running the tests locally? |
Yes, if you refer to It seemed like an unrelated failure, I assume rerunning the CI will work (unless it hits another issue of the same kind) |
131f1a6 to
8b8ff6e
Compare
|
@Piinks it seems everything is finally passing here, thanks for your help! |
|
Hi @elliette! Could you have a look on this when you have time please? Thanks! 😇 |
elliette
left a comment
There was a problem hiding this comment.
Looks good! One small request - it looks like the documentation at
packages/packages/go_router/lib/src/route.dart
Lines 373 to 374 in 6c3361d
8b8ff6e to
2a12b0b
Compare
|
Hi @elliette, thanks for the review! |
flutter/packages@3742a4e...3f34a6f 2026-11-01 [email protected] Roll Flutter from ee8b482 to fcfb4f2 (3 revisions) (flutter/packages#13520) 2026-10-31 [email protected] Roll Flutter from 5e805bf to ee8b482 (17 revisions) (flutter/packages#13512) 2026-10-30 [email protected] [VPAT] Describe the a11y_assessments dialog for screen readers (flutter/packages#13462) 2026-10-30 [email protected] [go_router_builder] Allow `build` 5 (flutter/packages#13455) 2026-10-30 [email protected] [go_router] Support nested parentheses, groups, and lookaround assertions in path parameters (flutter/packages#12571) 2026-10-30 [email protected] [in_app_purchase_storekit] Add SK2Transaction.currentEntitlements() (flutter/packages#13373) 2026-10-30 [email protected] [all] Remove broken .claude/skills symlink (flutter/packages#13492) 2026-10-30 [email protected] Roll Flutter from c091098 to 5e805bf (15 revisions) (flutter/packages#13504) If this roll has caused a breakage, revert this CL and set the roller to dry run mode using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC [email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
flutter/packages@3742a4e...3f34a6f 2026-11-01 [email protected] Roll Flutter from ee8b482 to fcfb4f2 (3 revisions) (flutter/packages#13520) 2026-10-31 [email protected] Roll Flutter from 5e805bf to ee8b482 (17 revisions) (flutter/packages#13512) 2026-10-30 [email protected] [VPAT] Describe the a11y_assessments dialog for screen readers (flutter/packages#13462) 2026-10-30 [email protected] [go_router_builder] Allow `build` 5 (flutter/packages#13455) 2026-10-30 [email protected] [go_router] Support nested parentheses, groups, and lookaround assertions in path parameters (flutter/packages#12571) 2026-10-30 [email protected] [in_app_purchase_storekit] Add SK2Transaction.currentEntitlements() (flutter/packages#13373) 2026-10-30 [email protected] [all] Remove broken .claude/skills symlink (flutter/packages#13492) 2026-10-30 [email protected] Roll Flutter from c091098 to 5e805bf (15 revisions) (flutter/packages#13504) If this roll has caused a breakage, revert this CL and set the roller to dry run mode using the controls here: https://autoroll.skia.org/r/flutter-packages-flutter-autoroll Please CC [email protected] on the revert to ensure that a human is aware of the problem. To file a bug in Flutter: https://github.com/flutter/flutter/issues/new/choose To report a problem with the AutoRoller itself, please file a bug: https://issues.skia.org/issues/new?component=1389291&template=1850622 Documentation for the AutoRoller is here: https://skia.googlesource.com/buildbot/+doc/main/autoroll/README.md
Example:
/tags/:slug((?!politics|economy)[^/]+)should match/tags/cultureand not match/tags/politics, but the current behavior is that the internal parenthesis are unhandled and the pattern is then used literally :/tags/flutter-> No match/tags/politics-> No match/tags/flutter((?!politics|economy))[^/]+)-> Match, slug="flutter"Disclosure: I did the investigation and fix using AI, which i carefully reviewed and tried to improve as much as I could according to the AI contribution guidelines. I think it's still better to mention it
A few things to note:
_escapeGroupfunction is completely gone (and why it was there in the first place if we can just remove it like that). The AI retraces this to when the repository transitioned from using thepath_to_regexppackage to having the functions in the codebase. This package seems to be using positional group matching, whereas go_router relies on named group matching, so escaping characters like :,- or ! is unnecessary as they can't disrupt the matching from working as expected.Pre-Review Checklist
[shared_preferences]///).