readProviderElement<State> method Null safety

ProviderElementBase<State> readProviderElement<State>(
  1. ProviderBase<State> provider
)

Reads the state of a provider, potentially creating it in the process.

It may throw if the provider requested threw when it was built.

Do not use this in production code. This is exposed only for testing and devtools, to be able to test if a provider has listeners or similar.

Implementation

ProviderElementBase<State> readProviderElement<State>(
  ProviderBase<State> provider,
) {
  if (_disposed) {
    throw StateError(
      'Tried to read a provider from a ProviderContainer that was already disposed',
    );
  }

  final reader = _getStateReader(provider);

  assert(() {
    // Avoid having the assert trigger itself exponentially
    if (!_debugVerifyDependenciesAreRespectedEnabled) return true;

    try {
      _debugVerifyDependenciesAreRespectedEnabled = false;

      // Check that this containers doesn't have access to an overridden
      // dependency of the targetted provider
      final targetElement = reader.getElement();
      final visitedDependencies = <ProviderBase>{};
      final queue = Queue<ProviderBase>();
      targetElement.visitAncestors((e) => queue.add(e.origin));

      while (queue.isNotEmpty) {
        final dependency = queue.removeFirst();
        if (visitedDependencies.add(dependency)) {
          final dependencyElement = readProviderElement<Object?>(dependency);

          assert(
              targetElement.provider != targetElement.origin ||
                  dependencyElement ==
                      targetElement.container
                          .readProviderElement<Object?>(dependency),
              '''
Tried to read $provider from a place where one of its dependencies were overridden but the provider is not.

To fix this error, you can add add "dependencies" to $provider such that we have:

```
final a = Provider(...);
final b = Provider((ref) => ref.watch(a), dependencies: [a]);
```
''');

          dependencyElement.visitAncestors((e) => queue.add(e.origin));
        }
      }
    } finally {
      _debugVerifyDependenciesAreRespectedEnabled = true;
    }
    return true;
  }(), '');

  return reader.getElement() as ProviderElementBase<State>;
}