addOrGetNode method

Future<Node> addOrGetNode(
  1. Type nodeType, {
  2. Object? tag,
  3. bool root = false,
  4. int depth = 0,
})

Implementation

Future<Node> addOrGetNode(Type nodeType,
        {Object? tag, bool root = false, int depth = 0}) =>
    _lockFor(nodeType, tag: tag).synchronized(() async {
      Node? existing = getNode(nodeType, tag: tag);
      bool instanced = Node.$nodeAnnotation<Instanced>(nodeType) != null;

      if (instanced || existing == null) {
        PrecisionStopwatch p = PrecisionStopwatch.start();
        existing = Curse.clazz(nodeType).constructors.first.construct();

        nodes.add(existing!);
        existing.$pool = this;

        if (root) {
          logger ??= existing.logger;
        }

        existing.$tag = tag;
        existing.$rootNode = root;
        List<Future> work = [];

        for (VariableMirror f in existing.$dependencyFields()) {
          Object? tag = (f.metadata
                  .where((m) => m.reflectee is Tag)
                  .map((m) => m.reflectee as Tag)
                  .firstOrNull)
              ?.value;
          work.add(
              addOrGetNode(f.type.reflectedType, tag: tag, depth: depth + 1)
                  .then((d) {
            d.$referenceCount++;
            reflect(existing).setField(f.simpleName, d);
          }));
        }

        await Future.wait(work);

        for (Future<void> Function(Node, NodeStorage, PrecisionStopwatch) f
            in onStartPipeline) {
          await f(existing, storage, p);
        }
      }

      return existing;
    });