Future Function()

in build_runner_core/lib/src/asset_graph/graph.dart [259:370]


      Future Function(AssetId id) delete,
      AssetReader digestReader) async {
    var newIds = <AssetId>{};
    var modifyIds = <AssetId>{};
    var removeIds = <AssetId>{};
    updates.forEach((id, changeType) {
      if (changeType != ChangeType.ADD && get(id) == null) return;
      switch (changeType) {
        case ChangeType.ADD:
          newIds.add(id);
          break;
        case ChangeType.MODIFY:
          modifyIds.add(id);
          break;
        case ChangeType.REMOVE:
          removeIds.add(id);
          break;
      }
    });

    var newAndModifiedNodes = [
      for (var id in modifyIds) get(id)!,
      ..._addSources(newIds),
    ];
    // Pre-emptively compute digests for the new and modified nodes we know have
    // outputs.
    await _setLastKnownDigests(
        newAndModifiedNodes.where((node) =>
            node.isValidInput &&
            (node.outputs.isNotEmpty ||
                node.primaryOutputs.isNotEmpty ||
                node.lastKnownDigest != null)),
        digestReader);

    // Collects the set of all transitive ids to be removed from the graph,
    // based on the removed `SourceAssetNode`s by following the
    // `primaryOutputs`.
    var transitiveRemovedIds = <AssetId>{};
    void addTransitivePrimaryOutputs(AssetId id) {
      transitiveRemovedIds.add(id);
      get(id)!.primaryOutputs.forEach(addTransitivePrimaryOutputs);
    }

    removeIds
        .where((id) => get(id) is SourceAssetNode)
        .forEach(addTransitivePrimaryOutputs);

    // The generated nodes to actually delete from the file system.
    var idsToDelete = Set<AssetId>.from(transitiveRemovedIds)
      ..removeAll(removeIds);

    // We definitely need to update manually deleted outputs.
    for (var deletedOutput
        in removeIds.map(get).whereType<GeneratedAssetNode>()) {
      deletedOutput.state = NodeState.definitelyNeedsUpdate;
    }

    // Transitively invalidates all assets. This needs to happen after the
    // structure of the graph has been updated.
    var invalidatedIds = <AssetId>{};

    var newGeneratedOutputs =
        _addOutputsForSources(buildPhases, newIds, rootPackage);
    var allNewAndDeletedIds = {...newGeneratedOutputs, ...transitiveRemovedIds};

    void invalidateNodeAndDeps(AssetId id) {
      var node = get(id);
      if (node == null) return;
      if (!invalidatedIds.add(id)) return;

      if (node is NodeWithInputs && node.state == NodeState.upToDate) {
        node.state = NodeState.mayNeedUpdate;
      }

      // Update all outputs of this asset as well.
      for (var output in node.outputs) {
        invalidateNodeAndDeps(output);
      }
    }

    for (var changed in updates.keys.followedBy(newGeneratedOutputs)) {
      invalidateNodeAndDeps(changed);
    }

    // For all new or deleted assets, check if they match any glob nodes and
    // invalidate those.
    for (var id in allNewAndDeletedIds) {
      var samePackageGlobNodes = packageNodes(id.package)
          .whereType<GlobAssetNode>()
          .where((n) => n.state == NodeState.upToDate);
      for (final node in samePackageGlobNodes) {
        if (node.glob.matches(id.path)) {
          invalidateNodeAndDeps(node.id);
          node.state = NodeState.mayNeedUpdate;
        }
      }
    }

    // Delete all the invalidated assets, then remove them from the graph. This
    // order is important because some `AssetWriter`s throw if the id is not in
    // the graph.
    await Future.wait(idsToDelete.map(delete));

    // Remove all deleted source assets from the graph, which also recursively
    // removes all their primary outputs.
    for (var id in removeIds.where((id) => get(id) is SourceAssetNode)) {
      invalidateNodeAndDeps(id);
      _removeRecursive(id);
    }

    return invalidatedIds;
  }