generate method

Method generate()

Implementation

Method generate() {
  // if true use an awaited initializer
  final useAsyncModifier = microPackagesModulesBefore.isNotEmpty ||
      microPackagesModulesAfter.isNotEmpty ||
      hasPreResolvedDependencies(dependencies);

  // all register modules
  final modules = <ModuleConfig>{};
  for (var dep in dependencies) {
    if (dep.moduleConfig != null) {
      modules.add(dep.moduleConfig!);
    }
  }

  final getInstanceRefer = refer(asExtension ? 'this' : 'getIt');

  final ghStatements = [
    for (final pckModule in microPackagesModulesBefore.map((e) => e.module))
      refer(pckModule.name, pckModule.import)
          .newInstance(const [])
          .property('init')
          .call([_ghLocalRefer])
          .awaited
          .statement,
    ...modules.map(
      (module) => declareFinal(toCamelCase(module.type.name))
          .assign(refer('_\$${module.type.name}').call([
            if (moduleHasOverrides(
              allDependencies.where((e) => e.moduleConfig == module),
            ))
              getInstanceRefer
          ]))
          .statement,
    ),
    ...dependencies.map((dep) {
      if (dep.injectableType == InjectableType.singleton) {
        return buildSingletonRegisterFun(dep);
      } else {
        return buildLazyRegisterFun(dep);
      }
    }),
    for (final pckModule in microPackagesModulesAfter.map((e) => e.module))
      refer(pckModule.name, pckModule.import)
          .newInstance(const [])
          .property('init')
          .call([_ghLocalRefer])
          .awaited
          .statement,
  ];

  final Reference returnRefer;
  if (isMicroPackage) {
    returnRefer = TypeReference((b) => b
      ..symbol = 'FutureOr'
      ..url = 'dart:async'
      ..types.add(refer('void')));
  } else {
    returnRefer = useAsyncModifier
        ? TypeReference((b) => b
          ..symbol = 'Future'
          ..types.add(_getItRefer))
        : _getItRefer;
  }

  final ghBuilder = refer('GetItHelper', _injectableImport).newInstance(
    [
      getInstanceRefer,
      refer('environment'),
      refer('environmentFilter'),
    ],
  );

  return Method(
    (b) => b
      ..docs.add(
          '\n// initializes the registration of ${scopeName ?? 'main'}-scope dependencies inside of GetIt')
      ..modifier = useAsyncModifier ? MethodModifier.async : null
      ..returns = returnRefer
      ..name = initializerName
      ..annotations.addAll([if (isMicroPackage) refer('override')])
      ..requiredParameters.addAll([
        if (!asExtension && !isMicroPackage)
          Parameter(
            (b) => b
              ..name = 'getIt'
              ..type = _getItRefer,
          ),
        if (isMicroPackage)
          Parameter(
            (b) => b
              ..name = 'gh'
              ..type = _ghRefer,
          )
      ])
      ..optionalParameters.addAll([
        if (scopeName == null && !isMicroPackage) ...[
          Parameter((b) => b
            ..named = true
            ..name = 'environment'
            ..type = nullableRefer(
              'String',
              nullable: true,
            )),
          Parameter((b) => b
            ..named = true
            ..name = 'environmentFilter'
            ..type = nullableRefer(
              'EnvironmentFilter',
              url: _injectableImport,
              nullable: true,
            )),
          if (usesConstructorCallback)
            Parameter((b) => b
              ..named = true
              ..name = 'constructorCallback'
              ..type = nullableRefer(
                'T Function<T>(T)',
                nullable: true,
              )),
        ] else if (!isMicroPackage)
          Parameter((b) => b
            ..named = true
            ..name = 'dispose'
            ..type = nullableRefer(
              'ScopeDisposeFunc',
              url: _getItImport,
              nullable: true,
            )),
      ])
      ..body = Block(
        (b) => b.statements.addAll([
          if (scopeName != null)
            _ghRefer
                .newInstance([getInstanceRefer])
                .property('initScope${useAsyncModifier ? 'Async' : ''}')
                .call([
                  literalString(scopeName!)
                ], {
                  'dispose': refer('dispose'),
                  'init': Method((b) => b
                    ..modifier =
                        useAsyncModifier ? MethodModifier.async : null
                    ..requiredParameters.add(Parameter(
                      (b) => b
                        ..name = 'gh'
                        ..type = refer('GetItHelper', _injectableImport),
                    ))
                    ..body = Block(
                      (b) => b.statements.addAll(ghStatements),
                    )).closure
                })
                .returned
                .statement
          else ...[
            if (!isMicroPackage)
              if (dependencies.isNotEmpty ||
                  microPackagesModulesAfter.isNotEmpty ||
                  microPackagesModulesBefore.isNotEmpty)
                declareFinal('gh').assign(ghBuilder).statement
              else
                ghBuilder.statement,
            if (usesConstructorCallback)
              declareFinal('ccb')
                  .assign(
                    refer('constructorCallback')
                        .ifNullThen(CodeExpression(Code('<T>(_) => _'))),
                  )
                  .statement,
            ...ghStatements,
            if (!isMicroPackage) getInstanceRefer.returned.statement,
          ],
        ]),
      ),
  );
}