Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[go_router] Refactored RouteMatchList and imperative APIs #5497

Merged
merged 9 commits into from
Dec 21, 2023

Conversation

chunhtai
Copy link
Contributor

@chunhtai chunhtai commented Nov 27, 2023

This pr refactor RouteMatchList to be a tree structure.

Added a common base class RouteMatchBase. It is extended by both RouteMatch and ShellRouteMatch.

The RouteMatch is for GoRoute, and is always a leaf node

The ShellRouteMatch is for ShellRouteBase, and is always and intermediate node with a list of child RouteMatchBase[s].

This pr also redo how push is processed. Will add a doc explain this shortly.

This is a breaking change, will write a migration guide soon.

fixes flutter/flutter#134524
fixes flutter/flutter#130406
fixes flutter/flutter#126365
fixes flutter/flutter#125752
fixes flutter/flutter#120791
fixes flutter/flutter#120665
fixes flutter/flutter#113001
fixes flutter/flutter#110512

Pre-launch Checklist

  • I read the Contributor Guide and followed the process outlined there for submitting PRs.
  • I read the Tree Hygiene wiki page, which explains my responsibilities.
  • I read and followed the relevant style guides and ran the auto-formatter. (Unlike the flutter/flutter repo, the flutter/packages repo does use dart format.)
  • I signed the CLA.
  • The title of the PR starts with the name of the package surrounded by square brackets, e.g. [shared_preferences]
  • I listed at least one issue that this PR fixes in the description above.
  • I updated pubspec.yaml with an appropriate new version according to the pub versioning philosophy, or this PR is exempt from version changes.
  • I updated CHANGELOG.md to add a description of the change, following repository CHANGELOG style.
  • I updated/added relevant documentation (doc comments with ///).
  • I added new tests to check the change I am making, or this PR is test-exempt.
  • All existing and new tests are passing.

If you need help, consider asking for advice on the #hackers-new channel on Discord.

@flutter-dashboard
Copy link

It looks like this pull request may not have tests. Please make sure to add tests before merging. If you need an exemption to this rule, contact Hixie or stuartmorgan on the #hackers channel in Chat (don't just cc them here, they won't see it! Use Discord!).

If you are not sure if you need tests, consider this rule of thumb: the purpose of a test is to make sure someone doesn't accidentally revert the fix. Ask yourself, is there anything in your PR that you feel it is important we not accidentally revert back to how it was before your fix?

Reviewers: Read the Tree Hygiene page and make sure this patch meets those guidelines before LGTMing.

@chunhtai chunhtai marked this pull request as draft November 27, 2023 22:55
@chunhtai chunhtai force-pushed the route-match-tree branch 2 times, most recently from 77e95ca to 109bdfc Compare December 6, 2023 23:02
@chunhtai chunhtai changed the title WIP route match tree [go_router] Refactored RouteMatchList and imperative APIs Dec 7, 2023

/// Returns the top-level pages instead of the root navigator. Used for
/// testing.
List<Page<Object?>> _buildPages(
Copy link
Contributor Author

Choose a reason for hiding this comment

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

most of the recursive build pages logic is moved to _CustomNavigatorState

@@ -73,25 +79,36 @@ class GoRouterDelegate extends RouterDelegate<RouteMatchList>

/// Returns `true` if the active Navigator can pop.
bool canPop() {
final _NavigatorStateIterator iterator = _createNavigatorStateIterator();
Copy link
Contributor Author

Choose a reason for hiding this comment

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

previously we need to scan the list and use parent navigator key to jump around the list. Therefore i created this iterator to abstract away the logic.

After the refactor we just need to look at the last node in the RouteMatchList and walk up the tree branch.


/// Generate a [RouteMatch] object by matching the `route` with
/// `remainingLocation`.
///
/// The extracted path parameters, as the result of the matching, are stored
/// into `pathParameters`.
static RouteMatch? match({
static List<RouteMatchBase> match({
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is the most complex part in this pr, previously match just produce a RouteMatch for the input route.

After this change, this match will recursively match the subroute in route and return the entire route matches if it finds the full match.


if (builder == null) {
return null;
}
return buildPage(context, state, Builder(builder: (BuildContext context) {
return _buildPlatformAdapterPage(context, state,
Builder(builder: (BuildContext context) {
return builder(context, state);
}));
}

/// Builds a [Page] for [ShellRouteBase]
Copy link
Member

Choose a reason for hiding this comment

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

nit : ShellRouteMatch

return _buildPlatformAdapterPage(context, state,
Builder(builder: (BuildContext context) {
return match.route.buildWidget(context, state, shellRouteContext)!;
}));
Copy link
Member

Choose a reason for hiding this comment

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

nit: comma

GoRouterState buildState(
RouteConfiguration configuration, RouteMatchList matches);

/// Generate a list [RouteMatchBase] objects by matching the `route` and its
Copy link
Member

Choose a reason for hiding this comment

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

nit: 'Generates a list of'

}
return copyWith(
matches: _createNewMatchUntilIncompatible(
matches, match.matches.matches, match));
Copy link
Member

Choose a reason for hiding this comment

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

nit: comma

packages/go_router/lib/src/match.dart Show resolved Hide resolved
/// The last leaf route.
///
/// If the last RouteMatchBase from [matches] is a ShellRouteMatch, it
/// cursively goes into its [ShellRouteMatch.matches] until it reach the leaf
Copy link
Member

Choose a reason for hiding this comment

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

nit: recursively

/// order is removed.
static List<RouteMatchBase> _removeRouteMatchFromList(
List<RouteMatchBase> matches, RouteMatchBase target) {
// Remove is usually caused by pop; therefore, start searching from the end.
Copy link
Member

Choose a reason for hiding this comment

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

Remove is usually caused by pop

by usually do you mean there are other cases?

this function looks like it assumes all removal is pop. it not only removes the target, but also remove all matches after the target.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

updated wording

@override
final ShellRouteBase route;

RouteMatch get _leafMatch {
Copy link
Member

Choose a reason for hiding this comment

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

I found the name leafMatch a bit confusing cause a tree can have many leaves. Maybe lastLeaf is more clear?

@override
void didChangeDependencies() {
super.didChangeDependencies();
// Return a HeroController based on the app type.
Copy link
Member

Choose a reason for hiding this comment

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

nit: returns

Copy link
Contributor Author

Choose a reason for hiding this comment

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

gramma is correct here since I am describing a fact, but the return may not be a good word here. will update

}
}
if (subRouteMatches?.isEmpty ?? true) {
// If not finding a sub route match, it is consider not matched for this
Copy link
Member

Choose a reason for hiding this comment

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

nit: considered

configuration: configuration,
errorBuilder: errorBuilder,
errorPageBuilder: errorPageBuilder,
));
Copy link
Member

Choose a reason for hiding this comment

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

nit: comma

required this.navigatorRestorationId,
required this.onPopPageWithRouteMatch,
required this.matchList,
required this.matches,
Copy link
Member

@hannah-hyj hannah-hyj Dec 14, 2023

Choose a reason for hiding this comment

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

why pass both matchList and matches? Can you add some comments?

packages/go_router/lib/src/match.dart Show resolved Hide resolved
registry: _registry,
child: HeroControllerScope(
controller: _controller!,
child: Builder(
Copy link
Member

Choose a reason for hiding this comment

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

Builder() here seems like unnecessary. context is not used.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

good catch

// Grabs the route matches for the scope navigator key and put it into the
// matches for `null`.
if (result.containsKey(scopedNavigatorKey)) {
final List<RouteMatchBase> matchForScopedNavigator =
Copy link
Member

Choose a reason for hiding this comment

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

nit matchesForScopedNavigator

);
} else {
assert(false, 'Unexpected route type: $route');
return const <GlobalKey<NavigatorState>?, List<RouteMatchBase>>{};
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
return const <GlobalKey<NavigatorState>?, List<RouteMatchBase>>{};
return const _empty;

packages/go_router/lib/src/match.dart Outdated Show resolved Hide resolved
required Uri uri,
}) {
final GlobalKey<NavigatorState>? parentKey =
route.parentNavigatorKey == null ||
Copy link
Member

Choose a reason for hiding this comment

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

same here

@@ -1,3 +1,10 @@
## 13.0.0

- Refactored `RouteMatchList` and imperative APIs.
Copy link
Member

Choose a reason for hiding this comment

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

nit: Refactors

parlough pushed a commit to flutter/website that referenced this pull request Dec 15, 2023
@chunhtai
Copy link
Contributor Author

cc @ValentinVignal

Copy link
Member

@hannah-hyj hannah-hyj left a comment

Choose a reason for hiding this comment

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

LGTM

@chunhtai chunhtai added the autosubmit Merge PR when tree becomes green via auto submit App label Dec 21, 2023
@auto-submit auto-submit bot merged commit 6660212 into flutter:main Dec 21, 2023
80 checks passed
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 22, 2023
engine-flutter-autoroll added a commit to engine-flutter-autoroll/flutter that referenced this pull request Dec 22, 2023
auto-submit bot pushed a commit to flutter/flutter that referenced this pull request Dec 22, 2023
flutter/packages@4c3bc49...23d2d9c

2023-12-22 49699333+dependabot[bot]@users.noreply.github.com Bump lewagon/wait-on-check-action from 1.3.1 to 1.3.3 (flutter/packages#5737)
2023-12-21 54558023+keyonghan@users.noreply.github.com Disable `presubmit: false` targets for recipes CQ (flutter/packages#5735)
2023-12-21 47866232+chunhtai@users.noreply.github.com [go_router] Refactored RouteMatchList and imperative APIs (flutter/packages#5497)
2023-12-21 54558023+keyonghan@users.noreply.github.com Add env_variables in ci.yaml (flutter/packages#5730)
2023-12-21 engine-flutter-autoroll@skia.org Roll Flutter (stable) from 2e9cb0a to 78666c8 (1 revision) (flutter/packages#5734)
2023-12-21 engine-flutter-autoroll@skia.org Roll Flutter from da0cd69 to 11def8e (16 revisions) (flutter/packages#5732)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com 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
ChopinDavid pushed a commit to wwt/flutter-packages that referenced this pull request Dec 28, 2023
This pr refactor RouteMatchList to be a tree structure.

Added a common base class RouteMatchBase. It is extended by both RouteMatch and ShellRouteMatch.

The RouteMatch is for GoRoute, and is always a leaf node

The ShellRouteMatch is for ShellRouteBase, and is always and intermediate node with a list of child RouteMatchBase[s].

This pr also redo how push is processed. Will add a doc explain this shortly.

This is a breaking change, will write a migration guide soon.

fixes flutter/flutter#134524
fixes flutter/flutter#130406
fixes flutter/flutter#126365
fixes flutter/flutter#125752
fixes flutter/flutter#120791
fixes flutter/flutter#120665
fixes flutter/flutter#113001
fixes flutter/flutter#110512
CoderDake pushed a commit to CoderDake/flutter that referenced this pull request Dec 28, 2023
flutter/packages@4c3bc49...23d2d9c

2023-12-22 49699333+dependabot[bot]@users.noreply.github.com Bump lewagon/wait-on-check-action from 1.3.1 to 1.3.3 (flutter/packages#5737)
2023-12-21 54558023+keyonghan@users.noreply.github.com Disable `presubmit: false` targets for recipes CQ (flutter/packages#5735)
2023-12-21 47866232+chunhtai@users.noreply.github.com [go_router] Refactored RouteMatchList and imperative APIs (flutter/packages#5497)
2023-12-21 54558023+keyonghan@users.noreply.github.com Add env_variables in ci.yaml (flutter/packages#5730)
2023-12-21 engine-flutter-autoroll@skia.org Roll Flutter (stable) from 2e9cb0a to 78666c8 (1 revision) (flutter/packages#5734)
2023-12-21 engine-flutter-autoroll@skia.org Roll Flutter from da0cd69 to 11def8e (16 revisions) (flutter/packages#5732)

If this roll has caused a breakage, revert this CL and stop the roller
using the controls here:
https://autoroll.skia.org/r/flutter-packages-flutter-autoroll
Please CC flutter-ecosystem@google.com,rmistry@google.com 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
@reidbaker reidbaker mentioned this pull request Jan 12, 2024
arc-yong pushed a commit to Arctuition/packages-arc that referenced this pull request Jun 14, 2024
This pr refactor RouteMatchList to be a tree structure.

Added a common base class RouteMatchBase. It is extended by both RouteMatch and ShellRouteMatch.

The RouteMatch is for GoRoute, and is always a leaf node

The ShellRouteMatch is for ShellRouteBase, and is always and intermediate node with a list of child RouteMatchBase[s].

This pr also redo how push is processed. Will add a doc explain this shortly.

This is a breaking change, will write a migration guide soon.

fixes flutter/flutter#134524
fixes flutter/flutter#130406
fixes flutter/flutter#126365
fixes flutter/flutter#125752
fixes flutter/flutter#120791
fixes flutter/flutter#120665
fixes flutter/flutter#113001
fixes flutter/flutter#110512
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment