[go_router] Cleans up route match API and introduces dart fix (#3819)

Clean up API around RouteMatch/RouteMatchList/GoRouterState,

This is a breaking change that renamed some of the GoRouterState property to have a more descriptive name as flutter style guide suggested https://github.com/flutter/flutter/wiki/Style-guide-for-Flutter-repo#avoid-abbreviations

also introducing dart fix to help with migration
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index a0d7804..d46e9de 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,19 @@
+## 7.0.0
+
+- **BREAKING CHANGE**:
+  - For the below changes, run `dart fix --apply` to automatically migrate your code.
+    - `GoRouteState.subloc` has been renamed to `GoRouteState.matchedLocation`.
+    - `GoRouteState.params` has been renamed to `GoRouteState.pathParameters`.
+    - `GoRouteState.fullpath` has been renamed to `GoRouteState.fullPath`.
+    - `GoRouteState.queryParams` has been renamed to `GoRouteState.queryParameters`.
+    - `params` and `queryParams` in `GoRouteState.namedLocation` have been renamed to `pathParameters` and `queryParameters`.
+    - `params` and `queryParams` in `GoRouter`'s `namedLocation`, `pushNamed`, `pushReplacementNamed`
+      `replaceNamed` have been renamed to `pathParameters` and `queryParameters`.
+  - For the below changes, please follow the [migration guide](https://docs.google.com/document/d/10Xbpifbs4E-zh6YE5akIO8raJq_m3FIXs6nUGdOspOg).
+    - `params` and `queryParams` in `BuildContext`'s `namedLocation`, `pushNamed`, `pushReplacementNamed`
+      `replaceNamed` have been renamed to `pathParameters` and `queryParameters`.
+- Cleans up API and makes RouteMatchList immutable.
+
 ## 6.5.9
 
 - Removes navigator keys from `GoRouteData` and `ShellRouteData`.
diff --git a/packages/go_router/README.md b/packages/go_router/README.md
index daed219..eae5297 100644
--- a/packages/go_router/README.md
+++ b/packages/go_router/README.md
@@ -37,6 +37,7 @@
 - [Error handling](https://pub.dev/documentation/go_router/latest/topics/Error%20handling-topic.html)
 
 ## Migration guides
+- [Migrating to 7.0.0](https://docs.google.com/document/d/10Xbpifbs4E-zh6YE5akIO8raJq_m3FIXs6nUGdOspOg).
 - [Migrating to 6.0.0](https://flutter.dev/go/go-router-v6-breaking-changes)
 - [Migrating to 5.1.2](https://flutter.dev/go/go-router-v5-1-2-breaking-changes)
 - [Migrating to 5.0](https://flutter.dev/go/go-router-v5-breaking-changes)
diff --git a/packages/go_router/analysis_options.yaml b/packages/go_router/analysis_options.yaml
new file mode 100644
index 0000000..cfb845a
--- /dev/null
+++ b/packages/go_router/analysis_options.yaml
@@ -0,0 +1,5 @@
+include: ../../analysis_options.yaml
+
+analyzer:
+  exclude:
+    - "test_fixes/**"
diff --git a/packages/go_router/doc/configuration.md b/packages/go_router/doc/configuration.md
index ef4658a..09093d0 100644
--- a/packages/go_router/doc/configuration.md
+++ b/packages/go_router/doc/configuration.md
@@ -43,7 +43,7 @@
 ```dart
 GoRoute(
   path: '/users/:userId',
-  builder: (context, state) => const UserScreen(id: state.params['userId']),
+  builder: (context, state) => const UserScreen(id: state.pathParameters['userId']),
 ),
 ```
 
@@ -55,7 +55,7 @@
 ```dart
 GoRoute(
   path: '/users',
-  builder: (context, state) => const UsersScreen(filter: state.queryParams['filter']),
+  builder: (context, state) => const UsersScreen(filter: state.queryParameters['filter']),
 ),
 ```
 
diff --git a/packages/go_router/doc/named-routes.md b/packages/go_router/doc/named-routes.md
index 54705d1..861277c 100644
--- a/packages/go_router/doc/named-routes.md
+++ b/packages/go_router/doc/named-routes.md
@@ -14,7 +14,7 @@
 ```dart
 TextButton(
   onPressed: () {
-    context.goNamed('song', params: {'songId': 123});
+    context.goNamed('song', pathParameters: {'songId': 123});
   },
   child: const Text('Go to song 2'),
 ),
@@ -25,7 +25,7 @@
 ```dart
 TextButton(
   onPressed: () {
-    final String location = context.namedLocation('song', params: {'songId': 123});
+    final String location = context.namedLocation('song', pathParameters: {'songId': 123});
     context.go(location);
   },
   child: const Text('Go to song 2'),
diff --git a/packages/go_router/example/lib/async_redirection.dart b/packages/go_router/example/lib/async_redirection.dart
index d91db6e..f84c14e 100644
--- a/packages/go_router/example/lib/async_redirection.dart
+++ b/packages/go_router/example/lib/async_redirection.dart
@@ -55,7 +55,7 @@
       // cause go_router to reparse current route if StreamAuth has new sign-in
       // information.
       final bool loggedIn = await StreamAuthScope.of(context).isSignedIn();
-      final bool loggingIn = state.subloc == '/login';
+      final bool loggingIn = state.matchedLocation == '/login';
       if (!loggedIn) {
         return '/login';
       }
diff --git a/packages/go_router/example/lib/books/main.dart b/packages/go_router/example/lib/books/main.dart
index 73cb6f3..eb757e3 100644
--- a/packages/go_router/example/lib/books/main.dart
+++ b/packages/go_router/example/lib/books/main.dart
@@ -63,7 +63,7 @@
       GoRoute(
         path: '/book/:bookId',
         redirect: (BuildContext context, GoRouterState state) =>
-            '/books/all/${state.params['bookId']}',
+            '/books/all/${state.pathParameters['bookId']}',
       ),
       GoRoute(
         path: '/books/:kind(new|all|popular)',
@@ -72,14 +72,14 @@
           key: _scaffoldKey,
           child: BookstoreScaffold(
             selectedTab: ScaffoldTab.books,
-            child: BooksScreen(state.params['kind']!),
+            child: BooksScreen(state.pathParameters['kind']!),
           ),
         ),
         routes: <GoRoute>[
           GoRoute(
             path: ':bookId',
             builder: (BuildContext context, GoRouterState state) {
-              final String bookId = state.params['bookId']!;
+              final String bookId = state.pathParameters['bookId']!;
               final Book? selectedBook = libraryInstance.allBooks
                   .firstWhereOrNull((Book b) => b.id.toString() == bookId);
 
@@ -91,7 +91,7 @@
       GoRoute(
         path: '/author/:authorId',
         redirect: (BuildContext context, GoRouterState state) =>
-            '/authors/${state.params['authorId']}',
+            '/authors/${state.pathParameters['authorId']}',
       ),
       GoRoute(
         path: '/authors',
@@ -107,7 +107,7 @@
           GoRoute(
             path: ':authorId',
             builder: (BuildContext context, GoRouterState state) {
-              final int authorId = int.parse(state.params['authorId']!);
+              final int authorId = int.parse(state.pathParameters['authorId']!);
               final Author? selectedAuthor = libraryInstance.allAuthors
                   .firstWhereOrNull((Author a) => a.id == authorId);
 
@@ -135,7 +135,7 @@
 
   String? _guard(BuildContext context, GoRouterState state) {
     final bool signedIn = _auth.signedIn;
-    final bool signingIn = state.subloc == '/signin';
+    final bool signingIn = state.matchedLocation == '/signin';
 
     // Go to /signin if the user is not signed in
     if (!signedIn && !signingIn) {
diff --git a/packages/go_router/example/lib/named_routes.dart b/packages/go_router/example/lib/named_routes.dart
index a9d4604..9685fc4 100644
--- a/packages/go_router/example/lib/named_routes.dart
+++ b/packages/go_router/example/lib/named_routes.dart
@@ -84,14 +84,15 @@
             name: 'family',
             path: 'family/:fid',
             builder: (BuildContext context, GoRouterState state) =>
-                FamilyScreen(fid: state.params['fid']!),
+                FamilyScreen(fid: state.pathParameters['fid']!),
             routes: <GoRoute>[
               GoRoute(
                 name: 'person',
                 path: 'person/:pid',
                 builder: (BuildContext context, GoRouterState state) {
                   return PersonScreen(
-                      fid: state.params['fid']!, pid: state.params['pid']!);
+                      fid: state.pathParameters['fid']!,
+                      pid: state.pathParameters['pid']!);
                 },
               ),
             ],
@@ -119,7 +120,7 @@
             ListTile(
               title: Text(entry.value.name),
               onTap: () => context.go(context.namedLocation('family',
-                  params: <String, String>{'fid': entry.key})),
+                  pathParameters: <String, String>{'fid': entry.key})),
             )
         ],
       ),
@@ -147,8 +148,8 @@
               title: Text(entry.value.name),
               onTap: () => context.go(context.namedLocation(
                 'person',
-                params: <String, String>{'fid': fid, 'pid': entry.key},
-                queryParams: <String, String>{'qid': 'quid'},
+                pathParameters: <String, String>{'fid': fid, 'pid': entry.key},
+                queryParameters: <String, String>{'qid': 'quid'},
               )),
             ),
         ],
diff --git a/packages/go_router/example/lib/others/nav_observer.dart b/packages/go_router/example/lib/others/nav_observer.dart
index 2b8bfcb..038d337 100644
--- a/packages/go_router/example/lib/others/nav_observer.dart
+++ b/packages/go_router/example/lib/others/nav_observer.dart
@@ -108,8 +108,8 @@
               ElevatedButton(
                 onPressed: () => context.goNamed(
                   'page2',
-                  params: <String, String>{'p1': 'pv1'},
-                  queryParams: <String, String>{'q1': 'qv1'},
+                  pathParameters: <String, String>{'p1': 'pv1'},
+                  queryParameters: <String, String>{'q1': 'qv1'},
                 ),
                 child: const Text('Go to page 2'),
               ),
@@ -134,7 +134,7 @@
               ElevatedButton(
                 onPressed: () => context.goNamed(
                   'page3',
-                  params: <String, String>{'p1': 'pv2'},
+                  pathParameters: <String, String>{'p1': 'pv2'},
                 ),
                 child: const Text('Go to page 3'),
               ),
diff --git a/packages/go_router/example/lib/others/push.dart b/packages/go_router/example/lib/others/push.dart
index 53567b6..06e3469 100644
--- a/packages/go_router/example/lib/others/push.dart
+++ b/packages/go_router/example/lib/others/push.dart
@@ -32,7 +32,7 @@
         path: '/page2',
         builder: (BuildContext context, GoRouterState state) =>
             Page2ScreenWithPush(
-          int.parse(state.queryParams['push-count']!),
+          int.parse(state.queryParameters['push-count']!),
         ),
       ),
     ],
diff --git a/packages/go_router/example/lib/path_and_query_parameters.dart b/packages/go_router/example/lib/path_and_query_parameters.dart
index 83d7b63..bf915a2 100755
--- a/packages/go_router/example/lib/path_and_query_parameters.dart
+++ b/packages/go_router/example/lib/path_and_query_parameters.dart
@@ -9,9 +9,9 @@
 //
 // The route segments that start with ':' are treated as path parameters when
 // defining GoRoute[s]. The parameter values can be accessed through
-// GoRouterState.params.
+// GoRouterState.pathParameters.
 //
-// The query parameters are automatically stored in GoRouterState.queryParams.
+// The query parameters are automatically stored in GoRouterState.queryParameters.
 
 /// Family data class.
 class Family {
@@ -84,8 +84,8 @@
               path: 'family/:fid',
               builder: (BuildContext context, GoRouterState state) {
                 return FamilyScreen(
-                  fid: state.params['fid']!,
-                  asc: state.queryParams['sort'] == 'asc',
+                  fid: state.pathParameters['fid']!,
+                  asc: state.queryParameters['sort'] == 'asc',
                 );
               }),
         ],
@@ -149,7 +149,8 @@
         actions: <Widget>[
           IconButton(
             onPressed: () => context.goNamed('family',
-                params: <String, String>{'fid': fid}, queryParams: newQueries),
+                pathParameters: <String, String>{'fid': fid},
+                queryParameters: newQueries),
             tooltip: 'sort ascending or descending',
             icon: const Icon(Icons.sort),
           )
diff --git a/packages/go_router/example/lib/redirection.dart b/packages/go_router/example/lib/redirection.dart
index 4e97f66..868944c 100644
--- a/packages/go_router/example/lib/redirection.dart
+++ b/packages/go_router/example/lib/redirection.dart
@@ -75,7 +75,7 @@
     redirect: (BuildContext context, GoRouterState state) {
       // if the user is not logged in, they need to login
       final bool loggedIn = _loginInfo.loggedIn;
-      final bool loggingIn = state.subloc == '/login';
+      final bool loggingIn = state.matchedLocation == '/login';
       if (!loggedIn) {
         return '/login';
       }
diff --git a/packages/go_router/lib/fix_data.yaml b/packages/go_router/lib/fix_data.yaml
new file mode 100644
index 0000000..99f9782
--- /dev/null
+++ b/packages/go_router/lib/fix_data.yaml
@@ -0,0 +1,151 @@
+# Copyright 2014 The Flutter Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+# For details regarding the *Flutter Fix* feature, see
+# https://flutter.dev/docs/development/tools/flutter-fix
+
+# Please add new fixes to the top of the file, separated by one blank line
+# from other fixes. In a comment, include a link to the PR where the change
+# requiring the fix was made.
+
+# Every fix must be tested. See the flutter/packages/flutter/test_fixes/README.md
+# file for instructions on testing these data driven fixes.
+
+# For documentation about this file format, see
+# https://dart.dev/go/data-driven-fixes
+
+version: 1
+transforms:
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouter.replaceNamed' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'replaceNamed'
+      inClass: 'GoRouter'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouter.pushReplacementNamed' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'pushReplacementNamed'
+      inClass: 'GoRouter'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouter.pushNamed' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'pushNamed'
+      inClass: 'GoRouter'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouter.goNamed' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'goNamed'
+      inClass: 'GoRouter'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouter.namedLocation' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'namedLocation'
+      inClass: 'GoRouter'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'params' and 'queryParams' in 'GoRouterState.namedLocation' with `pathParameters` and `queryParameters`"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      method: 'namedLocation'
+      inClass: 'GoRouterState'
+    changes:
+      - kind: 'renameParameter'
+        oldName: 'params'
+        newName: 'pathParameters'
+      - kind: 'renameParameter'
+        oldName: 'queryParams'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'GoRouterState.queryParams' with 'GoRouterState.queryParameters'"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      field: 'queryParams'
+      inClass: 'GoRouterState'
+    changes:
+      - kind: 'rename'
+        newName: 'queryParameters'
+
+  - title: "Replaces 'GoRouterState.fullpath' with 'GoRouterState.fullPath'"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      field: 'fullpath'
+      inClass: 'GoRouterState'
+    changes:
+      - kind: 'rename'
+        newName: 'fullPath'
+
+  - title: "Replaces 'GoRouterState.params' with 'GoRouterState.pathParameters'"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      field: 'params'
+      inClass: 'GoRouterState'
+    changes:
+      - kind: 'rename'
+        newName: 'pathParameters'
+
+  - title: "Replaces 'GoRouterState.subloc' with 'GoRouterState.matchedLocation'"
+    date: 2023-04-24
+    bulkApply: true
+    element:
+      uris: [ 'go_router.dart' ]
+      field: 'subloc'
+      inClass: 'GoRouterState'
+    changes:
+      - kind: 'rename'
+        newName: 'matchedLocation'
diff --git a/packages/go_router/lib/src/builder.dart b/packages/go_router/lib/src/builder.dart
index 681f1d2..c497a79 100644
--- a/packages/go_router/lib/src/builder.dart
+++ b/packages/go_router/lib/src/builder.dart
@@ -6,7 +6,6 @@
 import 'package:flutter/widgets.dart';
 
 import 'configuration.dart';
-import 'delegate.dart';
 import 'logging.dart';
 import 'match.dart';
 import 'matching.dart';
@@ -254,7 +253,7 @@
   }
 
   /// Helper method that builds a [GoRouterState] object for the given [match]
-  /// and [params].
+  /// and [pathParameters].
   @visibleForTesting
   GoRouterState buildState(RouteMatchList matchList, RouteMatch match) {
     final RouteBase route = match.route;
@@ -269,13 +268,14 @@
     return GoRouterState(
       configuration,
       location: effectiveMatchList.uri.toString(),
-      subloc: match.subloc,
+      matchedLocation: match.matchedLocation,
       name: name,
       path: path,
-      fullpath: effectiveMatchList.fullpath,
-      params: Map<String, String>.from(effectiveMatchList.pathParameters),
+      fullPath: effectiveMatchList.fullPath,
+      pathParameters:
+          Map<String, String>.from(effectiveMatchList.pathParameters),
       error: match.error,
-      queryParams: effectiveMatchList.uri.queryParameters,
+      queryParameters: effectiveMatchList.uri.queryParameters,
       queryParametersAll: effectiveMatchList.uri.queryParametersAll,
       extra: match.extra,
       pageKey: match.pageKey,
@@ -397,7 +397,10 @@
     return _pageBuilderForAppType!(
       key: state.pageKey,
       name: state.name ?? state.path,
-      arguments: <String, String>{...state.params, ...state.queryParams},
+      arguments: <String, String>{
+        ...state.pathParameters,
+        ...state.queryParameters
+      },
       restorationId: state.pageKey.value,
       child: child,
     );
@@ -444,9 +447,9 @@
     final GoRouterState state = GoRouterState(
       configuration,
       location: uri.toString(),
-      subloc: uri.path,
+      matchedLocation: uri.path,
       name: null,
-      queryParams: uri.queryParameters,
+      queryParameters: uri.queryParameters,
       queryParametersAll: uri.queryParametersAll,
       error: Exception(error),
       pageKey: const ValueKey<String>('error'),
diff --git a/packages/go_router/lib/src/configuration.dart b/packages/go_router/lib/src/configuration.dart
index c17b708..2c2f8e7 100644
--- a/packages/go_router/lib/src/configuration.dart
+++ b/packages/go_router/lib/src/configuration.dart
@@ -97,7 +97,7 @@
       if (route is! GoRoute) {
         continue;
       }
-      for (final String pathParam in route.pathParams) {
+      for (final String pathParam in route.pathParameters) {
         if (usedPathParams.containsKey(pathParam)) {
           final bool sameRoute = usedPathParams[pathParam] == route;
           throw GoError(
@@ -106,7 +106,7 @@
         usedPathParams[pathParam] = route;
       }
       _debugVerifyNoDuplicatePathParameter(route.routes, usedPathParams);
-      route.pathParams.forEach(usedPathParams.remove);
+      route.pathParameters.forEach(usedPathParams.remove);
     }
     return true;
   }
@@ -128,14 +128,14 @@
   /// Looks up the url location by a [GoRoute]'s name.
   String namedLocation(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
   }) {
     assert(() {
       log.info('getting location for name: '
           '"$name"'
-          '${params.isEmpty ? '' : ', params: $params'}'
-          '${queryParams.isEmpty ? '' : ', queryParams: $queryParams'}');
+          '${pathParameters.isEmpty ? '' : ', pathParameters: $pathParameters'}'
+          '${queryParameters.isEmpty ? '' : ', queryParameters: $queryParameters'}');
       return true;
     }());
     final String keyName = name.toLowerCase();
@@ -146,24 +146,24 @@
       final List<String> paramNames = <String>[];
       patternToRegExp(path, paramNames);
       for (final String paramName in paramNames) {
-        assert(params.containsKey(paramName),
+        assert(pathParameters.containsKey(paramName),
             'missing param "$paramName" for $path');
       }
 
       // Check that there are no extra params
-      for (final String key in params.keys) {
+      for (final String key in pathParameters.keys) {
         assert(paramNames.contains(key), 'unknown param "$key" for $path');
       }
       return true;
     }());
     final Map<String, String> encodedParams = <String, String>{
-      for (final MapEntry<String, String> param in params.entries)
+      for (final MapEntry<String, String> param in pathParameters.entries)
         param.key: Uri.encodeComponent(param.value)
     };
     final String location = patternToPath(path, encodedParams);
     return Uri(
             path: location,
-            queryParameters: queryParams.isEmpty ? null : queryParams)
+            queryParameters: queryParameters.isEmpty ? null : queryParameters)
         .toString();
   }
 
@@ -196,9 +196,9 @@
       int depth, StringBuffer sb) {
     for (final RouteBase route in routes) {
       if (route is GoRoute) {
-        final String fullpath = concatenatePaths(parentFullpath, route.path);
-        sb.writeln('  => ${''.padLeft(depth * 2)}$fullpath');
-        _debugFullPathsFor(route.routes, fullpath, depth + 1, sb);
+        final String fullPath = concatenatePaths(parentFullpath, route.path);
+        sb.writeln('  => ${''.padLeft(depth * 2)}$fullPath');
+        _debugFullPathsFor(route.routes, fullPath, depth + 1, sb);
       } else if (route is ShellRoute) {
         _debugFullPathsFor(route.routes, parentFullpath, depth, sb);
       }
diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart
index 279c10d..a62906a 100644
--- a/packages/go_router/lib/src/delegate.dart
+++ b/packages/go_router/lib/src/delegate.dart
@@ -86,15 +86,19 @@
       RouteMatchList matches, ValueKey<String> pageKey) async {
     final ImperativeRouteMatch<T> newPageKeyMatch = ImperativeRouteMatch<T>(
       route: matches.last.route,
-      subloc: matches.last.subloc,
+      matchedLocation: matches.last.matchedLocation,
       extra: matches.last.extra,
       error: matches.last.error,
       pageKey: pageKey,
       matches: matches,
     );
 
-    _matchList.push(newPageKeyMatch);
-    return newPageKeyMatch._future;
+    _matchList = _matchList.push(newPageKeyMatch);
+    return newPageKeyMatch.future;
+  }
+
+  void _remove(RouteMatch match) {
+    _matchList = _matchList.remove(match);
   }
 
   /// Pushes the given location onto the page stack.
@@ -108,7 +112,7 @@
   Future<T?> push<T extends Object?>(RouteMatchList matches) async {
     assert(matches.last.route is! ShellRoute);
 
-    final ValueKey<String> pageKey = _getNewKeyForPath(matches.fullpath);
+    final ValueKey<String> pageKey = _getNewKeyForPath(matches.fullPath);
     final Future<T?> future = _push(matches, pageKey);
     notifyListeners();
     return future;
@@ -155,7 +159,7 @@
     if (match is ImperativeRouteMatch) {
       match.complete(result);
     }
-    _matchList.remove(match!);
+    _remove(match!);
     notifyListeners();
     assert(() {
       _debugAssertMatchListNotEmpty();
@@ -175,7 +179,7 @@
   ///   state and not run any page animation.
   void pushReplacement(RouteMatchList matches) {
     assert(matches.last.route is! ShellRoute);
-    _matchList.remove(_matchList.last);
+    _remove(_matchList.last);
     push(matches); // [push] will notify the listeners.
   }
 
@@ -193,7 +197,7 @@
     assert(matches.last.route is! ShellRoute);
     final RouteMatch routeMatch = _matchList.last;
     final ValueKey<String> pageKey = routeMatch.pageKey;
-    _matchList.remove(routeMatch);
+    _remove(routeMatch);
     _push(matches, pageKey);
     notifyListeners();
   }
@@ -309,32 +313,3 @@
     return true;
   }
 }
-
-/// The route match that represent route pushed through [GoRouter.push].
-class ImperativeRouteMatch<T> extends RouteMatch {
-  /// Constructor for [ImperativeRouteMatch].
-  ImperativeRouteMatch({
-    required super.route,
-    required super.subloc,
-    required super.extra,
-    required super.error,
-    required super.pageKey,
-    required this.matches,
-  }) : _completer = Completer<T?>();
-
-  /// The matches that produces this route match.
-  final RouteMatchList matches;
-
-  /// The completer for the future returned by [GoRouter.push].
-  final Completer<T?> _completer;
-
-  /// Called when the corresponding [Route] associated with this route match is
-  /// completed.
-  void complete([dynamic value]) {
-    _completer.complete(value as T?);
-  }
-
-  /// The future of the [RouteMatch] completer.
-  /// When the future completes, this will return the value passed to [complete].
-  Future<T?> get _future => _completer.future;
-}
diff --git a/packages/go_router/lib/src/match.dart b/packages/go_router/lib/src/match.dart
index 0cb7041..7c3c736 100644
--- a/packages/go_router/lib/src/match.dart
+++ b/packages/go_router/lib/src/match.dart
@@ -2,35 +2,44 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'dart:async';
+
 import 'package:flutter/widgets.dart';
 
 import 'matching.dart';
 import 'path_utils.dart';
 import 'route.dart';
 
-///  An instance of a GoRoute plus information about the current location.
+/// An matched result by matching a [RouteBase] against a location.
+///
+/// This is typically created by calling [RouteMatch.match].
+@immutable
 class RouteMatch {
   /// Constructor for [RouteMatch].
-  RouteMatch({
+  const RouteMatch({
     required this.route,
-    required this.subloc,
+    required this.matchedLocation,
     required this.extra,
     required this.error,
     required this.pageKey,
   });
 
-  // ignore: public_member_api_docs
+  /// 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({
     required RouteBase route,
-    required String restLoc, // e.g. person/p1
-    required String parentSubloc, // e.g. /family/f2
+    required String remainingLocation, // e.g. person/p1
+    required String matchedLocation, // e.g. /family/f2
     required Map<String, String> pathParameters,
     required Object? extra,
   }) {
     if (route is ShellRoute) {
       return RouteMatch(
         route: route,
-        subloc: restLoc,
+        matchedLocation: remainingLocation,
         extra: extra,
         error: null,
         pageKey: ValueKey<String>(route.hashCode.toString()),
@@ -38,7 +47,7 @@
     } else if (route is GoRoute) {
       assert(!route.path.contains('//'));
 
-      final RegExpMatch? match = route.matchPatternAsPrefix(restLoc);
+      final RegExpMatch? match = route.matchPatternAsPrefix(remainingLocation);
       if (match == null) {
         return null;
       }
@@ -48,23 +57,31 @@
         pathParameters[param.key] = Uri.decodeComponent(param.value);
       }
       final String pathLoc = patternToPath(route.path, encodedParams);
-      final String subloc = concatenatePaths(parentSubloc, pathLoc);
+      final String newMatchedLocation =
+          concatenatePaths(matchedLocation, pathLoc);
       return RouteMatch(
         route: route,
-        subloc: subloc,
+        matchedLocation: newMatchedLocation,
         extra: extra,
         error: null,
         pageKey: ValueKey<String>(route.hashCode.toString()),
       );
     }
-    throw MatcherError('Unexpected route type: $route', restLoc);
+    throw MatcherError('Unexpected route type: $route', remainingLocation);
   }
 
   /// The matched route.
   final RouteBase route;
 
-  /// The matched location.
-  final String subloc; // e.g. /family/f2
+  /// The location string that matches the [route].
+  ///
+  /// for example:
+  ///
+  /// uri = '/family/f2/person/p2'
+  /// route = GoRoute('/family/:id)
+  ///
+  /// matchedLocation = '/family/f2'
+  final String matchedLocation;
 
   /// An extra object to pass along with the navigation.
   final Object? extra;
@@ -74,4 +91,59 @@
 
   /// Value key of type string, to hold a unique reference to a page.
   final ValueKey<String> pageKey;
+
+  @override
+  bool operator ==(Object other) {
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is RouteMatch &&
+        route == other.route &&
+        matchedLocation == other.matchedLocation &&
+        extra == other.extra &&
+        pageKey == other.pageKey;
+  }
+
+  @override
+  int get hashCode => Object.hash(route, matchedLocation, extra, pageKey);
+}
+
+/// The route match that represent route pushed through [GoRouter.push].
+class ImperativeRouteMatch<T> extends RouteMatch {
+  /// Constructor for [ImperativeRouteMatch].
+  ImperativeRouteMatch({
+    required super.route,
+    required super.matchedLocation,
+    required super.extra,
+    required super.error,
+    required super.pageKey,
+    required this.matches,
+  }) : _completer = Completer<T?>();
+
+  /// The matches that produces this route match.
+  final RouteMatchList matches;
+
+  /// The completer for the future returned by [GoRouter.push].
+  final Completer<T?> _completer;
+
+  /// Called when the corresponding [Route] associated with this route match is
+  /// completed.
+  void complete([dynamic value]) {
+    _completer.complete(value as T?);
+  }
+
+  /// The future of the [RouteMatch] completer.
+  /// When the future completes, this will return the value passed to [complete].
+  Future<T?> get future => _completer.future;
+
+  // An ImperativeRouteMatch has its own life cycle due the the _completer.
+  // comparing _completer between instances would be the same thing as
+  // comparing object reference.
+  @override
+  bool operator ==(Object other) {
+    return identical(this, other);
+  }
+
+  @override
+  int get hashCode => identityHashCode(this);
 }
diff --git a/packages/go_router/lib/src/matching.dart b/packages/go_router/lib/src/matching.dart
index b67c69b..5855204 100644
--- a/packages/go_router/lib/src/matching.dart
+++ b/packages/go_router/lib/src/matching.dart
@@ -2,11 +2,11 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+import 'package:collection/collection.dart';
 import 'package:flutter/foundation.dart';
 import 'package:flutter/widgets.dart';
 
 import 'configuration.dart';
-import 'delegate.dart';
 import 'match.dart';
 import 'path_utils.dart';
 
@@ -25,16 +25,17 @@
     final Map<String, String> pathParameters = <String, String>{};
     final List<RouteMatch> matches =
         _getLocRouteMatches(uri, extra, pathParameters);
-    return RouteMatchList(matches, uri, pathParameters);
+    return RouteMatchList(
+        matches: matches, uri: uri, pathParameters: pathParameters);
   }
 
   List<RouteMatch> _getLocRouteMatches(
       Uri uri, Object? extra, Map<String, String> pathParameters) {
     final List<RouteMatch>? result = _getLocRouteRecursively(
-      loc: uri.path,
-      restLoc: uri.path,
+      location: uri.path,
+      remainingLocation: uri.path,
       routes: configuration.routes,
-      parentSubloc: '',
+      matchedLocation: '',
       pathParameters: pathParameters,
       extra: extra,
     );
@@ -50,19 +51,50 @@
 /// The list of [RouteMatch] objects.
 ///
 /// This corresponds to the GoRouter's history.
+@immutable
 class RouteMatchList {
   /// RouteMatchList constructor.
-  RouteMatchList(List<RouteMatch> matches, this._uri, this.pathParameters)
-      : _matches = matches,
-        fullpath = _generateFullPath(matches);
+  RouteMatchList({
+    required this.matches,
+    required this.uri,
+    required this.pathParameters,
+  }) : fullPath = _generateFullPath(matches);
 
   /// Constructs an empty matches object.
-  static RouteMatchList empty =
-      RouteMatchList(<RouteMatch>[], Uri.parse(''), const <String, String>{});
+  static RouteMatchList empty = RouteMatchList(
+      matches: const <RouteMatch>[],
+      uri: Uri(),
+      pathParameters: const <String, String>{});
+
+  /// The route matches.
+  final List<RouteMatch> matches;
+
+  /// Parameters for the matched route, URI-encoded.
+  ///
+  /// The parameters only reflects [RouteMatch]s that are not
+  /// [ImperativeRouteMatch].
+  final Map<String, String> pathParameters;
+
+  /// The uri of the current match.
+  ///
+  /// This uri only reflects [RouteMatch]s that are not [ImperativeRouteMatch].
+  final Uri uri;
+
+  /// the full path pattern that matches the uri.
+  ///
+  /// For example:
+  ///
+  /// ```dart
+  /// '/family/:fid/person/:pid'
+  /// ```
+  final String fullPath;
 
   /// Generates the full path (ex: `'/family/:fid/person/:pid'`) of a list of
   /// [RouteMatch].
   ///
+  /// This method ignores [ImperativeRouteMatch]s in the `matches`, as they
+  /// don't contribute to the path.
+  ///
   /// This methods considers that [matches]'s elements verify the go route
   /// structure given to `GoRouter`. For example, if the routes structure is
   ///
@@ -90,7 +122,8 @@
   static String _generateFullPath(Iterable<RouteMatch> matches) {
     final StringBuffer buffer = StringBuffer();
     bool addsSlash = false;
-    for (final RouteMatch match in matches) {
+    for (final RouteMatch match in matches
+        .where((RouteMatch match) => match is! ImperativeRouteMatch)) {
       final RouteBase route = match.route;
       if (route is GoRoute) {
         if (addsSlash) {
@@ -103,66 +136,61 @@
     return buffer.toString();
   }
 
-  final List<RouteMatch> _matches;
-
-  /// the full path pattern that matches the uri.
-  ///
-  /// For example:
-  ///
-  /// ```dart
-  /// '/family/:fid/person/:pid'
-  /// ```
-  final String fullpath;
-
-  /// Parameters for the matched route, URI-encoded.
-  final Map<String, String> pathParameters;
-
-  /// The uri of the current match.
-  Uri get uri => _uri;
-  Uri _uri;
-
   /// Returns true if there are no matches.
-  bool get isEmpty => _matches.isEmpty;
+  bool get isEmpty => matches.isEmpty;
 
   /// Returns true if there are matches.
-  bool get isNotEmpty => _matches.isNotEmpty;
+  bool get isNotEmpty => matches.isNotEmpty;
 
-  /// Pushes a match onto the list of matches.
-  void push(RouteMatch match) {
-    _matches.add(match);
+  /// Returns a new instance of RouteMatchList with the input `match` pushed
+  /// onto the current instance.
+  RouteMatchList push<T>(ImperativeRouteMatch<T> match) {
+    // Imperative route match doesn't change the uri and path parameters.
+    return _copyWith(matches: <RouteMatch>[...matches, match]);
   }
 
-  /// Removes the match from the list.
-  void remove(RouteMatch match) {
-    final int index = _matches.indexOf(match);
+  /// Returns a new instance of RouteMatchList with the input `match` removed
+  /// from the current instance.
+  RouteMatchList remove(RouteMatch match) {
+    final List<RouteMatch> newMatches = matches.toList();
+    final int index = newMatches.indexOf(match);
     assert(index != -1);
-    _matches.removeRange(index, _matches.length);
+    newMatches.removeRange(index, newMatches.length);
 
     // Also pop ShellRoutes when there are no subsequent route matches
-    while (_matches.isNotEmpty && _matches.last.route is ShellRoute) {
-      _matches.removeLast();
+    while (newMatches.isNotEmpty && newMatches.last.route is ShellRoute) {
+      newMatches.removeLast();
+    }
+    // Removing ImperativeRouteMatch should not change uri and pathParameters.
+    if (match is ImperativeRouteMatch) {
+      return _copyWith(matches: newMatches);
     }
 
     final String fullPath = _generateFullPath(
-        _matches.where((RouteMatch match) => match is! ImperativeRouteMatch));
+        newMatches.where((RouteMatch match) => match is! ImperativeRouteMatch));
     // Need to remove path parameters that are no longer in the fullPath.
     final List<String> newParameters = <String>[];
     patternToRegExp(fullPath, newParameters);
     final Set<String> validParameters = newParameters.toSet();
-    pathParameters.removeWhere(
-        (String key, String value) => !validParameters.contains(key));
-
-    _uri = _uri.replace(path: patternToPath(fullPath, pathParameters));
+    final Map<String, String> newPathParameters =
+        Map<String, String>.fromEntries(
+      pathParameters.entries.where((MapEntry<String, String> value) =>
+          validParameters.contains(value.key)),
+    );
+    final Uri newUri =
+        uri.replace(path: patternToPath(fullPath, newPathParameters));
+    return _copyWith(
+      matches: newMatches,
+      uri: newUri,
+      pathParameters: newPathParameters,
+    );
   }
 
   /// An optional object provided by the app during navigation.
-  Object? get extra => _matches.isEmpty ? null : _matches.last.extra;
+  Object? get extra => matches.isEmpty ? null : matches.last.extra;
 
   /// The last matching route.
-  RouteMatch get last => _matches.last;
-
-  /// The route matches.
-  List<RouteMatch> get matches => _matches;
+  RouteMatch get last => matches.last;
 
   /// Returns true if the current match intends to display an error screen.
   bool get isError => matches.length == 1 && matches.first.error != null;
@@ -170,9 +198,44 @@
   /// Returns the error that this match intends to display.
   Exception? get error => matches.first.error;
 
+  RouteMatchList _copyWith({
+    List<RouteMatch>? matches,
+    Uri? uri,
+    Map<String, String>? pathParameters,
+  }) {
+    return RouteMatchList(
+        matches: matches ?? this.matches,
+        uri: uri ?? this.uri,
+        pathParameters: pathParameters ?? this.pathParameters);
+  }
+
+  @override
+  bool operator ==(Object other) {
+    if (other.runtimeType != runtimeType) {
+      return false;
+    }
+    return other is RouteMatchList &&
+        const ListEquality<RouteMatch>().equals(matches, other.matches) &&
+        uri == other.uri &&
+        const MapEquality<String, String>()
+            .equals(pathParameters, other.pathParameters);
+  }
+
+  @override
+  int get hashCode {
+    return Object.hash(
+      Object.hashAll(matches),
+      uri,
+      Object.hashAllUnordered(
+        pathParameters.entries.map<int>((MapEntry<String, String> entry) =>
+            Object.hash(entry.key, entry.value)),
+      ),
+    );
+  }
+
   @override
   String toString() {
-    return '${objectRuntimeType(this, 'RouteMatchList')}($fullpath)';
+    return '${objectRuntimeType(this, 'RouteMatchList')}($fullPath)';
   }
 }
 
@@ -198,17 +261,17 @@
 /// For example, for a given `loc` `/a/b/c/d`, this function will return the
 /// list of [RouteBase] `[GoRouteA(), GoRouterB(), GoRouteC(), GoRouterD()]`.
 ///
-/// - [loc] is the complete URL to match (without the query parameters). For
-///   example, for the URL `/a/b?c=0`, [loc] will be `/a/b`.
-/// - [restLoc] is the remaining part of the URL to match while [parentSubloc]
+/// - [location] is the complete URL to match (without the query parameters). For
+///   example, for the URL `/a/b?c=0`, [location] will be `/a/b`.
+/// - [remainingLocation] is the remaining part of the URL to match while [matchedLocation]
 ///   is the part of the URL that has already been matched. For examples, for
-///   the URL `/a/b/c/d`, at some point, [restLoc] would be `/c/d` and
-///   [parentSubloc] will be `/a/b`.
-/// - [routes] are the possible [RouteBase] to match to [restLoc].
+///   the URL `/a/b/c/d`, at some point, [remainingLocation] would be `/c/d` and
+///   [matchedLocation] will be `/a/b`.
+/// - [routes] are the possible [RouteBase] to match to [remainingLocation].
 List<RouteMatch>? _getLocRouteRecursively({
-  required String loc,
-  required String restLoc,
-  required String parentSubloc,
+  required String location,
+  required String remainingLocation,
+  required String matchedLocation,
   required List<RouteBase> routes,
   required Map<String, String> pathParameters,
   required Object? extra,
@@ -221,8 +284,8 @@
 
     final RouteMatch? match = RouteMatch.match(
       route: route,
-      restLoc: restLoc,
-      parentSubloc: parentSubloc,
+      remainingLocation: remainingLocation,
+      matchedLocation: matchedLocation,
       pathParameters: subPathParameters,
       extra: extra,
     );
@@ -232,9 +295,9 @@
     }
 
     if (match.route is GoRoute &&
-        match.subloc.toLowerCase() == loc.toLowerCase()) {
+        match.matchedLocation.toLowerCase() == location.toLowerCase()) {
       // If it is a complete match, then return the matched route
-      // NOTE: need a lower case match because subloc is canonicalized to match
+      // NOTE: need a lower case match because matchedLocation is canonicalized to match
       // the path case whereas the location can be of any case and still match
       result = <RouteMatch>[match];
     } else if (route.routes.isEmpty) {
@@ -245,21 +308,21 @@
       final String childRestLoc;
       final String newParentSubLoc;
       if (match.route is ShellRoute) {
-        childRestLoc = restLoc;
-        newParentSubLoc = parentSubloc;
+        childRestLoc = remainingLocation;
+        newParentSubLoc = matchedLocation;
       } else {
-        assert(loc.startsWith(match.subloc));
-        assert(restLoc.isNotEmpty);
+        assert(location.startsWith(match.matchedLocation));
+        assert(remainingLocation.isNotEmpty);
 
-        childRestLoc =
-            loc.substring(match.subloc.length + (match.subloc == '/' ? 0 : 1));
-        newParentSubLoc = match.subloc;
+        childRestLoc = location.substring(match.matchedLocation.length +
+            (match.matchedLocation == '/' ? 0 : 1));
+        newParentSubLoc = match.matchedLocation;
       }
 
       final List<RouteMatch>? subRouteMatch = _getLocRouteRecursively(
-        loc: loc,
-        restLoc: childRestLoc,
-        parentSubloc: newParentSubLoc,
+        location: location,
+        remainingLocation: childRestLoc,
+        matchedLocation: newParentSubLoc,
         routes: route.routes,
         pathParameters: subPathParameters,
         extra: extra,
@@ -284,20 +347,21 @@
 RouteMatchList errorScreen(Uri uri, String errorMessage) {
   final Exception error = Exception(errorMessage);
   return RouteMatchList(
-      <RouteMatch>[
-        RouteMatch(
-          subloc: uri.path,
-          extra: null,
-          error: error,
-          route: GoRoute(
-            path: uri.toString(),
-            pageBuilder: (BuildContext context, GoRouterState state) {
-              throw UnimplementedError();
-            },
-          ),
-          pageKey: const ValueKey<String>('error'),
+    matches: <RouteMatch>[
+      RouteMatch(
+        matchedLocation: uri.path,
+        extra: null,
+        error: error,
+        route: GoRoute(
+          path: uri.toString(),
+          pageBuilder: (BuildContext context, GoRouterState state) {
+            throw UnimplementedError();
+          },
         ),
-      ],
-      uri,
-      const <String, String>{});
+        pageKey: const ValueKey<String>('error'),
+      ),
+    ],
+    uri: uri,
+    pathParameters: const <String, String>{},
+  );
 }
diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart
index 47f5b08..05dbd0f 100644
--- a/packages/go_router/lib/src/misc/extensions.dart
+++ b/packages/go_router/lib/src/misc/extensions.dart
@@ -12,11 +12,11 @@
   /// Get a location from route name and parameters.
   String namedLocation(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
   }) =>
-      GoRouter.of(this)
-          .namedLocation(name, params: params, queryParams: queryParams);
+      GoRouter.of(this).namedLocation(name,
+          pathParameters: pathParameters, queryParameters: queryParameters);
 
   /// Navigate to a location.
   void go(String location, {Object? extra}) =>
@@ -25,14 +25,14 @@
   /// Navigate to a named route.
   void goNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       GoRouter.of(this).goNamed(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: pathParameters,
+        queryParameters: queryParameters,
         extra: extra,
       );
 
@@ -50,14 +50,14 @@
   /// Navigate to a named route onto the page stack.
   Future<T?> pushNamed<T extends Object?>(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       GoRouter.of(this).pushNamed<T>(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: pathParameters,
+        queryParameters: queryParameters,
         extra: extra,
       );
 
@@ -81,7 +81,7 @@
       GoRouter.of(this).pushReplacement(location, extra: extra);
 
   /// Replaces the top-most page of the page stack with the named route w/
-  /// optional parameters, e.g. `name='person', params={'fid': 'f2', 'pid':
+  /// optional parameters, e.g. `name='person', pathParameters={'fid': 'f2', 'pid':
   /// 'p1'}`.
   ///
   /// See also:
@@ -89,14 +89,14 @@
   /// * [pushNamed] which pushes a named route onto the page stack.
   void pushReplacementNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       GoRouter.of(this).pushReplacementNamed(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: pathParameters,
+        queryParameters: queryParameters,
         extra: extra,
       );
 
@@ -117,8 +117,8 @@
   /// preserving the page key.
   ///
   /// This will preserve the state and not run any page animation. Optional
-  /// parameters can be providded to the named route, e.g. `name='person',
-  /// params={'fid': 'f2', 'pid': 'p1'}`.
+  /// parameters can be provided to the named route, e.g. `name='person',
+  /// pathParameters={'fid': 'f2', 'pid': 'p1'}`.
   ///
   /// See also:
   /// * [pushNamed] which pushes the given location onto the page stack.
@@ -126,8 +126,8 @@
   ///   stack but always uses a new page key.
   void replaceNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       GoRouter.of(this).replaceNamed(name, extra: extra);
diff --git a/packages/go_router/lib/src/parser.dart b/packages/go_router/lib/src/parser.dart
index a888daf..7fd00cf 100644
--- a/packages/go_router/lib/src/parser.dart
+++ b/packages/go_router/lib/src/parser.dart
@@ -8,7 +8,6 @@
 import 'package:flutter/widgets.dart';
 
 import 'configuration.dart';
-import 'delegate.dart';
 import 'information_provider.dart';
 import 'logging.dart';
 import 'match.dart';
@@ -72,12 +71,12 @@
       // If there is a matching error for the initial location, we should
       // still try to process the top-level redirects.
       initialMatches = RouteMatchList(
-        <RouteMatch>[],
+        matches: const <RouteMatch>[],
         // TODO(chunhtai): remove this ignore and migrate the code
         // https://github.com/flutter/flutter/issues/124045.
         // ignore: deprecated_member_use, unnecessary_non_null_assertion
-        Uri.parse(canonicalUri(routeInformation.location!)),
-        const <String, String>{},
+        uri: Uri.parse(canonicalUri(routeInformation.location!)),
+        pathParameters: const <String, String>{},
       );
     }
     Future<RouteMatchList> processRedirectorResult(RouteMatchList matches) {
diff --git a/packages/go_router/lib/src/redirection.dart b/packages/go_router/lib/src/redirection.dart
index 3ebef5c..3ac4a5b 100644
--- a/packages/go_router/lib/src/redirection.dart
+++ b/packages/go_router/lib/src/redirection.dart
@@ -96,8 +96,8 @@
         name: null,
         // No name available at the top level trim the query params off the
         // sub-location to match route.redirect
-        subloc: prevMatchList.uri.path,
-        queryParams: prevMatchList.uri.queryParameters,
+        matchedLocation: prevMatchList.uri.path,
+        queryParameters: prevMatchList.uri.queryParameters,
         queryParametersAll: prevMatchList.uri.queryParametersAll,
         extra: extra,
         pageKey: const ValueKey<String>('topLevel'),
@@ -138,13 +138,13 @@
       GoRouterState(
         configuration,
         location: matchList.uri.toString(),
-        subloc: match.subloc,
+        matchedLocation: match.matchedLocation,
         name: route.name,
         path: route.path,
-        fullpath: matchList.fullpath,
+        fullPath: matchList.fullPath,
         extra: match.extra,
-        params: matchList.pathParameters,
-        queryParams: matchList.uri.queryParameters,
+        pathParameters: matchList.pathParameters,
+        queryParameters: matchList.uri.queryParameters,
         queryParametersAll: matchList.uri.queryParametersAll,
         pageKey: match.pageKey,
       ),
diff --git a/packages/go_router/lib/src/route.dart b/packages/go_router/lib/src/route.dart
index 7f4b9c1..21e8053 100644
--- a/packages/go_router/lib/src/route.dart
+++ b/packages/go_router/lib/src/route.dart
@@ -42,7 +42,7 @@
 ///         GoRoute(
 ///           path: 'family/:fid',
 ///           pageBuilder: (BuildContext context, GoRouterState state) {
-///             final Family family = Families.family(state.params['fid']!);
+///             final Family family = Families.family(state.pathParameters['fid']!);
 ///             return MaterialPage<void>(
 ///               key: state.pageKey,
 ///               child: FamilyPage(family: family),
@@ -52,8 +52,8 @@
 ///             GoRoute(
 ///               path: 'person/:pid',
 ///               pageBuilder: (BuildContext context, GoRouterState state) {
-///                 final Family family = Families.family(state.params['fid']!);
-///                 final Person person = family.person(state.params['pid']!);
+///                 final Family family = Families.family(state.pathParameters['fid']!);
+///                 final Person person = family.person(state.pathParameters['pid']!);
 ///                 return MaterialPage<void>(
 ///                   key: state.pageKey,
 ///                   child: PersonPage(family: family, person: person),
@@ -137,7 +137,7 @@
             'builder, pageBuilder, or redirect must be provided'),
         super._() {
     // cache the path regexp and parameters
-    _pathRE = patternToRegExp(path, pathParams);
+    _pathRE = patternToRegExp(path, pathParameters);
   }
 
   /// Optional name of the route.
@@ -169,8 +169,8 @@
   ///
   /// context.go(
   ///   context.namedLocation('family'),
-  ///   params: <String, String>{'fid': 123},
-  ///   queryParams: <String, String>{'qid': 'quid'},
+  ///   pathParameters: <String, String>{'fid': 123},
+  ///   queryParameters: <String, String>{'qid': 'quid'},
   /// );
   /// ```
   ///
@@ -228,7 +228,7 @@
   ///   path: '/',
   ///   builder: (BuildContext context, GoRouterState state) => FamilyPage(
   ///     families: Families.family(
-  ///       state.params['id'],
+  ///       state.pathParameters['id'],
   ///     ),
   ///   ),
   /// ),
@@ -306,11 +306,11 @@
 
   /// Extract the path parameters from a match.
   Map<String, String> extractPathParams(RegExpMatch match) =>
-      extractPathParameters(pathParams, match);
+      extractPathParameters(pathParameters, match);
 
   /// The path parameters in this route.
   @internal
-  final List<String> pathParams = <String>[];
+  final List<String> pathParameters = <String>[];
 
   @override
   String toString() {
diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart
index 134c46e..e9b4ec6 100644
--- a/packages/go_router/lib/src/router.dart
+++ b/packages/go_router/lib/src/router.dart
@@ -8,6 +8,7 @@
 import 'delegate.dart';
 import 'information_provider.dart';
 import 'logging.dart';
+import 'match.dart';
 import 'matching.dart';
 import 'misc/inherited_router.dart';
 import 'parser.dart';
@@ -179,13 +180,13 @@
   /// This is useful for redirecting to a named location.
   String namedLocation(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
   }) =>
       _routeInformationParser.configuration.namedLocation(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: pathParameters,
+        queryParameters: queryParameters,
       );
 
   /// Navigate to a URI location w/ optional query parameters, e.g.
@@ -203,16 +204,17 @@
   }
 
   /// Navigate to a named route w/ optional parameters, e.g.
-  /// `name='person', params={'fid': 'f2', 'pid': 'p1'}`
+  /// `name='person', pathParameters={'fid': 'f2', 'pid': 'p1'}`
   /// Navigate to the named route.
   void goNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       go(
-        namedLocation(name, params: params, queryParams: queryParams),
+        namedLocation(name,
+            pathParameters: pathParameters, queryParameters: queryParameters),
         extra: extra,
       );
 
@@ -245,15 +247,16 @@
   }
 
   /// Push a named route onto the page stack w/ optional parameters, e.g.
-  /// `name='person', params={'fid': 'f2', 'pid': 'p1'}`
+  /// `name='person', pathParameters={'fid': 'f2', 'pid': 'p1'}`
   Future<T?> pushNamed<T extends Object?>(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) =>
       push<T>(
-        namedLocation(name, params: params, queryParams: queryParams),
+        namedLocation(name,
+            pathParameters: pathParameters, queryParameters: queryParameters),
         extra: extra,
       );
 
@@ -283,7 +286,7 @@
   }
 
   /// Replaces the top-most page of the page stack with the named route w/
-  /// optional parameters, e.g. `name='person', params={'fid': 'f2', 'pid':
+  /// optional parameters, e.g. `name='person', pathParameters={'fid': 'f2', 'pid':
   /// 'p1'}`.
   ///
   /// See also:
@@ -291,12 +294,13 @@
   /// * [pushNamed] which pushes a named route onto the page stack.
   void pushReplacementNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) {
     pushReplacement(
-      namedLocation(name, params: params, queryParams: queryParams),
+      namedLocation(name,
+          pathParameters: pathParameters, queryParameters: queryParameters),
       extra: extra,
     );
   }
@@ -332,7 +336,7 @@
   ///
   /// This will preserve the state and not run any page animation. Optional
   /// parameters can be providded to the named route, e.g. `name='person',
-  /// params={'fid': 'f2', 'pid': 'p1'}`.
+  /// pathParameters={'fid': 'f2', 'pid': 'p1'}`.
   ///
   /// See also:
   /// * [pushNamed] which pushes the given location onto the page stack.
@@ -340,12 +344,13 @@
   ///   stack but always uses a new page key.
   void replaceNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) {
     replace(
-      namedLocation(name, params: params, queryParams: queryParams),
+      namedLocation(name,
+          pathParameters: pathParameters, queryParameters: queryParameters),
       extra: extra,
     );
   }
diff --git a/packages/go_router/lib/src/state.dart b/packages/go_router/lib/src/state.dart
index 57c68a2..c360cef 100644
--- a/packages/go_router/lib/src/state.dart
+++ b/packages/go_router/lib/src/state.dart
@@ -16,12 +16,12 @@
   const GoRouterState(
     this._configuration, {
     required this.location,
-    required this.subloc,
+    required this.matchedLocation,
     required this.name,
     this.path,
-    this.fullpath,
-    this.params = const <String, String>{},
-    this.queryParams = const <String, String>{},
+    this.fullPath,
+    this.pathParameters = const <String, String>{},
+    this.queryParameters = const <String, String>{},
     this.queryParametersAll = const <String, List<String>>{},
     this.extra,
     this.error,
@@ -35,8 +35,15 @@
   /// The full location of the route, e.g. /family/f2/person/p1
   final String location;
 
-  /// The location of this sub-route, e.g. /family/f2
-  final String subloc;
+  /// The matched location until this point.
+  ///
+  /// For example:
+  ///
+  /// location = /family/f2/person/p1
+  /// route = GoRoute('/family/:id')
+  ///
+  /// matchedLocation = /family/f2
+  final String matchedLocation;
 
   /// The optional name of the route.
   final String? name;
@@ -45,13 +52,13 @@
   final String? path;
 
   /// The full path to this sub-route, e.g. /family/:fid
-  final String? fullpath;
+  final String? fullPath;
 
   /// The parameters for this sub-route, e.g. {'fid': 'f2'}
-  final Map<String, String> params;
+  final Map<String, String> pathParameters;
 
   /// The query parameters for the location, e.g. {'from': '/family/f2'}
-  final Map<String, String> queryParams;
+  final Map<String, String> queryParameters;
 
   /// The query parameters for the location,
   /// e.g. `{'q1': ['v1'], 'q2': ['v2', 'v3']}`
@@ -98,7 +105,7 @@
   /// class MyWidget extends StatelessWidget {
   ///   @override
   ///   Widget build(BuildContext context) {
-  ///     return Text('${GoRouterState.of(context).params['id']}');
+  ///     return Text('${GoRouterState.of(context).pathParameters['id']}');
   ///   }
   /// }
   /// ```
@@ -125,26 +132,27 @@
 
   /// Get a location from route name and parameters.
   /// This is useful for redirecting to a named location.
-  @Deprecated('Use GoRouter.of(context).namedLocation instead')
+  // TODO(chunhtai): remove this method when go_router can provide a way to
+  // look up named location during redirect.
   String namedLocation(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, String> queryParams = const <String, String>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, String> queryParameters = const <String, String>{},
   }) {
     return _configuration.namedLocation(name,
-        params: params, queryParams: queryParams);
+        pathParameters: pathParameters, queryParameters: queryParameters);
   }
 
   @override
   bool operator ==(Object other) {
     return other is GoRouterState &&
         other.location == location &&
-        other.subloc == subloc &&
+        other.matchedLocation == matchedLocation &&
         other.name == name &&
         other.path == path &&
-        other.fullpath == fullpath &&
-        other.params == params &&
-        other.queryParams == queryParams &&
+        other.fullPath == fullPath &&
+        other.pathParameters == pathParameters &&
+        other.queryParameters == queryParameters &&
         other.queryParametersAll == queryParametersAll &&
         other.extra == extra &&
         other.error == error &&
@@ -152,8 +160,18 @@
   }
 
   @override
-  int get hashCode => Object.hash(location, subloc, name, path, fullpath,
-      params, queryParams, queryParametersAll, extra, error, pageKey);
+  int get hashCode => Object.hash(
+      location,
+      matchedLocation,
+      name,
+      path,
+      fullPath,
+      pathParameters,
+      queryParameters,
+      queryParametersAll,
+      extra,
+      error,
+      pageKey);
 }
 
 /// An inherited widget to host a [GoRouterStateRegistry] for the subtree.
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index bf4b672..4d1cb1f 100644
--- a/packages/go_router/pubspec.yaml
+++ b/packages/go_router/pubspec.yaml
@@ -1,7 +1,7 @@
 name: go_router
 description: A declarative router for Flutter based on Navigation 2 supporting
   deep linking, data-driven routes and more
-version: 6.5.9
+version: 7.0.0
 repository: https://github.com/flutter/packages/tree/main/packages/go_router
 issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router%22
 
@@ -21,3 +21,4 @@
 dev_dependencies:
   flutter_test:
     sdk: flutter
+  path: ^1.8.2
diff --git a/packages/go_router/test/builder_test.dart b/packages/go_router/test/builder_test.dart
index 04e7543..81f4182 100644
--- a/packages/go_router/test/builder_test.dart
+++ b/packages/go_router/test/builder_test.dart
@@ -29,17 +29,17 @@
       );
 
       final RouteMatchList matches = RouteMatchList(
-          <RouteMatch>[
+          matches: <RouteMatch>[
             RouteMatch(
               route: config.routes.first as GoRoute,
-              subloc: '/',
+              matchedLocation: '/',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>('/'),
             ),
           ],
-          Uri.parse('/'),
-          const <String, String>{});
+          uri: Uri.parse('/'),
+          pathParameters: const <String, String>{});
 
       await tester.pumpWidget(
         _BuilderTestWidget(
@@ -76,17 +76,17 @@
       );
 
       final RouteMatchList matches = RouteMatchList(
-          <RouteMatch>[
+          matches: <RouteMatch>[
             RouteMatch(
               route: config.routes.first,
-              subloc: '/',
+              matchedLocation: '/',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>('/'),
             ),
           ],
-          Uri.parse('/'),
-          <String, String>{});
+          uri: Uri.parse('/'),
+          pathParameters: const <String, String>{});
 
       await tester.pumpWidget(
         _BuilderTestWidget(
@@ -118,17 +118,17 @@
       );
 
       final RouteMatchList matches = RouteMatchList(
-          <RouteMatch>[
+          matches: <RouteMatch>[
             RouteMatch(
               route: config.routes.first as GoRoute,
-              subloc: '/',
+              matchedLocation: '/',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>('/'),
             ),
           ],
-          Uri.parse('/'),
-          <String, String>{});
+          uri: Uri.parse('/'),
+          pathParameters: const <String, String>{});
 
       await tester.pumpWidget(
         _BuilderTestWidget(
@@ -173,24 +173,24 @@
       );
 
       final RouteMatchList matches = RouteMatchList(
-          <RouteMatch>[
+          matches: <RouteMatch>[
             RouteMatch(
               route: config.routes.first,
-              subloc: '',
+              matchedLocation: '',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>(''),
             ),
             RouteMatch(
               route: config.routes.first.routes.first,
-              subloc: '/details',
+              matchedLocation: '/details',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>('/details'),
             ),
           ],
-          Uri.parse('/details'),
-          <String, String>{});
+          uri: Uri.parse('/details'),
+          pathParameters: const <String, String>{});
 
       await tester.pumpWidget(
         _BuilderTestWidget(
@@ -248,17 +248,17 @@
       );
 
       final RouteMatchList matches = RouteMatchList(
-          <RouteMatch>[
+          matches: <RouteMatch>[
             RouteMatch(
               route: config.routes.first.routes.first as GoRoute,
-              subloc: '/a/details',
+              matchedLocation: '/a/details',
               extra: null,
               error: null,
               pageKey: const ValueKey<String>('/a/details'),
             ),
           ],
-          Uri.parse('/a/details'),
-          <String, String>{});
+          uri: Uri.parse('/a/details'),
+          pathParameters: const <String, String>{});
 
       await tester.pumpWidget(
         _BuilderTestWidget(
diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart
index e40084a..a0533a1 100644
--- a/packages/go_router/test/delegate_test.dart
+++ b/packages/go_router/test/delegate_test.dart
@@ -5,7 +5,6 @@
 import 'package:flutter/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:go_router/go_router.dart';
-import 'package:go_router/src/delegate.dart';
 import 'package:go_router/src/match.dart';
 import 'package:go_router/src/misc/error_screen.dart';
 
diff --git a/packages/go_router/test/go_router_state_test.dart b/packages/go_router/test/go_router_state_test.dart
index 59cee73..b1d0eb5 100644
--- a/packages/go_router/test/go_router_state_test.dart
+++ b/packages/go_router/test/go_router_state_test.dart
@@ -17,13 +17,13 @@
             path: '/',
             builder: (BuildContext context, _) {
               final GoRouterState state = GoRouterState.of(context);
-              return Text('/ ${state.queryParams['p']}');
+              return Text('/ ${state.queryParameters['p']}');
             }),
         GoRoute(
             path: '/a',
             builder: (BuildContext context, _) {
               final GoRouterState state = GoRouterState.of(context);
-              return Text('/a ${state.queryParams['p']}');
+              return Text('/a ${state.queryParameters['p']}');
             }),
       ];
       final GoRouter router = await createRouter(routes, tester);
@@ -83,7 +83,7 @@
                   builder: (_, __) {
                     return Builder(builder: (BuildContext context) {
                       return Text(
-                          '2 ${GoRouterState.of(context).params['id']}');
+                          '2 ${GoRouterState.of(context).pathParameters['id']}');
                     });
                   }),
             ]),
diff --git a/packages/go_router/test/go_router_test.dart b/packages/go_router/test/go_router_test.dart
index dca1199..a93b492 100644
--- a/packages/go_router/test/go_router_test.dart
+++ b/packages/go_router/test/go_router_test.dart
@@ -11,7 +11,6 @@
 import 'package:flutter/services.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:go_router/go_router.dart';
-import 'package:go_router/src/delegate.dart';
 import 'package:go_router/src/match.dart';
 import 'package:go_router/src/matching.dart';
 import 'package:logging/logging.dart';
@@ -152,7 +151,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches, hasLength(1));
-      expect(matches.first.subloc, '/login');
+      expect(matches.first.matchedLocation, '/login');
       expect(find.byType(LoginScreen), findsOneWidget);
     });
 
@@ -181,7 +180,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches, hasLength(1));
-      expect(matches.first.subloc, '/login');
+      expect(matches.first.matchedLocation, '/login');
       expect(find.byType(LoginScreen), findsOneWidget);
     });
 
@@ -205,7 +204,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches, hasLength(1));
-      expect(matches.first.subloc, '/login');
+      expect(matches.first.matchedLocation, '/login');
       expect(find.byType(LoginScreen), findsOneWidget);
     });
 
