Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Proposal: const *Route.withArgs() generated constructor #2094

Open
mernen opened this issue Nov 20, 2024 · 0 comments
Open

Proposal: const *Route.withArgs() generated constructor #2094

mernen opened this issue Nov 20, 2024 · 0 comments

Comments

@mernen
Copy link
Contributor

mernen commented Nov 20, 2024

Suppose we had the following routes:

@RoutePage()
class FirstPage extends StatelessWidget {
  const FirstPage({super.key});

  @override
  Widget build(BuildContext context) => const Placeholder();
}

@RoutePage()
class SecondPage extends StatelessWidget {
  const SecondPage({super.key, this.param});

  final String? param;

  @override
  Widget build(BuildContext context) => const Placeholder();
}

The generated routes would look something like:

/// generated route for
/// [_i1.FirstPage]
class FirstRoute extends _i2.PageRouteInfo<void> {
  const FirstRoute({List<_i2.PageRouteInfo>? children})
      : super(
          FirstRoute.name,
          initialChildren: children,
        );

  static const String name = 'FirstRoute';

  static _i2.PageInfo page = _i2.PageInfo(
    name,
    builder: (data) {
      return const _i1.FirstPage();
    },
  );
}

/// generated route for
/// [_i1.SecondPage]
class SecondRoute extends _i2.PageRouteInfo<SecondRouteArgs> {
  SecondRoute({
    _i3.Key? key,
    String? param,
    List<_i2.PageRouteInfo>? children,
  }) : super(
          SecondRoute.name,
          args: SecondRouteArgs(
            key: key,
            param: param,
          ),
          initialChildren: children,
        );

  static const String name = 'SecondRoute';

  static _i2.PageInfo page = _i2.PageInfo(
    name,
    builder: (data) {
      final args = data.argsAs<SecondRouteArgs>(
          orElse: () => const SecondRouteArgs());
      return _i1.SecondPage(
        key: args.key,
        param: args.param,
      );
    },
  );
}

class SecondRouteArgs {
  const SecondRouteArgs({
    this.key,
    this.param,
  });

  final _i3.Key? key;

  final String? param;

  @override
  String toString() {
    return 'SecondRouteArgs{key: $key, param: $param}';
  }
}

We can see that due to the presence of a parameter in SecondPage (key is ignored if it's the only parameter), the generated constructor is no longer const, and a SecondRouteArgs class was created.

I'd like to propose in this situation to produce a second constructor:

class SecondRoute extends _i2.PageRouteInfo<SecondRouteArgs> {
  // ...all existing constructors and members unchanged

  const SecondRoute.withArgs(
    SecondRouteArgs args, {
    List<_i2.PageRouteInfo>? children,
  }) : super(
          SecondRoute.name,
          args: args,
          initialChildren: children,
        );
}

The purpose here being solely to offer a const constructor, as it can be useful in some situations like when declaring default values or enum constructor arguments.

Because the *RouteArgs classes are already present and public, no changes at all are necessary to what is already being generated, and adding constructors is in no way a breaking change.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant