blob: c85e8e3486752899ca3a53f9959a6a80ca38b058 [file] [log] [blame]
// 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';
import 'package:source_gen_test/annotations.dart';
@ShouldThrow('The @TypedGoRoute annotation can only be applied to classes.')
@TypedGoRoute(path: 'bob') // ignore: invalid_annotation_target
const int theAnswer = 42;
// This test should be removed: dart enforces the `required` keyword.
@ShouldThrow('Missing `path` value on annotation.')
// ignore:missing_required_argument
@TypedGoRoute()
class MissingPathValue extends GoRouteData {}
@ShouldThrow(
'The @TypedGoRoute annotation can only be applied to classes that extend or '
'implement `GoRouteData`.',
)
@TypedGoRoute(path: 'bob')
class AppliedToWrongClassType {}
@ShouldThrow(
'The @TypedGoRoute annotation must have a type parameter that matches the '
'annotated element.',
)
@TypedGoRoute(path: 'bob')
class MissingTypeAnnotation extends GoRouteData {}
@ShouldThrow(
'Could not find a field for the path parameter "id".',
)
@TypedGoRoute<BadPathParam>(path: 'bob/:id')
class BadPathParam extends GoRouteData {}
@ShouldThrow(
'The parameter type `Stopwatch` is not supported.',
)
@TypedGoRoute<UnsupportedType>(path: 'bob/:id')
class UnsupportedType extends GoRouteData {
UnsupportedType({required this.id});
final Stopwatch id;
}
@ShouldThrow(
'Required parameters cannot be nullable.',
)
@TypedGoRoute<NullableRequiredParam>(path: 'bob/:id')
class NullableRequiredParam extends GoRouteData {
NullableRequiredParam({required this.id});
final int? id;
}
@ShouldThrow(
r'Parameters named `$extra` cannot be required.',
)
@TypedGoRoute<ExtraMustBeOptional>(path: r'bob/:$extra')
class ExtraMustBeOptional extends GoRouteData {
ExtraMustBeOptional({required this.$extra});
final int $extra;
}
@ShouldThrow(
'Missing param `id` in path.',
)
@TypedGoRoute<MissingPathParam>(path: 'bob/')
class MissingPathParam extends GoRouteData {
MissingPathParam({required this.id});
final String id;
}
@ShouldGenerate(r'''
GoRoute get $enumParam => GoRouteData.$route(
path: '/:y',
factory: $EnumParamExtension._fromState,
);
extension $EnumParamExtension on EnumParam {
static EnumParam _fromState(GoRouterState state) => EnumParam(
y: _$EnumTestEnumMap._$fromName(state.params['y']!),
);
String get location => GoRouteData.$location(
'/${Uri.encodeComponent(_$EnumTestEnumMap[y]!)}',
);
void go(BuildContext context) => context.go(location, extra: this);
void push(BuildContext context) => context.push(location, extra: this);
void pushReplacement(BuildContext context) =>
context.pushReplacement(location, extra: this);
}
const _$EnumTestEnumMap = {
EnumTest.a: 'a',
EnumTest.b: 'b',
EnumTest.c: 'c',
};
extension<T extends Enum> on Map<T, String> {
T _$fromName(String value) =>
entries.singleWhere((element) => element.value == value).key;
}
''')
@TypedGoRoute<EnumParam>(path: '/:y')
class EnumParam extends GoRouteData {
EnumParam({required this.y});
final EnumTest y;
}
enum EnumTest {
a(1),
b(3),
c(5);
const EnumTest(this.x);
final int x;
}
@ShouldGenerate(r'''
GoRoute get $defaultValueRoute => GoRouteData.$route(
path: '/default-value-route',
factory: $DefaultValueRouteExtension._fromState,
);
extension $DefaultValueRouteExtension on DefaultValueRoute {
static DefaultValueRoute _fromState(GoRouterState state) => DefaultValueRoute(
param: _$convertMapValue('param', state.queryParams, int.parse) ?? 0,
);
String get location => GoRouteData.$location(
'/default-value-route',
queryParams: {
if (param != 0) 'param': param.toString(),
},
);
void go(BuildContext context) => context.go(location, extra: this);
void push(BuildContext context) => context.push(location, extra: this);
void pushReplacement(BuildContext context) =>
context.pushReplacement(location, extra: this);
}
T? _$convertMapValue<T>(
String key,
Map<String, String> map,
T Function(String) converter,
) {
final value = map[key];
return value == null ? null : converter(value);
}
''')
@TypedGoRoute<DefaultValueRoute>(path: '/default-value-route')
class DefaultValueRoute extends GoRouteData {
DefaultValueRoute({this.param = 0});
final int param;
}
@ShouldThrow(
'Default value used with a nullable type. Only non-nullable type can have a default value.',
todo: 'Remove the default value or make the type non-nullable.',
)
@TypedGoRoute<NullableDefaultValueRoute>(path: '/nullable-default-value-route')
class NullableDefaultValueRoute extends GoRouteData {
NullableDefaultValueRoute({this.param = 0});
final int? param;
}