@@ -224,7 +223,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches, hasLength(1));
-      expect(matches.first.subloc, '/profile/foo');
+      expect(matches.first.matchedLocation, '/profile/foo');
       expect(find.byType(DummyScreen), findsOneWidget);
     });
 
@@ -243,7 +242,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches, hasLength(1));
-      expect(matches.first.subloc, '/profile/foo');
+      expect(matches.first.matchedLocation, '/profile/foo');
       expect(find.byType(DummyScreen), findsOneWidget);
     });
 
@@ -355,9 +354,9 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
       expect(matches.length, 2);
-      expect(matches.first.subloc, '/');
+      expect(matches.first.matchedLocation, '/');
       expect(find.byType(HomeScreen, skipOffstage: false), findsOneWidget);
-      expect(matches[1].subloc, '/login');
+      expect(matches[1].matchedLocation, '/login');
       expect(find.byType(LoginScreen), findsOneWidget);
     });
 
@@ -402,9 +401,9 @@
       {
         final RouteMatchList matches = router.routerDelegate.matches;
         expect(matches.matches.length, 2);
-        expect(matches.matches.first.subloc, '/');
+        expect(matches.matches.first.matchedLocation, '/');
         expect(find.byType(HomeScreen, skipOffstage: false), findsOneWidget);
-        expect(matches.matches[1].subloc, '/login');
+        expect(matches.matches[1].matchedLocation, '/login');
         expect(find.byType(LoginScreen), findsOneWidget);
       }
 
@@ -413,9 +412,9 @@
       {
         final RouteMatchList matches = router.routerDelegate.matches;
         expect(matches.matches.length, 2);
-        expect(matches.matches.first.subloc, '/');
+        expect(matches.matches.first.matchedLocation, '/');
         expect(find.byType(HomeScreen, skipOffstage: false), findsOneWidget);
-        expect(matches.matches[1].subloc, '/family/f2');
+        expect(matches.matches[1].matchedLocation, '/family/f2');
         expect(find.byType(FamilyScreen), findsOneWidget);
       }
 
@@ -424,11 +423,11 @@
       {
         final RouteMatchList matches = router.routerDelegate.matches;
         expect(matches.matches.length, 3);
-        expect(matches.matches.first.subloc, '/');
+        expect(matches.matches.first.matchedLocation, '/');
         expect(find.byType(HomeScreen, skipOffstage: false), findsOneWidget);
-        expect(matches.matches[1].subloc, '/family/f2');
+        expect(matches.matches[1].matchedLocation, '/family/f2');
         expect(find.byType(FamilyScreen, skipOffstage: false), findsOneWidget);
-        expect(matches.matches[2].subloc, '/family/f2/person/p1');
+        expect(matches.matches[2].matchedLocation, '/family/f2/person/p1');
         expect(find.byType(PersonScreen), findsOneWidget);
       }
     });
@@ -494,11 +493,11 @@
           path: '/',
           builder: (BuildContext context, GoRouterState state) {
             expect(state.location, '/');
-            expect(state.subloc, '/');
+            expect(state.matchedLocation, '/');
             expect(state.name, 'home');
             expect(state.path, '/');
-            expect(state.fullpath, '/');
-            expect(state.params, <String, String>{});
+            expect(state.fullPath, '/');
+            expect(state.pathParameters, <String, String>{});
             expect(state.error, null);
             if (state.extra != null) {
               expect(state.extra! as int, 1);
@@ -511,11 +510,11 @@
               path: 'login',
               builder: (BuildContext context, GoRouterState state) {
                 expect(state.location, '/login');
-                expect(state.subloc, '/login');
+                expect(state.matchedLocation, '/login');
                 expect(state.name, 'login');
                 expect(state.path, 'login');
-                expect(state.fullpath, '/login');
-                expect(state.params, <String, String>{});
+                expect(state.fullPath, '/login');
+                expect(state.pathParameters, <String, String>{});
                 expect(state.error, null);
                 expect(state.extra! as int, 2);
                 return const LoginScreen();
@@ -529,14 +528,14 @@
                   state.location,
                   anyOf(<String>['/family/f2', '/family/f2/person/p1']),
                 );
-                expect(state.subloc, '/family/f2');
+                expect(state.matchedLocation, '/family/f2');
                 expect(state.name, 'family');
                 expect(state.path, 'family/:fid');
-                expect(state.fullpath, '/family/:fid');
-                expect(state.params, <String, String>{'fid': 'f2'});
+                expect(state.fullPath, '/family/:fid');
+                expect(state.pathParameters, <String, String>{'fid': 'f2'});
                 expect(state.error, null);
                 expect(state.extra! as int, 3);
-                return FamilyScreen(state.params['fid']!);
+                return FamilyScreen(state.pathParameters['fid']!);
               },
               routes: <GoRoute>[
                 GoRoute(
@@ -544,18 +543,18 @@
                   path: 'person/:pid',
                   builder: (BuildContext context, GoRouterState state) {
                     expect(state.location, '/family/f2/person/p1');
-                    expect(state.subloc, '/family/f2/person/p1');
+                    expect(state.matchedLocation, '/family/f2/person/p1');
                     expect(state.name, 'person');
                     expect(state.path, 'person/:pid');
-                    expect(state.fullpath, '/family/:fid/person/:pid');
+                    expect(state.fullPath, '/family/:fid/person/:pid');
                     expect(
-                      state.params,
+                      state.pathParameters,
                       <String, String>{'fid': 'f2', 'pid': 'p1'},
                     );
                     expect(state.error, null);
                     expect(state.extra! as int, 4);
-                    return PersonScreen(
-                        state.params['fid']!, state.params['pid']!);
+                    return PersonScreen(state.pathParameters['fid']!,
+                        state.pathParameters['pid']!);
                   },
                 ),
               ],
@@ -585,7 +584,7 @@
         GoRoute(
           path: '/family/:fid',
           builder: (BuildContext context, GoRouterState state) =>
-              FamilyScreen(state.params['fid']!),
+              FamilyScreen(state.pathParameters['fid']!),
         ),
       ];
 
