diff --git a/packages/go_router_builder/CHANGELOG.md b/packages/go_router_builder/CHANGELOG.md index 57fd07f2dc3..8fc9b5f2dfd 100644 --- a/packages/go_router_builder/CHANGELOG.md +++ b/packages/go_router_builder/CHANGELOG.md @@ -1,3 +1,7 @@ +## 1.1.6 + +* Generates the const enum map for enums used in `List`, `Set` and `Iterable`. + ## 1.1.5 * Replaces unnecessary Flutter SDK constraint with corresponding Dart diff --git a/packages/go_router_builder/example/lib/all_types.dart b/packages/go_router_builder/example/lib/all_types.dart index 21945d6d2df..8e1f5177843 100644 --- a/packages/go_router_builder/example/lib/all_types.dart +++ b/packages/go_router_builder/example/lib/all_types.dart @@ -297,16 +297,19 @@ class IterableRoute extends GoRouteData { this.stringIterableField, this.boolIterableField, this.enumIterableField, + this.enumOnlyInIterableField, this.intListField, this.doubleListField, this.stringListField, this.boolListField, this.enumListField, + this.enumOnlyInListField, this.intSetField, this.doubleSetField, this.stringSetField, this.boolSetField, this.enumSetField, + this.enumOnlyInSetField, }); final Iterable? intIterableField; @@ -329,6 +332,10 @@ class IterableRoute extends GoRouteData { final List? enumListField; final Set? enumSetField; + final Iterable? enumOnlyInIterableField; + final List? enumOnlyInListField; + final Set? enumOnlyInSetField; + @override Widget build(BuildContext context, GoRouterState state) => const BasePage( diff --git a/packages/go_router_builder/example/lib/all_types.g.dart b/packages/go_router_builder/example/lib/all_types.g.dart index 61f38b7aee9..c30ebeee286 100644 --- a/packages/go_router_builder/example/lib/all_types.g.dart +++ b/packages/go_router_builder/example/lib/all_types.g.dart @@ -364,6 +364,9 @@ extension $IterableRouteExtension on IterableRoute { ?.map(_$boolConverter), enumIterableField: state.queryParametersAll['enum-iterable-field'] ?.map(_$SportDetailsEnumMap._$fromName), + enumOnlyInIterableField: state + .queryParametersAll['enum-only-in-iterable-field'] + ?.map(_$CookingRecipeEnumMap._$fromName), intListField: state.queryParametersAll['int-list-field']?.map(int.parse).toList(), doubleListField: state.queryParametersAll['double-list-field'] @@ -378,6 +381,9 @@ extension $IterableRouteExtension on IterableRoute { enumListField: state.queryParametersAll['enum-list-field'] ?.map(_$SportDetailsEnumMap._$fromName) .toList(), + enumOnlyInListField: state.queryParametersAll['enum-only-in-list-field'] + ?.map(_$CookingRecipeEnumMap._$fromName) + .toList(), intSetField: state.queryParametersAll['int-set-field']?.map(int.parse).toSet(), doubleSetField: state.queryParametersAll['double-set-field'] @@ -391,6 +397,9 @@ extension $IterableRouteExtension on IterableRoute { enumSetField: state.queryParametersAll['enum-set-field'] ?.map(_$SportDetailsEnumMap._$fromName) .toSet(), + enumOnlyInSetField: state.queryParametersAll['enum-only-in-set-field'] + ?.map(_$CookingRecipeEnumMap._$fromName) + .toSet(), ); String get location => GoRouteData.$location( @@ -412,6 +421,10 @@ extension $IterableRouteExtension on IterableRoute { 'enum-iterable-field': enumIterableField ?.map((e) => _$SportDetailsEnumMap[e]) .toList(), + if (enumOnlyInIterableField != null) + 'enum-only-in-iterable-field': enumOnlyInIterableField + ?.map((e) => _$CookingRecipeEnumMap[e]) + .toList(), if (intListField != null) 'int-list-field': intListField?.map((e) => e.toString()).toList(), if (doubleListField != null) @@ -424,6 +437,10 @@ extension $IterableRouteExtension on IterableRoute { if (enumListField != null) 'enum-list-field': enumListField?.map((e) => _$SportDetailsEnumMap[e]).toList(), + if (enumOnlyInListField != null) + 'enum-only-in-list-field': enumOnlyInListField + ?.map((e) => _$CookingRecipeEnumMap[e]) + .toList(), if (intSetField != null) 'int-set-field': intSetField?.map((e) => e.toString()).toList(), if (doubleSetField != null) @@ -436,6 +453,10 @@ extension $IterableRouteExtension on IterableRoute { if (enumSetField != null) 'enum-set-field': enumSetField?.map((e) => _$SportDetailsEnumMap[e]).toList(), + if (enumOnlyInSetField != null) + 'enum-only-in-set-field': enumOnlyInSetField + ?.map((e) => _$CookingRecipeEnumMap[e]) + .toList(), }, ); @@ -460,6 +481,12 @@ const _$SportDetailsEnumMap = { SportDetails.hockey: 'hockey', }; +const _$CookingRecipeEnumMap = { + CookingRecipe.burger: 'burger', + CookingRecipe.pizza: 'pizza', + CookingRecipe.tacos: 'tacos', +}; + T? _$convertMapValue( String key, Map map, diff --git a/packages/go_router_builder/example/lib/shared/data.dart b/packages/go_router_builder/example/lib/shared/data.dart index edc3f205eb4..20f7c92d444 100644 --- a/packages/go_router_builder/example/lib/shared/data.dart +++ b/packages/go_router_builder/example/lib/shared/data.dart @@ -54,6 +54,13 @@ enum SportDetails { final bool hasNet; } +/// An enum used only in iterables. +enum CookingRecipe { + burger, + pizza, + tacos, +} + /// sample Person class class Person { Person({ diff --git a/packages/go_router_builder/example/test/all_types_test.dart b/packages/go_router_builder/example/test/all_types_test.dart index ff3bff1ac69..4b0cb3fb979 100644 --- a/packages/go_router_builder/example/test/all_types_test.dart +++ b/packages/go_router_builder/example/test/all_types_test.dart @@ -127,13 +127,18 @@ void main() { expect(find.text('Query param: https://dart.dev'), findsOneWidget); IterableRoute( + enumIterableField: [SportDetails.football], intListField: [1, 2, 3], + enumOnlyInSetField: { + CookingRecipe.burger, + CookingRecipe.pizza, + }, ).go(scaffoldState.context); await tester.pumpAndSettle(); expect(find.text('IterableRoute'), findsOneWidget); expect( find.text( - '/iterable-route?int-list-field=1&int-list-field=2&int-list-field=3'), + '/iterable-route?enum-iterable-field=football&int-list-field=1&int-list-field=2&int-list-field=3&enum-only-in-set-field=burger&enum-only-in-set-field=pizza'), findsOneWidget); }); } diff --git a/packages/go_router_builder/lib/src/route_config.dart b/packages/go_router_builder/lib/src/route_config.dart index 87087a368fe..cfc4863fedf 100644 --- a/packages/go_router_builder/lib/src/route_config.dart +++ b/packages/go_router_builder/lib/src/route_config.dart @@ -179,8 +179,15 @@ GoRoute get $_routeGetterName => ${_routeDefinition()}; ...routeDef._ctorParams, ...routeDef._ctorQueryParams, ]) { - if (ctorParam.type.isEnum) { - enumParamTypes.add(ctorParam.type as InterfaceType); + DartType potentialEnumType = ctorParam.type; + if (potentialEnumType is ParameterizedType && + (ctorParam.type as ParameterizedType).typeArguments.isNotEmpty) { + potentialEnumType = + (ctorParam.type as ParameterizedType).typeArguments.first; + } + + if (potentialEnumType.isEnum) { + enumParamTypes.add(potentialEnumType as InterfaceType); } } } diff --git a/packages/go_router_builder/pubspec.yaml b/packages/go_router_builder/pubspec.yaml index 999c4a06673..36493448882 100644 --- a/packages/go_router_builder/pubspec.yaml +++ b/packages/go_router_builder/pubspec.yaml @@ -2,7 +2,7 @@ name: go_router_builder description: >- A builder that supports generated strongly-typed route helpers for package:go_router -version: 1.1.5 +version: 1.1.6 repository: https://github.com/flutter/packages/tree/main/packages/go_router_builder issue_tracker: https://github.com/flutter/flutter/issues?q=is%3Aissue+is%3Aopen+label%3A%22p%3A+go_router_builder%22 diff --git a/packages/go_router_builder/test/builder_test.dart b/packages/go_router_builder/test/builder_test.dart index 68c5a1b28ae..f9124ed4520 100644 --- a/packages/go_router_builder/test/builder_test.dart +++ b/packages/go_router_builder/test/builder_test.dart @@ -35,4 +35,5 @@ const Set _expectedAnnotatedTests = { 'EnumParam', 'DefaultValueRoute', 'NullableDefaultValueRoute', + 'IterableWithEnumRoute' }; diff --git a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart index abb47ad5b7d..39e6ef688e8 100644 --- a/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart +++ b/packages/go_router_builder/test/test_inputs/_go_router_builder_test_input.dart @@ -213,3 +213,57 @@ class NullableDefaultValueRoute extends GoRouteData { NullableDefaultValueRoute({this.param = 0}); final int? param; } + +@ShouldGenerate(r''' +GoRoute get $iterableWithEnumRoute => GoRouteData.$route( + path: '/iterable-with-enum', + factory: $IterableWithEnumRouteExtension._fromState, + ); + +extension $IterableWithEnumRouteExtension on IterableWithEnumRoute { + static IterableWithEnumRoute _fromState(GoRouterState state) => + IterableWithEnumRoute( + param: state.queryParametersAll['param'] + ?.map(_$EnumOnlyUsedInIterableEnumMap._$fromName), + ); + + String get location => GoRouteData.$location( + '/iterable-with-enum', + queryParams: { + if (param != null) + 'param': + param?.map((e) => _$EnumOnlyUsedInIterableEnumMap[e]).toList(), + }, + ); + + void go(BuildContext context) => context.go(location); + + void push(BuildContext context) => context.push(location); + + void pushReplacement(BuildContext context) => + context.pushReplacement(location); +} + +const _$EnumOnlyUsedInIterableEnumMap = { + EnumOnlyUsedInIterable.a: 'a', + EnumOnlyUsedInIterable.b: 'b', + EnumOnlyUsedInIterable.c: 'c', +}; + +extension on Map { + T _$fromName(String value) => + entries.singleWhere((element) => element.value == value).key; +} +''') +@TypedGoRoute(path: '/iterable-with-enum') +class IterableWithEnumRoute extends GoRouteData { + IterableWithEnumRoute({this.param}); + + final Iterable? param; +} + +enum EnumOnlyUsedInIterable { + a, + b, + c, +}