addDirectiveProviders method

void addDirectiveProviders(
  1. List<ProviderAst> providerList,
  2. List<CompileDirectiveMetadata> directives
)

Given a list of directives (and component itself), adds providers for each directive at this node. Code generators that want to build instances can handle the createProviderInstance callback on the host interface.

Implementation

void addDirectiveProviders(
  final List<ProviderAst> providerList,
  final List<CompileDirectiveMetadata> directives,
) {
  // Create a lookup map from token to provider.
  for (var provider in providerList) {
    _resolvedProviders.add(provider.token, provider);
  }
  // Create all the provider instances, some in the view constructor (eager),
  // some as getters (eager=false). We rely on the fact that they are
  // already sorted topologically.
  for (var resolvedProvider in providerList) {
    // One or more(multi) sources when built will return provider value
    // expressions.
    var providerSources = <ProviderSource>[];
    var isLocalAlias = false;
    CompileDirectiveMetadata? directiveMetadata;
    for (var provider in resolvedProvider.providers) {
      ProviderSource providerSource;
      if (provider.useExisting != null) {
        // If this provider is just an alias for another provider on this
        // component, we don't need to generate a getter.
        if (_instances.containsKey(provider.useExisting!) &&
            !resolvedProvider.multiProvider) {
          isLocalAlias = true;
          break;
        }
        // Given the token and visibility defined by providerType,
        // get value based on existing expression mapped to token.
        providerSource = _getDependency(
            CompileDiDependencyMetadata(token: provider.useExisting));
        directiveMetadata = null;
      } else if (provider.useFactory != null) {
        providerSource =
            _addFactoryProvider(provider, resolvedProvider.providerType);
      } else if (provider.useClass != null) {
        var classType = provider.useClass!.identifier;
        providerSource = _addClassProvider(
          provider,
          resolvedProvider.providerType,
        );
        // Check if class is a directive and keep track of directiveMetadata
        // for the directive so we can determine if the provider has
        // an associated change detector class.
        for (var dir in directives) {
          if (dir.identifier == classType) {
            directiveMetadata = dir;
            break;
          }
        }
      } else {
        providerSource = ExpressionProviderSource(
            provider.token!, convertValueToOutputAst(provider.useValue));
      }
      providerSources.add(providerSource);
    }
    if (isLocalAlias) {
      // This provider is just an alias for an existing field/instance
      // on the same view class, so just add the existing reference for this
      // token.
      var provider = resolvedProvider.providers.single;
      var alias = provider.useExisting!;
      if (_aliasedProviders.containsKey(alias)) {
        alias = _aliasedProviders.get(alias)!;
      }
      if (!_aliases.containsKey(alias)) {
        _aliases.add(alias, <CompileTokenMetadata>[]);
      }
      _aliases.get(alias)!.add(provider.token!);
      _aliasedProviders.add(resolvedProvider.token, alias);
      _instances.add(resolvedProvider.token, _instances.get(alias)!);
    } else {
      var token = resolvedProvider.token;
      _instances.add(
          token,
          _host.createProviderInstance(resolvedProvider, directiveMetadata,
              providerSources, _instances.length));
    }
  }
}