@@ -595,7 +594,7 @@
       await tester.pumpAndSettle();
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
 
-      // NOTE: match the lower case, since subloc is canonicalized to match the
+      // NOTE: match the lower case, since location is canonicalized to match the
       // path case whereas the location can be any case; so long as the path
       // produces a match regardless of the location case, we win!
       expect(router.location.toLowerCase(), loc.toLowerCase());
@@ -1321,7 +1320,7 @@
                   name: 'person',
                   path: 'person/:pid',
                   builder: (BuildContext context, GoRouterState state) {
-                    expect(state.params,
+                    expect(state.pathParameters,
                         <String, String>{'fid': 'f2', 'pid': 'p1'});
                     return const PersonScreen('dummy', 'dummy');
                   },
@@ -1334,7 +1333,7 @@
 
       final GoRouter router = await createRouter(routes, tester);
       router.goNamed('person',
-          params: <String, String>{'fid': 'f2', 'pid': 'p1'});
+          pathParameters: <String, String>{'fid': 'f2', 'pid': 'p1'});
     });
 
     testWidgets('too few params', (WidgetTester tester) async {
@@ -1364,7 +1363,7 @@
       ];
       await expectLater(() async {
         final GoRouter router = await createRouter(routes, tester);
-        router.goNamed('person', params: <String, String>{'fid': 'f2'});
+        router.goNamed('person', pathParameters: <String, String>{'fid': 'f2'});
         await tester.pump();
       }, throwsA(isAssertionError));
     });
