@@ -48,6 +48,8 @@ class AssetGraph implements GeneratedAssetHider {
48
48
49
49
final BuiltMap <String , LanguageVersion ?> packageLanguageVersions;
50
50
51
+ Map <AssetId , Set <AssetId >>? _outputs;
52
+
51
53
/// All post process build steps outputs, indexed by package then
52
54
/// [PostProcessBuildStepId] .
53
55
///
@@ -128,6 +130,15 @@ class AssetGraph implements GeneratedAssetHider {
128
130
if (node == null ) throw StateError ('Missing node: $id ' );
129
131
final updatedNode = node.rebuild (updates);
130
132
_nodesByPackage[id.package]! [id.path] = updatedNode;
133
+
134
+ if (updatedNode.type == NodeType .generated) {
135
+ if (node.type != NodeType .generated ||
136
+ updatedNode.generatedNodeState! .inputs !=
137
+ node.generatedNodeState! .inputs) {
138
+ _outputs = null ;
139
+ }
140
+ }
141
+
131
142
return updatedNode;
132
143
}
133
144
@@ -144,6 +155,16 @@ class AssetGraph implements GeneratedAssetHider {
144
155
if (node == null ) return null ;
145
156
final updatedNode = node.rebuild (updates);
146
157
_nodesByPackage[id.package]! [id.path] = updatedNode;
158
+
159
+ // TODO(davidmorgan): dedupe.
160
+ if (updatedNode.type == NodeType .generated) {
161
+ if (node.type != NodeType .generated ||
162
+ updatedNode.generatedNodeState! .inputs !=
163
+ node.generatedNodeState! .inputs) {
164
+ _outputs = null ;
165
+ }
166
+ }
167
+
147
168
return updatedNode;
148
169
}
149
170
@@ -161,7 +182,6 @@ class AssetGraph implements GeneratedAssetHider {
161
182
// primary outputs. We only want to remove this node.
162
183
_nodesByPackage[existing.id.package]! .remove (existing.id.path);
163
184
node = node.rebuild ((b) {
164
- b.outputs.addAll (existing.outputs);
165
185
b.primaryOutputs.addAll (existing.primaryOutputs);
166
186
});
167
187
} else {
@@ -173,6 +193,10 @@ class AssetGraph implements GeneratedAssetHider {
173
193
}
174
194
_nodesByPackage.putIfAbsent (node.id.package, () => {})[node.id.path] = node;
175
195
196
+ if (node.type == NodeType .generated || node.type == NodeType .glob) {
197
+ _outputs = null ;
198
+ }
199
+
176
200
return node;
177
201
}
178
202
@@ -269,7 +293,8 @@ class AssetGraph implements GeneratedAssetHider {
269
293
anchorOutputs: anchorOutputs,
270
294
);
271
295
}
272
- for (var output in node.outputs) {
296
+ final outputs = computeOutputs ();
297
+ for (var output in (outputs[node.id] ?? const < AssetId > {})) {
273
298
updateNodeIfPresent (output, (nodeBuilder) {
274
299
if (nodeBuilder.type == NodeType .generated) {
275
300
nodeBuilder.generatedNodeState.inputs.remove (id);
@@ -285,23 +310,14 @@ class AssetGraph implements GeneratedAssetHider {
285
310
for (var input in node.generatedNodeState! .inputs) {
286
311
// We may have already removed this node entirely.
287
312
updateNodeIfPresent (input, (nodeBuilder) {
288
- nodeBuilder
289
- ..outputs.remove (id)
290
- ..primaryOutputs.remove (id);
313
+ nodeBuilder.primaryOutputs.remove (id);
291
314
});
292
315
}
293
- updateNode (node.generatedNodeConfiguration! .builderOptionsId, (
294
- nodeBuilder,
295
- ) {
296
- nodeBuilder.outputs.remove (id);
297
- });
298
316
} else if (node.type == NodeType .glob) {
299
317
for (var input in node.globNodeState! .inputs) {
300
318
// We may have already removed this node entirely.
301
319
updateNodeIfPresent (input, (nodeBuilder) {
302
- nodeBuilder
303
- ..outputs.remove (id)
304
- ..primaryOutputs.remove (id);
320
+ nodeBuilder.primaryOutputs.remove (id);
305
321
});
306
322
}
307
323
}
@@ -319,6 +335,23 @@ class AssetGraph implements GeneratedAssetHider {
319
335
return removedIds;
320
336
}
321
337
338
+ Map <AssetId , Set <AssetId >> computeOutputs () {
339
+ if (_outputs != null ) return _outputs! ;
340
+ final result = < AssetId , Set <AssetId >> {};
341
+ for (final node in allNodes) {
342
+ if (node.type == NodeType .generated) {
343
+ result
344
+ .putIfAbsent (node.id, () => {})
345
+ .addAll (node.generatedNodeState! .inputs);
346
+ } else if (node.type == NodeType .glob) {
347
+ result
348
+ .putIfAbsent (node.id, () => {})
349
+ .addAll (node.globNodeState! .inputs);
350
+ }
351
+ }
352
+ return _outputs = result;
353
+ }
354
+
322
355
/// All nodes in the graph, whether source files or generated outputs.
323
356
Iterable <AssetNode > get allNodes =>
324
357
_nodesByPackage.values.expand ((pkdIds) => pkdIds.values);
@@ -410,8 +443,7 @@ class AssetGraph implements GeneratedAssetHider {
410
443
.where (
411
444
(node) =>
412
445
node.isTrackedInput &&
413
- (node.outputs.isNotEmpty ||
414
- node.primaryOutputs.isNotEmpty ||
446
+ (node.primaryOutputs.isNotEmpty ||
415
447
node.lastKnownDigest != null ),
416
448
)
417
449
.map ((node) => node.id),
@@ -460,6 +492,7 @@ class AssetGraph implements GeneratedAssetHider {
460
492
// Transitively invalidates all assets. This needs to happen after the
461
493
// structure of the graph has been updated.
462
494
var invalidatedIds = < AssetId > {};
495
+ final computedOutputs = computeOutputs ();
463
496
464
497
void invalidateNodeAndDeps (AssetId startNodeId) {
465
498
if (! invalidatedIds.add (startNodeId)) return ;
@@ -486,7 +519,8 @@ class AssetGraph implements GeneratedAssetHider {
486
519
});
487
520
488
521
if (invalidatedNode != null ) {
489
- for (final id in invalidatedNode.outputs) {
522
+ for (final id
523
+ in (computedOutputs[invalidatedNode.id] ?? const < AssetId > {})) {
490
524
if (invalidatedIds.add (id)) {
491
525
nodesToInvalidate.add (id);
492
526
}
@@ -713,14 +747,6 @@ class AssetGraph implements GeneratedAssetHider {
713
747
builderOptionsId: builderOptionsNode.id,
714
748
isHidden: isHidden,
715
749
);
716
- if (existing != null ) {
717
- newNode = newNode.rebuild ((b) => b..outputs.addAll (existing! .outputs));
718
- // Ensure we set up the reverse link for NodeWithInput nodes.
719
- _addInput (existing.outputs, output);
720
- }
721
- updateNode (builderOptionsNode.id, (nodeBuilder) {
722
- nodeBuilder.outputs.add (output);
723
- });
724
750
_add (newNode);
725
751
}
726
752
return removed;
@@ -733,21 +759,6 @@ class AssetGraph implements GeneratedAssetHider {
733
759
void add (AssetNode node) => _add (node);
734
760
Set <AssetId > remove (AssetId id) => _removeRecursive (id);
735
761
736
- /// Adds [input] to all [outputs] if they track inputs.
737
- ///
738
- /// Nodes that track inputs are [AssetNode.generated] or [AssetNode.glob] .
739
- void _addInput (Iterable <AssetId > outputs, AssetId input) {
740
- for (var output in outputs) {
741
- updateNodeIfPresent (output, (nodeBuilder) {
742
- if (nodeBuilder.type == NodeType .generated) {
743
- nodeBuilder.generatedNodeState.inputs.add (input);
744
- } else if (nodeBuilder.type == NodeType .glob) {
745
- nodeBuilder.globNodeState.inputs.add (input);
746
- }
747
- });
748
- }
749
- }
750
-
751
762
@override
752
763
AssetId maybeHide (AssetId id, String rootPackage) {
753
764
if (id.path.startsWith (generatedOutputDirectory) ||
0 commit comments