injectable icon indicating copy to clipboard operation
injectable copied to clipboard

Order in generated file is wrong

Open ChristianNavolskyi opened this issue 3 years ago • 16 comments

I created a minimal (not-)working example here.

In get_it.config.dart the class A is added first to the helper, but it depends on the second class B.

...
gh.singleton<A>(AImpl(get<B>()));
gh.singleton<intest.B>(intest.BImpl());
...

Any idea how I could work around this or what I am doing wrong here?

ChristianNavolskyi avatar Dec 16 '20 14:12 ChristianNavolskyi

It seems that the problem arises from import 'package:intest/util.dart';. When using import 'package:intest/b.dart'; in A to import B it works. However having those exports (in utils.dart) is quite convenient and should work with injectable, at least I hope so.

ChristianNavolskyi avatar Dec 16 '20 14:12 ChristianNavolskyi

I have created another ordering issue example here. In this issue, the referenced 'Dio' is registered too late, only when we add the 'SomethingInBetween' class to the mix. We don't do any special hacks, everything is imported directly, not via exports etc. @Milad-Akarie is there anything we are misconfiguring/abusing that could cause this to fail, or does the generator need to be patched?

NicolaVerbeeck avatar Mar 01 '21 08:03 NicolaVerbeeck

@NicolaChimerapps @ChristianNavolskyi did this occur after upgrading to 1.1.x?

Milad-Akarie avatar Mar 01 '21 08:03 Milad-Akarie

I just checked on my example, this happens on 1.0.7 too for example

NicolaVerbeeck avatar Mar 01 '21 08:03 NicolaVerbeeck

@NicolaChimerapps I'll take a look.

Milad-Akarie avatar Mar 01 '21 08:03 Milad-Akarie

@NicolaChimerapps It seems my sorting logic does not consider named instances, because as you can see in the below example GApi was registered after it's dependency Dio it's just not the right Dio lol

  gh.singleton<_i6.Dio>(registerModule.provideDataDio(get<_i4.NetworkLogInterceptor>()), instanceName: 'data');

  gh.singleton<_i7.GApi>(_i7.GApi(get<_i6.Dio>()));

Milad-Akarie avatar Mar 01 '21 08:03 Milad-Akarie

Same issue still present in version 1.1.2. I updated the example repo.

ChristianNavolskyi avatar Mar 01 '21 10:03 ChristianNavolskyi

@ChristianNavolskyi I think I know what the problem is but no idea how to fix it yet. a type is identified by it's Name and location in your example the comparison happens between B from b.dart & B from utils.dart so to injectable these are two different types

Milad-Akarie avatar Mar 01 '21 12:03 Milad-Akarie

Okay, makes sense. Thanks for looking into it.

Recently I stumbled over another related issue, but I didn't have the time to create an example to reproduce it and by now I forgot how I got it to not work. I will post here, when I find something new.

ChristianNavolskyi avatar Mar 01 '21 12:03 ChristianNavolskyi

@NicolaChimerapps It seems my sorting logic does not consider named instances, because as you can see in the below example GApi was registered after it's dependency Dio it's just not the right Dio lol

  gh.singleton<_i6.Dio>(registerModule.provideDataDio(get<_i4.NetworkLogInterceptor>()), instanceName: 'data');

  gh.singleton<_i7.GApi>(_i7.GApi(get<_i6.Dio>()));

Any progress on this? 🙏

NicolaVerbeeck avatar Mar 15 '21 10:03 NicolaVerbeeck

I ran into an ordering issue as well :( works fine when I reorder the generated file manually. I have no idea why this happens though. There is nothing complex going on in my dependency tree, but all of the needed DAOs get registered right after the X01MatchControlDaoImpl where they would be needed.

gh.singleton<_i25.X01MatchControlDao>(_i25.X01MatchControlDaoImpl(
      get<_i11.AppDatabase>(),
      mockMatchPlayerDao: get<_i26.X01MatchPlayerDao>(),
      mockMatchDao: get<_i27.X01MatchDao>(),
      mockSetDao: get<_i28.X01SetDao>(),
      mockLegDao: get<_i24.X01LegDao>(),
      mockVisitDao: get<_i29.X01VisitDao>()));
  gh.singleton<_i27.X01MatchDao>(_i27.X01MatchDaoImpl(get<_i11.AppDatabase>()));
  gh.singleton<_i26.X01MatchPlayerDao>(
      _i26.X01MatchPlayerDaoImpl(get<_i11.AppDatabase>()));
  gh.singleton<_i28.X01SetDao>(_i28.X01SetDaoImpl(get<_i11.AppDatabase>()));
  gh.singleton<_i29.X01VisitDao>(_i29.X01VisitDaoImpl(get<_i11.AppDatabase>()));
  gh.singleton<_i30.MatchControlRepository>(_i31.MatchControlRepositoryImpl(
      get<_i25.X01MatchControlDao>(),
      get<_i29.X01VisitDao>(),
      get<_i10.VisitModelConverter>(),
      get<_i5.MatchInfoConverter>(),
      get<_i6.PlayerModelConverter>()));

Any updates on this issue yet?

NikoBoerger avatar Mar 16 '21 19:03 NikoBoerger

@NikoBoerger are you using an index/barrel file to export your dependencies?

Milad-Akarie avatar Mar 19 '21 13:03 Milad-Akarie

@Milad-Akarie no I don't, but I figured out that it happens because of the optional named params of my X01MatchControlDaoImpl. They don't need to be set to instantiate the object. Injectable doesn't seem to care about those optional params when determining the order, but it tries to inject the corresponding objects anyways.

I was able to prevent the bug by doing the object instantiation of the X01MatchControlDaoImpl myself in a @module. There I just don't use the optional params to instantiate the object.

NikoBoerger avatar Mar 19 '21 13:03 NikoBoerger

hmm I guess it makes sense now, my sorting method will include a dependency if it's registered or doesn't exist. that's how the recursive sorting method looks like

for (var dep in unSorted) {
    if (dep.dependencies.every(
      (iDep) =>
          iDep.isFactoryParam ||
          sorted.any((d) => d.type == iDep.type && d.instanceName == iDep.instanceName) ||
          !unSorted.map((d) => d.type).contains(iDep.type),
    )) {
      sorted.add(dep);
    }
  }
  if (unSorted.isNotEmpty) {
    _sortByDependents(unSorted.difference(sorted), sorted);
  }

Milad-Akarie avatar Mar 19 '21 13:03 Milad-Akarie

Any idea as to when this change will make it into a build?

stantronic avatar Jul 06 '21 14:07 stantronic

Well, now is 1.5.0 version but i ran into this problem too.

[AuthService] depends on unregistered type [AuthBloc] from package:fust2022/logic/auth/auth_bloc.dart

in

_i1.GetIt $initGetIt(_i1.GetIt get,
    {String? environment, _i2.EnvironmentFilter? environmentFilter}) {
  final gh = _i2.GetItHelper(get, environment, environmentFilter);

   ...

  gh.lazySingleton<_i3.AuthService>(() => _i3.AuthService(
      authBloc: get<_i4.AuthBloc>(),
      localAuthBloc: get<_i5.LocalAuthGetListBloc>()));

      ...
      
  gh.lazySingleton<_i4.AuthBloc>(() => _i4.AuthBloc(get<_i16.AuthFacade>()));
  return get;
}

Though later in runtime initialization works correctly

I/flutter (10720): 2021-09-15 17:27:55.868245: AuthBloc.AuthBloc
I/flutter (10720): 2021-09-15 17:27:55.884913: AuthService.AuthService

ValeriusGC avatar Sep 15 '21 12:09 ValeriusGC