@@ -1388,7 +1387,7 @@
                   name: 'PeRsOn',
                   path: 'person/:pid',
                   builder: (BuildContext context, GoRouterState state) {
-                    expect(state.params,
+                    expect(state.pathParameters,
                         <String, String>{'fid': 'f2', 'pid': 'p1'});
                     return const PersonScreen('dummy', 'dummy');
                   },
@@ -1401,7 +1400,7 @@
 
       final GoRouter router = await createRouter(routes, tester);
       router.goNamed('person',
-          params: <String, String>{'fid': 'f2', 'pid': 'p1'});
+          pathParameters: <String, String>{'fid': 'f2', 'pid': 'p1'});
     });
 
     testWidgets('too few params', (WidgetTester tester) async {
@@ -1431,7 +1430,7 @@
       await expectLater(() async {
         final GoRouter router = await createRouter(routes, tester);
         router.goNamed('family',
-            params: <String, String>{'fid': 'f2', 'pid': 'p1'});
+            pathParameters: <String, String>{'fid': 'f2', 'pid': 'p1'});
       }, throwsA(isAssertionError));
     });
 
@@ -1445,7 +1444,7 @@
         GoRoute(
           path: '/family/:fid',
           builder: (BuildContext context, GoRouterState state) => FamilyScreen(
-            state.params['fid']!,
+            state.pathParameters['fid']!,
           ),
           routes: <GoRoute>[
             GoRoute(
@@ -1453,8 +1452,8 @@
               path: 'person:pid',
               builder: (BuildContext context, GoRouterState state) =>
                   PersonScreen(
-                state.params['fid']!,
-                state.params['pid']!,
+                state.pathParameters['fid']!,
+                state.pathParameters['pid']!,
               ),
             ),
           ],
@@ -1463,7 +1462,7 @@
 
       final GoRouter router = await createRouter(routes, tester);
       router.goNamed('person',
-          params: <String, String>{'fid': 'f2', 'pid': 'p1'});
+          pathParameters: <String, String>{'fid': 'f2', 'pid': 'p1'});
       await tester.pumpAndSettle();
       expect(find.byType(PersonScreen), findsOneWidget);
     });
@@ -1476,15 +1475,15 @@
           name: 'page1',
           path: '/page1/:param1',
           builder: (BuildContext c, GoRouterState s) {
-            expect(s.params['param1'], param1);
+            expect(s.pathParameters['param1'], param1);
             return const DummyScreen();
           },
         ),
       ];
 
       final GoRouter router = await createRouter(routes, tester);
-      final String loc = router
-          .namedLocation('page1', params: <String, String>{'param1': param1});
+      final String loc = router.namedLocation('page1',
+          pathParameters: <String, String>{'param1': param1});
       router.go(loc);
       await tester.pumpAndSettle();
 
@@ -1501,7 +1500,7 @@
           name: 'page1',
           path: '/page1',
           builder: (BuildContext c, GoRouterState s) {
-            expect(s.queryParams['param1'], param1);
+            expect(s.queryParameters['param1'], param1);
             return const DummyScreen();
           },
         ),
@@ -1509,7 +1508,7 @@
 
       final GoRouter router = await createRouter(routes, tester);
       final String loc = router.namedLocation('page1',
-          queryParams: <String, String>{'param1': param1});
+          queryParameters: <String, String>{'param1': param1});
       router.go(loc);
       await tester.pumpAndSettle();
       final RouteMatchList matches = router.routerDelegate.matches;
@@ -1542,7 +1541,7 @@
       final GoRouter router = await createRouter(routes, tester,
           redirect: (BuildContext context, GoRouterState state) {
         redirected = true;
-        return state.subloc == '/login' ? null : '/login';
+        return state.matchedLocation == '/login' ? null : '/login';
       });
 
       expect(router.location, '/login');
@@ -1617,7 +1616,9 @@
         routes,
         tester,
         redirect: (BuildContext context, GoRouterState state) =>
-            state.subloc == '/login' ? null : state.namedLocation('login'),
+            state.matchedLocation == '/login'
+                ? null
+                : state.namedLocation('login'),
       );
       expect(router.location, '/login');
     });
@@ -1682,7 +1683,7 @@
       final GoRouter router = await createRouter(routes, tester,
           redirect: (BuildContext context, GoRouterState state) {
         redirected = true;
-        return state.subloc == '/login' ? null : '/login';
+        return state.matchedLocation == '/login' ? null : '/login';
       });
       redirected = false;
       // Directly set the url through platform message.
@@ -1750,7 +1751,7 @@
 
       final GoRouter router = await createRouter(routes, tester,
           redirect: (BuildContext context, GoRouterState state) =>
-              state.subloc == '/dummy1' ? '/dummy2' : null);
+              state.matchedLocation == '/dummy1' ? '/dummy2' : null);
       router.go('/dummy1');
       await tester.pump();
       expect(router.location, '/');
@@ -1759,9 +1760,9 @@
     testWidgets('top-level redirect loop', (WidgetTester tester) async {
       final GoRouter router = await createRouter(<GoRoute>[], tester,
           redirect: (BuildContext context, GoRouterState state) =>
-              state.subloc == '/'
+              state.matchedLocation == '/'
                   ? '/login'
-                  : state.subloc == '/login'
+                  : state.matchedLocation == '/login'
                       ? '/'
                       : null);
 
@@ -1809,7 +1810,7 @@
         ],
         tester,
         redirect: (BuildContext context, GoRouterState state) =>
-            state.subloc == '/' ? '/login' : null,
+            state.matchedLocation == '/' ? '/login' : null,
       );
 
       final List<RouteMatch> matches = router.routerDelegate.matches.matches;
@@ -1826,9 +1827,9 @@
         <GoRoute>[],
         tester,
         redirect: (BuildContext context, GoRouterState state) =>
