Skip to content

Make factory params return exact type #214

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

Merged
merged 1 commit into from
Jul 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/get_it.dart
Original file line number Diff line number Diff line change
Expand Up @@ -209,7 +209,7 @@ abstract class GetIt {
/// getIt.registerFactoryParam<TestClassParam,String,void>((s,_)
/// => TestClassParam(param1:s);
void registerFactoryParam<T extends Object, P1, P2>(
FactoryFuncParam<T, P1?, P2?> factoryFunc, {
FactoryFuncParam<T, P1, P2> factoryFunc, {
String? instanceName,
});

Expand Down
14 changes: 7 additions & 7 deletions lib/get_it_impl.dart
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@ class _ServiceFactory<T extends Object, P1, P2> {
/// only one of them is always set.
final FactoryFunc<T>? creationFunction;
final FactoryFuncAsync<T>? asyncCreationFunction;
final FactoryFuncParam<T, P1?, P2?>? creationFunctionParam;
final FactoryFuncParamAsync<T, P1?, P2?>? asyncCreationFunctionParam;
final FactoryFuncParam<T, P1, P2>? creationFunctionParam;
final FactoryFuncParamAsync<T, P1, P2>? asyncCreationFunctionParam;

/// Dispose function that is used when a scope is popped
final DisposingFunc<T>? disposeFunction;
Expand Down Expand Up @@ -149,7 +149,7 @@ class _ServiceFactory<T extends Object, P1, P2> {
// param2 == null || param2.runtimeType == param2Type,
// 'Incompatible Type passed as param2\n'
// 'expected: $param2Type actual: ${param2.runtimeType}');
return creationFunctionParam!(param1 as P1?, param2 as P2?);
return creationFunctionParam!(param1 as P1, param2 as P2);
} else {
return creationFunction!();
}
Expand Down Expand Up @@ -213,7 +213,7 @@ class _ServiceFactory<T extends Object, P1, P2> {
// param2 == null || param2.runtimeType == param2Type,
// 'Incompatible Type passed a param2\n'
// 'expected: $param2Type actual: ${param2.runtimeType}');
return asyncCreationFunctionParam!(param1 as P1?, param2 as P2?)
return asyncCreationFunctionParam!(param1 as P1, param2 as P2)
as Future<R>;
} else {
return asyncCreationFunction!() as Future<R>;
Expand Down Expand Up @@ -483,7 +483,7 @@ class _GetItImplementation implements GetIt {
/// => TestClassParam(param1:s);
@override
void registerFactoryParam<T extends Object, P1, P2>(
FactoryFuncParam<T, P1?, P2?> factoryFunc, {
FactoryFuncParam<T, P1, P2> factoryFunc, {
String? instanceName,
}) {
_register<T, P1, P2>(
Expand Down Expand Up @@ -780,9 +780,9 @@ class _GetItImplementation implements GetIt {
void _register<T extends Object, P1, P2>({
required _ServiceFactoryType type,
FactoryFunc<T>? factoryFunc,
FactoryFuncParam<T, P1?, P2?>? factoryFuncParam,
FactoryFuncParam<T, P1, P2>? factoryFuncParam,
FactoryFuncAsync<T>? factoryFuncAsync,
FactoryFuncParamAsync<T, P1?, P2?>? factoryFuncParamAsync,
FactoryFuncParamAsync<T, P1, P2>? factoryFuncParamAsync,
T? instance,
required String? instanceName,
required bool isAsync,
Expand Down
73 changes: 62 additions & 11 deletions test/async_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -575,6 +575,25 @@ void main() {
expect(instance2.param1, '123');
});

test('register factory with one nullable Param', () async {
final getIt = GetIt.instance;

constructorCounter = 0;
getIt
.registerFactoryParamAsync<TestClassParam, String?, void>((s, _) async {
await Future.delayed(const Duration(milliseconds: 1));
return TestClassParam(param1: s);
});

final instance1 = await getIt.getAsync<TestClassParam>(param1: 'abc');
final instance2 = await getIt.getAsync<TestClassParam>();

expect(instance1 is TestClassParam, true);
expect(instance1.param1, 'abc');
expect(instance2 is TestClassParam, true);
expect(instance2.param1, null);
});

test('register factory with two Params', () async {
final getIt = GetIt.instance;

Expand All @@ -599,20 +618,52 @@ void main() {
expect(instance2.param2, 5);
});

// this isn't currently possible to ensure because a limitation of Dart
// test('register factory with Params with wrong type', () {
// final getIt = GetIt.instance;
// getIt.reset();
test('register factory with two nullable Params', () async {
final getIt = GetIt.instance;

constructorCounter = 0;
getIt
.registerFactoryParamAsync<TestClassParam, String?, int?>((s, i) async {
await Future.delayed(const Duration(milliseconds: 1));
return TestClassParam(param1: s, param2: i);
});

final instance1 =
await getIt.getAsync<TestClassParam>(param1: 'abc', param2: 3);
final instance2 = await getIt.getAsync<TestClassParam>();

expect(instance1 is TestClassParam, true);
expect(instance1.param1, 'abc');
expect(instance1.param2, 3);
expect(instance2 is TestClassParam, true);
expect(instance2.param1, null);
expect(instance2.param2, null);
});

test('register factory with Params with wrong type', () {
final getIt = GetIt.instance;
getIt.reset();

constructorCounter = 0;
getIt.registerFactoryParamAsync<TestClassParam, String, int>(
(s, i) async => TestClassParam(param1: s, param2: i));

expect(() => getIt.getAsync<TestClassParam>(param1: 'abc', param2: '3'),
throwsA(const TypeMatcher<TypeError>()));
});

// constructorCounter = 0;
// getIt.registerFactoryParamAsync<TestClassParam, String, int>(
// (s, i) async => TestClassParam(param1: s, param2: i));
test('register factory with Params with non-nullable type but not pass it',
() {
final getIt = GetIt.instance;
getIt.reset();

// //final instance1 = getIt.get<TestBaseClass>();
constructorCounter = 0;
getIt.registerFactoryParamAsync<TestClassParam, String, void>(
(s, i) async => TestClassParam(param1: s));

// expect(() => getIt.getAsync<TestClassParam>(param1: 'abc', param2: '3'),
// throwsA(const TypeMatcher<AssertionError>()));
// });
expect(() => getIt.getAsync<TestClassParam>(),
throwsA(const TypeMatcher<TypeError>()));
});

test('asyncFactory called with get instead of getAsync', () async {
final getIt = GetIt.instance;
Expand Down
46 changes: 46 additions & 0 deletions test/get_it_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,22 @@ void main() {
expect(instance2.param1, '123');
});

test('register factory with one nullable Param', () {
final getIt = GetIt.instance;

constructorCounter = 0;
getIt.registerFactoryParam<TestClassParam, String?, void>(
(s, _) => TestClassParam(param1: s));

final instance1 = getIt<TestClassParam>(param1: 'abc');
final instance2 = getIt<TestClassParam>(param1: null);

expect(instance1 is TestClassParam, true);
expect(instance1.param1, 'abc');
expect(instance2 is TestClassParam, true);
expect(instance2.param1, null);
});

test('register factory with two Params', () {
final getIt = GetIt.instance;

Expand All @@ -111,6 +127,24 @@ void main() {
expect(instance2.param2, 5);
});

test('register factory with two nullable Params', () {
final getIt = GetIt.instance;

constructorCounter = 0;
getIt.registerFactoryParam<TestClassParam, String?, int?>(
(s, i) => TestClassParam(param1: s, param2: i));

final instance1 = getIt<TestClassParam>(param1: 'abc', param2: 3);
final instance2 = getIt<TestClassParam>();

expect(instance1 is TestClassParam, true);
expect(instance1.param1, 'abc');
expect(instance1.param2, 3);
expect(instance2 is TestClassParam, true);
expect(instance2.param1, null);
expect(instance2.param2, null);
});

test('register factory with Params with wrong type', () {
final getIt = GetIt.instance;

Expand All @@ -122,6 +156,18 @@ void main() {
throwsA(const TypeMatcher<TypeError>()));
});

test('register factory with Params with non-nullable type but not pass it',
() {
final getIt = GetIt.instance;

constructorCounter = 0;
getIt.registerFactoryParam<TestClassParam, String, int>(
(s, i) => TestClassParam(param1: s, param2: i));

expect(() => getIt.get<TestClassParam>(param2: '3'),
throwsA(const TypeMatcher<TypeError>()));
});

test('register factory with access as singleton', () {
constructorCounter = 0;
GetIt.instance.registerFactory<TestBaseClass>(() => TestClass());
Expand Down