[go_router] Add GoRouterState parameters to GoRouterData and rename replace methods (#2848)

* :sparkles: Add redirectWithState method to GoRouteData

* :white_check_mark: Update the tests

* :arrow_up: Increase version number

* :pencil2: Better changelog

* :boom: Remove xxxWithState and adds a the context and the state as a parameter to all GoRouteData callbacks

* :memo: Update the change logs and version number

* :boom: Rename replace into pushReplacement

* :memo: Add pushReplacementNamed into change log

* :memo: Add migration guide's link to the read me
diff --git a/packages/go_router/CHANGELOG.md b/packages/go_router/CHANGELOG.md
index b11aeb4..075e950 100644
--- a/packages/go_router/CHANGELOG.md
+++ b/packages/go_router/CHANGELOG.md
@@ -1,3 +1,13 @@
+## 6.0.0
+
+- **BREAKING CHANGE**
+  - `GoRouteData`'s `redirect` now takes 2 parameters `BuildContext context, GoRouterState state`.
+  - `GoRouteData`'s `build` now takes 2 parameters `BuildContext context, GoRouterState state`.
+  - `GoRouteData`'s `buildPageWithState` has been removed and replaced by `buildPage` with now takes 2 parameters `BuildContext context, GoRouterState state`.
+  - `replace` from `GoRouter`, `GoRouterDelegate` and `GoRouterHelper` has been renamed into `pushReplacement`. 
+  - `replaceNamed` from `GoRouter`, `GoRouterDelegate` and `GoRouterHelper` has been renamed into `pushReplacementNamed`. 
+  - [go_router v6 migration guide](https://flutter.dev/go/go-router-v6-breaking-changes)
+
 ## 5.2.4
 
 - Fixes crashes when using async redirect.
diff --git a/packages/go_router/README.md b/packages/go_router/README.md
index b0cd9ab..daed219 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 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)
 - [Migrating to 4.0](https://flutter.dev/go/go-router-v4-breaking-changes)
diff --git a/packages/go_router/lib/src/delegate.dart b/packages/go_router/lib/src/delegate.dart
index 82a6e6d..b34aac0 100644
--- a/packages/go_router/lib/src/delegate.dart
+++ b/packages/go_router/lib/src/delegate.dart
@@ -145,7 +145,7 @@
   ///
   /// See also:
   /// * [push] which pushes the given location onto the page stack.
-  void replace(RouteMatchList matches) {
+  void pushReplacement(RouteMatchList matches) {
     _matchList.pop();
     push(matches); // [push] will notify the listeners.
   }
diff --git a/packages/go_router/lib/src/misc/extensions.dart b/packages/go_router/lib/src/misc/extensions.dart
index 65e45cb..7030ad3 100644
--- a/packages/go_router/lib/src/misc/extensions.dart
+++ b/packages/go_router/lib/src/misc/extensions.dart
@@ -67,8 +67,8 @@
   /// See also:
   /// * [go] which navigates to the location.
   /// * [push] which pushes the location onto the page stack.
-  void replace(String location, {Object? extra}) =>
-      GoRouter.of(this).replace(location, extra: extra);
+  void pushReplacement(String location, {Object? extra}) =>
+      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':
@@ -77,13 +77,13 @@
   /// See also:
   /// * [goNamed] which navigates a named route.
   /// * [pushNamed] which pushes a named route onto the page stack.
-  void replaceNamed(
+  void pushReplacementNamed(
     String name, {
     Map<String, String> params = const <String, String>{},
     Map<String, dynamic> queryParams = const <String, dynamic>{},
     Object? extra,
   }) =>
-      GoRouter.of(this).replaceNamed(
+      GoRouter.of(this).pushReplacementNamed(
         name,
         params: params,
         queryParams: queryParams,
diff --git a/packages/go_router/lib/src/route_data.dart b/packages/go_router/lib/src/route_data.dart
index ba862d0..efa9e85 100644
--- a/packages/go_router/lib/src/route_data.dart
+++ b/packages/go_router/lib/src/route_data.dart
@@ -14,7 +14,7 @@
 /// Baseclass for supporting
 /// [Type-safe routing](https://pub.dev/documentation/go_router/latest/topics/Type-safe%20routes-topic.html).
 ///
-/// Subclasses must override one of [build], [buildPageWithState], or
+/// Subclasses must override one of [build], [buildPage], or
 /// [redirect].
 /// {@category Type-safe routes}
 abstract class GoRouteData {
@@ -25,53 +25,36 @@
 
   /// Creates the [Widget] for `this` route.
   ///
-  /// Subclasses must override one of [build], [buildPageWithState], or
+  /// Subclasses must override one of [build], [buildPage], or
   /// [redirect].
   ///
   /// Corresponds to [GoRoute.builder].
-  Widget build(BuildContext context) => throw UnimplementedError(
-        'One of `build` or `buildPageWithState` must be implemented.',
+  Widget build(BuildContext context, GoRouterState state) =>
+      throw UnimplementedError(
+        'One of `build` or `buildPage` must be implemented.',
       );
 
   /// A page builder for this route.
   ///
   /// Subclasses can override this function to provide a custom [Page].
   ///
-  /// Subclasses must override one of [build], [buildPageWithState] or
+  /// Subclasses must override one of [build], [buildPage] or
   /// [redirect].
   ///
   /// Corresponds to [GoRoute.pageBuilder].
   ///
   /// By default, returns a [Page] instance that is ignored, causing a default
   /// [Page] implementation to be used with the results of [build].
-  @Deprecated(
-    'This method has been deprecated in favor of buildPageWithState. '
-    'This feature was deprecated after v4.3.0.',
-  )
-  Page<void> buildPage(BuildContext context) => const NoOpPage();
-
-  /// A page builder for this route with [GoRouterState].
-  ///
-  /// Subclasses can override this function to provide a custom [Page].
-  ///
-  /// Subclasses must override one of [build], [buildPageWithState] or
-  /// [redirect].
-  ///
-  /// Corresponds to [GoRoute.pageBuilder].
-  ///
-  /// By default, returns a [Page] instance that is ignored, causing a default
-  /// [Page] implementation to be used with the results of [build].
-  Page<void> buildPageWithState(BuildContext context, GoRouterState state) =>
-      // ignore: deprecated_member_use_from_same_package
-      buildPage(context);
+  Page<void> buildPage(BuildContext context, GoRouterState state) =>
+      const NoOpPage();
 
   /// An optional redirect function for this route.
   ///
-  /// Subclasses must override one of [build], [buildPageWithState], or
+  /// Subclasses must override one of [build], [buildPage], or
   /// [redirect].
   ///
   /// Corresponds to [GoRoute.redirect].
-  FutureOr<String?> redirect() => null;
+  FutureOr<String?> redirect(BuildContext context, GoRouterState state) => null;
 
   /// A helper function used by generated code.
   ///
@@ -106,13 +89,13 @@
     }
 
     Widget builder(BuildContext context, GoRouterState state) =>
-        factoryImpl(state).build(context);
+        factoryImpl(state).build(context, state);
 
     Page<void> pageBuilder(BuildContext context, GoRouterState state) =>
-        factoryImpl(state).buildPageWithState(context, state);
+        factoryImpl(state).buildPage(context, state);
 
     FutureOr<String?> redirect(BuildContext context, GoRouterState state) =>
-        factoryImpl(state).redirect();
+        factoryImpl(state).redirect(context, state);
 
     return GoRoute(
       path: path,
diff --git a/packages/go_router/lib/src/router.dart b/packages/go_router/lib/src/router.dart
index c3fb0a8..73a86c6 100644
--- a/packages/go_router/lib/src/router.dart
+++ b/packages/go_router/lib/src/router.dart
@@ -240,7 +240,7 @@
   /// See also:
   /// * [go] which navigates to the location.
   /// * [push] which pushes the location onto the page stack.
-  void replace(String location, {Object? extra}) {
+  void pushReplacement(String location, {Object? extra}) {
     routeInformationParser
         .parseRouteInformationWithDependencies(
       RouteInformation(location: location, state: extra),
@@ -249,7 +249,7 @@
       _routerDelegate.navigatorKey.currentContext!,
     )
         .then<void>((RouteMatchList matchList) {
-      routerDelegate.replace(matchList);
+      routerDelegate.pushReplacement(matchList);
     });
   }
 
@@ -260,13 +260,13 @@
   /// See also:
   /// * [goNamed] which navigates a named route.
   /// * [pushNamed] which pushes a named route onto the page stack.
-  void replaceNamed(
+  void pushReplacementNamed(
     String name, {
     Map<String, String> params = const <String, String>{},
     Map<String, dynamic> queryParams = const <String, dynamic>{},
     Object? extra,
   }) {
-    replace(
+    pushReplacement(
       namedLocation(name, params: params, queryParams: queryParams),
       extra: extra,
     );
diff --git a/packages/go_router/pubspec.yaml b/packages/go_router/pubspec.yaml
index af92f1c..edcfd0a 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: 5.2.4
+version: 6.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
 
diff --git a/packages/go_router/test/delegate_test.dart b/packages/go_router/test/delegate_test.dart
index 7df8504..62f4b69 100644
--- a/packages/go_router/test/delegate_test.dart
+++ b/packages/go_router/test/delegate_test.dart
@@ -106,7 +106,7 @@
     );
   });
 
-  group('replace', () {
+  group('pushReplacement', () {
     testWidgets('It should replace the last match with the given one',
         (WidgetTester tester) async {
       final GoRouter goRouter = GoRouter(
@@ -128,7 +128,7 @@
       goRouter.routerDelegate.addListener(expectAsync0(() {}));
       final RouteMatch first = goRouter.routerDelegate.matches.matches.first;
       final RouteMatch last = goRouter.routerDelegate.matches.last;
-      goRouter.replace('/page-1');
+      goRouter.pushReplacement('/page-1');
       expect(goRouter.routerDelegate.matches.matches.length, 2);
       expect(
         goRouter.routerDelegate.matches.matches.first,
@@ -169,7 +169,7 @@
           const Key('/a-p1'),
         );
 
-        goRouter.replace('/a');
+        goRouter.pushReplacement('/a');
         await tester.pumpAndSettle();
 
         expect(goRouter.routerDelegate.matches.matches.length, 2);
@@ -181,7 +181,7 @@
     );
   });
 
-  group('replaceNamed', () {
+  group('pushReplacementNamed', () {
     testWidgets(
       'It should replace the last match with the given one',
       (WidgetTester tester) async {
@@ -210,7 +210,7 @@
         goRouter.routerDelegate.addListener(expectAsync0(() {}));
         final RouteMatch first = goRouter.routerDelegate.matches.matches.first;
         final RouteMatch last = goRouter.routerDelegate.matches.last;
-        goRouter.replaceNamed('page1');
+        goRouter.pushReplacementNamed('page1');
         expect(goRouter.routerDelegate.matches.matches.length, 2);
         expect(
           goRouter.routerDelegate.matches.matches.first,
diff --git a/packages/go_router/test/route_data_test.dart b/packages/go_router/test/route_data_test.dart
index 4ae12f6..6c8a49a 100644
--- a/packages/go_router/test/route_data_test.dart
+++ b/packages/go_router/test/route_data_test.dart
@@ -2,6 +2,8 @@
 // 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/material.dart';
 import 'package:flutter_test/flutter_test.dart';
 import 'package:go_router/go_router.dart';
@@ -9,7 +11,8 @@
 class _GoRouteDataBuild extends GoRouteData {
   const _GoRouteDataBuild();
   @override
-  Widget build(BuildContext context) => const SizedBox(key: Key('build'));
+  Widget build(BuildContext context, GoRouterState state) =>
+      const SizedBox(key: Key('build'));
 }
 
 final GoRoute _goRouteDataBuild = GoRouteData.$route(
@@ -20,7 +23,8 @@
 class _GoRouteDataBuildPage extends GoRouteData {
   const _GoRouteDataBuildPage();
   @override
-  Page<void> buildPage(BuildContext context) => const MaterialPage<void>(
+  Page<void> buildPage(BuildContext context, GoRouterState state) =>
+      const MaterialPage<void>(
         child: SizedBox(key: Key('buildPage')),
       );
 }
@@ -30,24 +34,22 @@
   factory: (GoRouterState state) => const _GoRouteDataBuildPage(),
 );
 
-class _GoRouteDataBuildPageWithState extends GoRouteData {
-  const _GoRouteDataBuildPageWithState();
+class _GoRouteDataRedirectPage extends GoRouteData {
+  const _GoRouteDataRedirectPage();
   @override
-  Page<void> buildPageWithState(BuildContext context, GoRouterState state) =>
-      const MaterialPage<void>(
-        child: SizedBox(key: Key('buildPageWithState')),
-      );
+  FutureOr<String> redirect(BuildContext context, GoRouterState state) =>
+      '/build-page';
 }
 
-final GoRoute _goRouteDataBuildPageWithState = GoRouteData.$route(
-  path: '/build-page-with-state',
-  factory: (GoRouterState state) => const _GoRouteDataBuildPageWithState(),
+final GoRoute _goRouteDataRedirect = GoRouteData.$route(
+  path: '/redirect',
+  factory: (GoRouterState state) => const _GoRouteDataRedirectPage(),
 );
 
 final List<GoRoute> _routes = <GoRoute>[
   _goRouteDataBuild,
   _goRouteDataBuildPage,
-  _goRouteDataBuildPageWithState,
+  _goRouteDataRedirect,
 ];
 
 void main() {
@@ -65,7 +67,6 @@
       ));
       expect(find.byKey(const Key('build')), findsOneWidget);
       expect(find.byKey(const Key('buildPage')), findsNothing);
-      expect(find.byKey(const Key('buildPageWithState')), findsNothing);
     },
   );
 
@@ -83,12 +84,11 @@
       ));
       expect(find.byKey(const Key('build')), findsNothing);
       expect(find.byKey(const Key('buildPage')), findsOneWidget);
-      expect(find.byKey(const Key('buildPageWithState')), findsNothing);
     },
   );
 
   testWidgets(
-    'It should build the page from the overridden buildPageWithState method',
+    'It should build the page from the overridden buildPage method',
     (WidgetTester tester) async {
       final GoRouter goRouter = GoRouter(
         initialLocation: '/build-page-with-state',
@@ -101,7 +101,39 @@
       ));
       expect(find.byKey(const Key('build')), findsNothing);
       expect(find.byKey(const Key('buildPage')), findsNothing);
-      expect(find.byKey(const Key('buildPageWithState')), findsOneWidget);
+    },
+  );
+  testWidgets(
+    'It should redirect using the overridden redirect method',
+    (WidgetTester tester) async {
+      final GoRouter goRouter = GoRouter(
+        initialLocation: '/redirect',
+        routes: _routes,
+      );
+      await tester.pumpWidget(MaterialApp.router(
+        routeInformationProvider: goRouter.routeInformationProvider,
+        routeInformationParser: goRouter.routeInformationParser,
+        routerDelegate: goRouter.routerDelegate,
+      ));
+      expect(find.byKey(const Key('build')), findsNothing);
+      expect(find.byKey(const Key('buildPage')), findsOneWidget);
+    },
+  );
+
+  testWidgets(
+    'It should redirect using the overridden redirect method',
+    (WidgetTester tester) async {
+      final GoRouter goRouter = GoRouter(
+        initialLocation: '/redirect-with-state',
+        routes: _routes,
+      );
+      await tester.pumpWidget(MaterialApp.router(
+        routeInformationProvider: goRouter.routeInformationProvider,
+        routeInformationParser: goRouter.routeInformationParser,
+        routerDelegate: goRouter.routerDelegate,
+      ));
+      expect(find.byKey(const Key('build')), findsNothing);
+      expect(find.byKey(const Key('buildPage')), findsNothing);
     },
   );
 }