-            state.subloc == '/'
+            state.matchedLocation == '/'
                 ? '/login?from=${state.location}'
-                : state.subloc == '/login'
+                : state.matchedLocation == '/login'
                     ? '/'
                     : null,
       );
@@ -1841,7 +1842,7 @@
       expect(screen.ex, isNotNull);
     });
 
-    testWidgets('expect null path/fullpath on top-level redirect',
+    testWidgets('expect null path/fullPath on top-level redirect',
         (WidgetTester tester) async {
       final List<GoRoute> routes = <GoRoute>[
         GoRoute(
@@ -1884,12 +1885,12 @@
         initialLocation: '/login?from=/',
         redirect: (BuildContext context, GoRouterState state) {
           expect(Uri.parse(state.location).queryParameters, isNotEmpty);
-          expect(Uri.parse(state.subloc).queryParameters, isEmpty);
+          expect(Uri.parse(state.matchedLocation).queryParameters, isEmpty);
           expect(state.path, isNull);
-          expect(state.fullpath, isNull);
-          expect(state.params.length, 0);
-          expect(state.queryParams.length, 1);
-          expect(state.queryParams['from'], '/');
+          expect(state.fullPath, isNull);
+          expect(state.pathParameters.length, 0);
+          expect(state.queryParameters.length, 1);
+          expect(state.queryParameters['from'], '/');
           return null;
         },
       );
@@ -1906,11 +1907,11 @@
           path: '/book/:bookId',
           redirect: (BuildContext context, GoRouterState state) {
             expect(state.location, loc);
-            expect(state.subloc, loc);
+            expect(state.matchedLocation, loc);
             expect(state.path, '/book/:bookId');
-            expect(state.fullpath, '/book/:bookId');
-            expect(state.params, <String, String>{'bookId': '0'});
-            expect(state.queryParams.length, 0);
+            expect(state.fullPath, '/book/:bookId');
+            expect(state.pathParameters, <String, String>{'bookId': '0'});
+            expect(state.queryParameters.length, 0);
             return null;
           },
           builder: (BuildContext c, GoRouterState s) => const HomeScreen(),
@@ -1938,18 +1939,18 @@
             GoRoute(
               path: 'family/:fid',
               builder: (BuildContext c, GoRouterState s) =>
-                  FamilyScreen(s.params['fid']!),
+                  FamilyScreen(s.pathParameters['fid']!),
               routes: <GoRoute>[
                 GoRoute(
                   path: 'person/:pid',
                   redirect: (BuildContext context, GoRouterState s) {
-                    expect(s.params['fid'], 'f2');
-                    expect(s.params['pid'], 'p1');
+                    expect(s.pathParameters['fid'], 'f2');
+                    expect(s.pathParameters['pid'], 'p1');
                     return null;
                   },
                   builder: (BuildContext c, GoRouterState s) => PersonScreen(
-                    s.params['fid']!,
-                    s.params['pid']!,
+                    s.pathParameters['fid']!,
+                    s.pathParameters['pid']!,
                   ),
                 ),
               ],
@@ -2221,7 +2222,7 @@
         GoRoute(
           path: '/family/:fid',
           builder: (BuildContext context, GoRouterState state) =>
-              FamilyScreen(state.params['fid']!),
+              FamilyScreen(state.pathParameters['fid']!),
         ),
       ];
 
@@ -2249,7 +2250,7 @@
         GoRoute(
           path: '/family',
           builder: (BuildContext context, GoRouterState state) => FamilyScreen(
-            state.queryParams['fid']!,
+            state.queryParameters['fid']!,
           ),
         ),
       ];
@@ -2275,7 +2276,7 @@
         GoRoute(
           path: '/page1/:param1',
           builder: (BuildContext c, GoRouterState s) {
-            expect(s.params['param1'], param1);
+            expect(s.pathParameters['param1'], param1);
             return const DummyScreen();
           },
         ),
@@ -2298,7 +2299,7 @@
         GoRoute(
           path: '/page1',
           builder: (BuildContext c, GoRouterState s) {
-            expect(s.queryParams['param1'], param1);
+            expect(s.queryParameters['param1'], param1);
             return const DummyScreen();
           },
         ),
@@ -2346,10 +2347,10 @@
           GoRoute(
             path: '/',
             builder: (BuildContext context, GoRouterState state) {
-              log.info('id= ${state.params['id']}');
-              expect(state.params.length, 0);
-              expect(state.queryParams.length, 1);
-              expect(state.queryParams['id'], anyOf('0', '1'));
+              log.info('id= ${state.pathParameters['id']}');
+              expect(state.pathParameters.length, 0);
+              expect(state.queryParameters.length, 1);
+              expect(state.queryParameters['id'], anyOf('0', '1'));
               return const HomeScreen();
             },
           ),
@@ -2359,7 +2360,7 @@
       );
       final RouteMatchList matches = router.routerDelegate.matches;
       expect(matches.matches, hasLength(1));
-      expect(matches.fullpath, '/');
+      expect(matches.fullPath, '/');
       expect(find.byType(HomeScreen), findsOneWidget);
     });
 
@@ -2369,8 +2370,8 @@
           GoRoute(
             path: '/:id',
             builder: (BuildContext context, GoRouterState state) {
-              expect(state.params, <String, String>{'id': '0'});
-              expect(state.queryParams, <String, String>{'id': '1'});
+              expect(state.pathParameters, <String, String>{'id': '0'});
+              expect(state.queryParameters, <String, String>{'id': '1'});
               return const HomeScreen();
             },
           ),
@@ -2382,7 +2383,7 @@
       await tester.pumpAndSettle();
       final RouteMatchList matches = router.routerDelegate.matches;
       expect(matches.matches, hasLength(1));
-      expect(matches.fullpath, '/:id');
+      expect(matches.fullPath, '/:id');
       expect(find.byType(HomeScreen), findsOneWidget);
     });
 
@@ -2394,15 +2395,15 @@
             path: '/family',
             builder: (BuildContext context, GoRouterState state) =>
                 FamilyScreen(
-              state.queryParams['fid']!,
+              state.queryParameters['fid']!,
             ),
           ),
           GoRoute(
             path: '/person',
             builder: (BuildContext context, GoRouterState state) =>
                 PersonScreen(
-              state.queryParams['fid']!,
-              state.queryParams['pid']!,
+              state.queryParameters['fid']!,
+              state.queryParameters['pid']!,
             ),
           ),
         ],
@@ -2470,13 +2471,13 @@
         GoRoute(
           path: '/family/:fid',
           builder: (BuildContext context, GoRouterState state) =>
-              FamilyScreen(state.params['fid']!),
+              FamilyScreen(state.pathParameters['fid']!),
           routes: <GoRoute>[
             GoRoute(
               path: 'person/:pid',
               builder: (BuildContext context, GoRouterState state) {
-                final String fid = state.params['fid']!;
-                final String pid = state.params['pid']!;
+                final String fid = state.pathParameters['fid']!;
+                final String pid = state.pathParameters['pid']!;
 
                 return PersonScreen(fid, pid);
               },
@@ -2536,7 +2537,7 @@
 
       final GoRouter router = await createRouter(routes, tester);
 
-      router.goNamed('page', queryParams: const <String, dynamic>{
+      router.goNamed('page', queryParameters: const <String, dynamic>{
         'q1': 'v1',
         'q2': <String>['v2', 'v3'],
       });
@@ -2694,12 +2695,12 @@
       );
       key.currentContext!.namedLocation(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: params,
+        queryParameters: queryParams,
       );
       expect(router.name, name);
-      expect(router.params, params);
-      expect(router.queryParams, queryParams);
+      expect(router.pathParameters, params);
+      expect(router.queryParameters, queryParams);
     });
 
     testWidgets('calls [go] on closest GoRouter', (WidgetTester tester) async {
@@ -2729,13 +2730,13 @@
       );
       key.currentContext!.goNamed(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: params,
+        queryParameters: queryParams,
         extra: extra,
       );
       expect(router.name, name);
-      expect(router.params, params);
-      expect(router.queryParams, queryParams);
+      expect(router.pathParameters, params);
+      expect(router.queryParameters, queryParams);
       expect(router.extra, extra);
     });
 
@@ -2787,13 +2788,13 @@
       );
       key.currentContext!.pushNamed(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: params,
+        queryParameters: queryParams,
         extra: extra,
       );
       expect(router.name, name);
-      expect(router.params, params);
-      expect(router.queryParams, queryParams);
+      expect(router.pathParameters, params);
+      expect(router.queryParameters, queryParams);
       expect(router.extra, extra);
     });
 
@@ -2810,15 +2811,15 @@
       );
       final String? result = await router.pushNamed<String>(
         name,
-        params: params,
-        queryParams: queryParams,
+        pathParameters: params,
+        queryParameters: queryParams,
         extra: extra,
       );
       expect(result, extra);
       expect(router.extra, extra);
       expect(router.name, name);
-      expect(router.params, params);
-      expect(router.queryParams, queryParams);
+      expect(router.pathParameters, params);
+      expect(router.queryParameters, queryParams);
     });
 
     testWidgets('calls [pop] on closest GoRouter', (WidgetTester tester) async {
diff --git a/packages/go_router/test/inherited_test.dart b/packages/go_router/test/inherited_test.dart
index 7afa9fe..1b7fb3f 100644
--- a/packages/go_router/test/inherited_test.dart
+++ b/packages/go_router/test/inherited_test.dart
@@ -130,8 +130,8 @@
 
   @override
   Future<T?> pushNamed<T extends Object?>(String name,
-      {Map<String, String> params = const <String, String>{},
-      Map<String, dynamic> queryParams = const <String, dynamic>{},
+      {Map<String, String> pathParameters = const <String, String>{},
+      Map<String, dynamic> queryParameters = const <String, dynamic>{},
       Object? extra}) {
     latestPushedName = name;
     return Future<T?>.value();
diff --git a/packages/go_router/test/match_test.dart b/packages/go_router/test/match_test.dart
index aa14db1..712f379 100644
--- a/packages/go_router/test/match_test.dart
+++ b/packages/go_router/test/match_test.dart
@@ -17,8 +17,8 @@
       final Map<String, String> pathParameters = <String, String>{};
       final RouteMatch? match = RouteMatch.match(
         route: route,
-        restLoc: '/users/123',
-        parentSubloc: '',
+        remainingLocation: '/users/123',
+        matchedLocation: '',
         pathParameters: pathParameters,
         extra: const _Extra('foo'),
       );
@@ -26,14 +26,14 @@
         fail('Null match');
       }
       expect(match.route, route);
-      expect(match.subloc, '/users/123');
+      expect(match.matchedLocation, '/users/123');
       expect(pathParameters['userId'], '123');
       expect(match.extra, const _Extra('foo'));
       expect(match.error, isNull);
       expect(match.pageKey, isNotNull);
     });
 
-    test('subloc', () {
+    test('matchedLocation', () {
       final GoRoute route = GoRoute(
         path: 'users/:userId',
         builder: _builder,
@@ -41,8 +41,8 @@
       final Map<String, String> pathParameters = <String, String>{};
       final RouteMatch? match = RouteMatch.match(
         route: route,
-        restLoc: 'users/123',
-        parentSubloc: '/home',
+        remainingLocation: 'users/123',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo'),
       );
@@ -50,7 +50,7 @@
         fail('Null match');
       }
       expect(match.route, route);
-      expect(match.subloc, '/home/users/123');
+      expect(match.matchedLocation, '/home/users/123');
       expect(pathParameters['userId'], '123');
       expect(match.extra, const _Extra('foo'));
       expect(match.error, isNull);
@@ -70,8 +70,8 @@
       final Map<String, String> pathParameters = <String, String>{};
       final RouteMatch? match = RouteMatch.match(
         route: route,
-        restLoc: 'users/123',
-        parentSubloc: '/home',
+        remainingLocation: 'users/123',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo'),
       );
@@ -94,16 +94,16 @@
       final Map<String, String> pathParameters = <String, String>{};
       final RouteMatch? match1 = RouteMatch.match(
         route: route,
-        restLoc: 'users/123',
-        parentSubloc: '/home',
+        remainingLocation: 'users/123',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo'),
       );
 
       final RouteMatch? match2 = RouteMatch.match(
         route: route,
-        restLoc: 'users/1234',
-        parentSubloc: '/home',
+        remainingLocation: 'users/1234',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo1'),
       );
@@ -119,16 +119,16 @@
       final Map<String, String> pathParameters = <String, String>{};
       final RouteMatch? match1 = RouteMatch.match(
         route: route,
-        restLoc: 'users/123',
-        parentSubloc: '/home',
+        remainingLocation: 'users/123',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo'),
       );
 
       final RouteMatch? match2 = RouteMatch.match(
         route: route,
-        restLoc: 'users/1234',
-        parentSubloc: '/home',
+        remainingLocation: 'users/1234',
+        matchedLocation: '/home',
         pathParameters: pathParameters,
         extra: const _Extra('foo1'),
       );
diff --git a/packages/go_router/test/matching_test.dart b/packages/go_router/test/matching_test.dart
index c92533b..daf8ccc 100644
--- a/packages/go_router/test/matching_test.dart
+++ b/packages/go_router/test/matching_test.dart
@@ -5,6 +5,7 @@
 import 'package:flutter/widgets.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:go_router/src/configuration.dart';
+import 'package:go_router/src/match.dart';
 import 'package:go_router/src/matching.dart';
 import 'package:go_router/src/router.dart';
 
@@ -27,4 +28,50 @@
     final RouteMatchList matches = router.routerDelegate.matches;
     expect(matches.toString(), contains('/page-0'));
   });
+
+  test('RouteMatchList compares', () async {
+    final GoRoute route = GoRoute(
+      path: '/page-0',
+      builder: (BuildContext context, GoRouterState state) =>
+          const Placeholder(),
+    );
+    final Map<String, String> params1 = <String, String>{};
+    final RouteMatch match1 = RouteMatch.match(
+      route: route,
+      remainingLocation: '/page-0',
+      matchedLocation: '',
+      pathParameters: params1,
+      extra: null,
+    )!;
+
+    final Map<String, String> params2 = <String, String>{};
+    final RouteMatch match2 = RouteMatch.match(
+      route: route,
+      remainingLocation: '/page-0',
+      matchedLocation: '',
+      pathParameters: params2,
+      extra: null,
+    )!;
+
+    final RouteMatchList matches1 = RouteMatchList(
+      matches: <RouteMatch>[match1],
+      uri: Uri.parse(''),
+      pathParameters: params1,
+    );
+
+    final RouteMatchList matches2 = RouteMatchList(
+      matches: <RouteMatch>[match2],
+      uri: Uri.parse(''),
+      pathParameters: params2,
+    );
+
+    final RouteMatchList matches3 = RouteMatchList(
+      matches: <RouteMatch>[match2],
+      uri: Uri.parse('/page-0'),
+      pathParameters: params2,
+    );
+
+    expect(matches1 == matches2, isTrue);
+    expect(matches1 == matches3, isFalse);
+  });
 }
diff --git a/packages/go_router/test/parser_test.dart b/packages/go_router/test/parser_test.dart
index 1cc4048..76a068b 100644
--- a/packages/go_router/test/parser_test.dart
+++ b/packages/go_router/test/parser_test.dart
@@ -65,7 +65,7 @@
     expect(matches.length, 1);
     expect(matchesObj.uri.toString(), '/');
     expect(matches[0].extra, isNull);
-    expect(matches[0].subloc, '/');
+    expect(matches[0].matchedLocation, '/');
     expect(matches[0].route, routes[0]);
 
     final Object extra = Object();
@@ -75,11 +75,11 @@
     expect(matches.length, 2);
     expect(matchesObj.uri.toString(), '/abc?def=ghi');
     expect(matches[0].extra, extra);
-    expect(matches[0].subloc, '/');
+    expect(matches[0].matchedLocation, '/');
     expect(matches[0].route, routes[0]);
 
     expect(matches[1].extra, extra);
-    expect(matches[1].subloc, '/abc');
+    expect(matches[1].matchedLocation, '/abc');
     expect(matches[1].route, routes[0].routes[0]);
   });
 
@@ -126,11 +126,11 @@
     expect(configuration.namedLocation('lowercase'), '/abc');
     expect(
         configuration.namedLocation('lowercase',
-            queryParams: const <String, String>{'q': '1'}),
+            queryParameters: const <String, String>{'q': '1'}),
         '/abc?q=1');
     expect(
         configuration.namedLocation('lowercase',
-            queryParams: const <String, String>{'q': '1', 'g': '2'}),
+            queryParameters: const <String, String>{'q': '1', 'g': '2'}),
         '/abc?q=1&g=2');
   });
 
@@ -160,7 +160,7 @@
 
     expect(
       configuration
-          .namedLocation('routeName', queryParams: const <String, dynamic>{
+          .namedLocation('routeName', queryParameters: const <String, dynamic>{
         'q1': 'v1',
         'q2': <String>['v2', 'v3'],
       }),
@@ -198,7 +198,7 @@
     expect(matches.length, 1);
     expect(matchesObj.uri.toString(), '/def');
     expect(matches[0].extra, isNull);
-    expect(matches[0].subloc, '/def');
+    expect(matches[0].matchedLocation, '/def');
     expect(matches[0].error!.toString(),
         'Exception: no routes for location: /def');
   });
@@ -268,10 +268,10 @@
     expect(matchesObj.pathParameters['uid'], '123');
     expect(matchesObj.pathParameters['fid'], '456');
     expect(matches[0].extra, isNull);
-    expect(matches[0].subloc, '/');
+    expect(matches[0].matchedLocation, '/');
 
     expect(matches[1].extra, isNull);
-    expect(matches[1].subloc, '/123/family/456');
+    expect(matches[1].matchedLocation, '/123/family/456');
   });
 
   testWidgets(
@@ -309,9 +309,9 @@
 
     expect(matches.length, 2);
     expect(matchesObj.uri.toString(), '/123/family/345');
-    expect(matches[0].subloc, '/');
+    expect(matches[0].matchedLocation, '/');
 
-    expect(matches[1].subloc, '/123/family/345');
+    expect(matches[1].matchedLocation, '/123/family/345');
   });
 
   testWidgets(
@@ -349,9 +349,9 @@
 
     expect(matches.length, 2);
     expect(matchesObj.uri.toString(), '/123/family/345');
-    expect(matches[0].subloc, '/');
+    expect(matches[0].matchedLocation, '/');
 
-    expect(matches[1].subloc, '/123/family/345');
+    expect(matches[1].matchedLocation, '/123/family/345');
   });
 
   testWidgets(
diff --git a/packages/go_router/test/test_helpers.dart b/packages/go_router/test/test_helpers.dart
index b81f4c2..d2187d4 100644
--- a/packages/go_router/test/test_helpers.dart
+++ b/packages/go_router/test/test_helpers.dart
@@ -37,18 +37,18 @@
   GoRouterNamedLocationSpy({required super.routes});
 
   String? name;
-  Map<String, String>? params;
-  Map<String, dynamic>? queryParams;
+  Map<String, String>? pathParameters;
+  Map<String, dynamic>? queryParameters;
 
   @override
   String namedLocation(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
   }) {
     this.name = name;
-    this.params = params;
-    this.queryParams = queryParams;
+    this.pathParameters = pathParameters;
+    this.queryParameters = queryParameters;
     return '';
   }
 }
@@ -70,20 +70,20 @@
   GoRouterGoNamedSpy({required super.routes});
 
   String? name;
-  Map<String, String>? params;
-  Map<String, dynamic>? queryParams;
+  Map<String, String>? pathParameters;
+  Map<String, dynamic>? queryParameters;
   Object? extra;
 
   @override
   void goNamed(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) {
     this.name = name;
-    this.params = params;
-    this.queryParams = queryParams;
+    this.pathParameters = pathParameters;
+    this.queryParameters = queryParameters;
     this.extra = extra;
   }
 }
@@ -106,20 +106,20 @@
   GoRouterPushNamedSpy({required super.routes});
 
   String? name;
-  Map<String, String>? params;
-  Map<String, dynamic>? queryParams;
+  Map<String, String>? pathParameters;
+  Map<String, dynamic>? queryParameters;
   Object? extra;
 
   @override
   Future<T?> pushNamed<T extends Object?>(
     String name, {
-    Map<String, String> params = const <String, String>{},
-    Map<String, dynamic> queryParams = const <String, dynamic>{},
+    Map<String, String> pathParameters = const <String, String>{},
+    Map<String, dynamic> queryParameters = const <String, dynamic>{},
     Object? extra,
   }) {
     this.name = name;
-    this.params = params;
-    this.queryParams = queryParams;
+    this.pathParameters = pathParameters;
+    this.queryParameters = queryParameters;
     this.extra = extra;
     return Future<T?>.value(extra as T?);
   }
diff --git a/packages/go_router/test_fixes/README.md b/packages/go_router/test_fixes/README.md
new file mode 100644
index 0000000..994d67d
--- /dev/null
+++ b/packages/go_router/test_fixes/README.md
@@ -0,0 +1,17 @@
+## Directory contents
+
+The Dart files and golden master `.expect` files in this directory are used to
+test the [`dart fix` framework](https://dart.dev/tools/dart-fix) refactorings
+used by the go_router package
+
+See the packages/packages/go_router/lib/fix_data.yaml directory for the current
+package:go_router data-driven fixes.
+
+To run these tests locally, execute this command in the
+packages/packages/go_router/test_fixes directory.
+```sh
+dart fix --compare-to-golden
+```
+
+For more documentation about Data Driven Fixes, see
+https://dart.dev/go/data-driven-fixes#test-folder.
diff --git a/packages/go_router/test_fixes/analysis_options.yaml b/packages/go_router/test_fixes/analysis_options.yaml
new file mode 100644
index 0000000..7cca7b1
--- /dev/null
+++ b/packages/go_router/test_fixes/analysis_options.yaml
@@ -0,0 +1 @@
+# This ensures that parent analysis options do not accidentally break the fix tests.
diff --git a/packages/go_router/test_fixes/go_router.dart b/packages/go_router/test_fixes/go_router.dart
new file mode 100644
index 0000000..5811737
--- /dev/null
+++ b/packages/go_router/test_fixes/go_router.dart
@@ -0,0 +1,44 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:go_router/go_router.dart';
+
+void main() {
+  const GoRouterState state = GoRouterState();
+  final GoRouter router = GoRouter(routes: <RouteBase>[]);
+  state.fullpath;
+  state.params;
+  state.subloc;
+  state.queryParams;
+  state.namedLocation(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+  router.namedLocation(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+  router.goNamed(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+  router.pushNamed(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+  router.pushReplacementNamed(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+  router.replaceNamed(
+    'name',
+    params: <String, String>{},
+    queryParams: <String, String>{},
+  );
+}
diff --git a/packages/go_router/test_fixes/go_router.dart.expect b/packages/go_router/test_fixes/go_router.dart.expect
new file mode 100644
index 0000000..c2c5aa6
--- /dev/null
+++ b/packages/go_router/test_fixes/go_router.dart.expect
@@ -0,0 +1,44 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+import 'package:go_router/go_router.dart';
+
+void main() {
+  const GoRouterState state = GoRouterState();
+  final GoRouter router = GoRouter(routes: <RouteBase>[]);
+  state.fullPath;
+  state.pathParameters;
+  state.matchedLocation;
+  state.queryParameters;
+  state.namedLocation(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+  router.namedLocation(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+  router.goNamed(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+  router.pushNamed(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+  router.pushReplacementNamed(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+  router.replaceNamed(
+    'name',
+    pathParameters: <String, String>{},
+    queryParameters: <String, String>{},
+  );
+}
diff --git a/packages/go_router/tool/run_tests.dart b/packages/go_router/tool/run_tests.dart
new file mode 100644
index 0000000..39fe8cc
--- /dev/null
+++ b/packages/go_router/tool/run_tests.dart
@@ -0,0 +1,51 @@
+// Copyright 2013 The Flutter Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Called from the custom-tests CI action.
+//
+// usage: dart run tool/run_tests.dart
+
+// ignore_for_file: avoid_print
+
+import 'dart:io';
+import 'package:path/path.dart' as p;
+
+Future<void> main(List<String> args) async {
+  if (!Platform.isMacOS) {
+    print('This test can only be run on macOS.');
+    exit(0);
+  }
+  final Directory packageRoot =
+      Directory(p.dirname(Platform.script.path)).parent;
+  final int status = await _runProcess(
+    'dart',
+    <String>[
+      'fix',
+      '--compare-to-golden',
+    ],
+    workingDirectory: p.join(packageRoot.path, 'test_fixes'),
+  );
+
+  exit(status);
+}
+
+Future<Process> _streamOutput(Future<Process> processFuture) async {
+  final Process process = await processFuture;
+  stdout.addStream(process.stdout);
+  stderr.addStream(process.stderr);
+  return process;
+}
+
+Future<int> _runProcess(
+  String command,
+  List<String> arguments, {
+  String? workingDirectory,
+}) async {
+  final Process process = await _streamOutput(Process.start(
+    command,
+    arguments,
+    workingDirectory: workingDirectory,
+  ));
+  return process.exitCode;
+}
diff --git a/script/configs/custom_analysis.yaml b/script/configs/custom_analysis.yaml
index 93e2744..569f9e1 100644
--- a/script/configs/custom_analysis.yaml
+++ b/script/configs/custom_analysis.yaml
@@ -23,3 +23,5 @@
 - rfw/example
 # Disables docs requirements, as it is test code.
 - web_benchmarks/testing/test_app
+# Has some test files that are intentionally broken to conduct dart fix tests.
+- go_router