@@ -82,6 +82,8 @@ class LibraryCycleGraphLoader {
82
82
_newAssets.clear ();
83
83
_cycles.clear ();
84
84
_graphs.clear ();
85
+ _graphsToComputeByPhase.clear ();
86
+ _runningAtPhases.clear ();
85
87
}
86
88
87
89
/// Loads [id] and its transitive dependencies at all phases available to
@@ -103,9 +105,10 @@ class LibraryCycleGraphLoader {
103
105
.where ((entry) => entry.key <= assetDepsLoader.phase)
104
106
.any ((entry) => entry.value.isNotEmpty)) {
105
107
final firstPhase = (_idsToLoad.keys..toList ().sort ()).firstWhere (
106
- (key) => key <= assetDepsLoader.phase && _idsToLoad[key]! .isNotEmpty);
108
+ (key) => key <= assetDepsLoader.phase && _idsToLoad[key]! .isNotEmpty,
109
+ );
107
110
final idToLoad = _idsToLoad[firstPhase]! .last;
108
- print ('($_runningAtPhases , $id ) take $idToLoad at phase $firstPhase ' );
111
+ // print('($_runningAtPhases, $id) take $idToLoad at phase $firstPhase');
109
112
110
113
// Nothing to do if deps were already loaded, unless they expire and
111
114
// [assetDepsLoader] is at a late enough phase to see the updated value.
@@ -116,41 +119,44 @@ class LibraryCycleGraphLoader {
116
119
continue ;
117
120
}
118
121
119
- print (
120
- '($_runningAtPhases , $id ) Load $idToLoad at ${assetDepsLoader .phase }' );
122
+ /* print(
123
+ '($_runningAtPhases, $id) Load
124
+ $idToLoad at ${assetDepsLoader.phase}');*/
121
125
final assetDeps =
122
126
_assetDeps[idToLoad] = await assetDepsLoader.load (idToLoad);
123
127
124
128
// First time seeing the asset, mark for computation of cycles and
125
129
// graphs given the initial state of the build.
126
130
if (alreadyLoadedAssetDeps == null ) {
127
- print ('For phase $firstPhase , Add to new assets: $idToLoad ' );
131
+ // print('For phase $firstPhase, Add to new assets: $idToLoad');
128
132
_newAssets.add (idToLoad);
129
133
}
130
134
131
135
if (assetDeps.isComplete) {
132
136
// "isComplete" means it's a source file or a generated value that has
133
137
// already been generated. It has deps, so mark them for loading.
134
- print (
135
- '($_runningAtPhases , $id ) Completed $idToLoad : ${assetDeps .lastValue .deps }' );
138
+ /* print(
139
+ '($_runningAtPhases, $id) Completed $idToLoad:
140
+ ${assetDeps.lastValue.deps}');*/
136
141
for (final dep in assetDeps.lastValue.deps) {
137
142
final phaseIdsToLoad = _idsToLoad[0 ] ?? = [];
138
143
phaseIdsToLoad.add (dep);
139
- print ('($_runningAtPhases , $id ) add $dep to _idsToLoad at 0' );
144
+ // print('($_runningAtPhases, $id) add $dep to _idsToLoad at 0');
140
145
}
141
- print ('Ehm: $thisPhaseIdsToLoad --- $_idsToLoad ' );
146
+ // print('Ehm: $thisPhaseIdsToLoad --- $_idsToLoad');
142
147
} else {
143
148
// It's a generated source that has not yet been generated. Mark it for
144
149
// loading later.
145
- print ('($_runningAtPhases , $id ) Add $idToLoad to IDs to load later' );
146
- (_idsToLoad[assetDeps.values.last.expiresAfter! + 1 ] ?? = [])
147
- .add (idToLoad);
150
+ // print('($_runningAtPhases, $id) Add $idToLoad to IDs to load later');
151
+ (_idsToLoad[assetDeps.values.last.expiresAfter! + 1 ] ?? = []).add (
152
+ idToLoad,
153
+ );
148
154
}
149
155
150
156
_idsToLoad[firstPhase]! .remove (idToLoad);
151
157
}
152
158
153
- print ('($_runningAtPhases , $id ) returning: $_idsToLoad ' );
159
+ // print('($_runningAtPhases, $id) returning: $_idsToLoad');
154
160
}
155
161
156
162
/// Computes [_cycles] for all [_newAssets] at phase 0, then for all assets
@@ -167,11 +173,13 @@ class LibraryCycleGraphLoader {
167
173
// Process phases that have work to do in ascending order.
168
174
while (true ) {
169
175
int phase;
170
- Set <AssetId > idsToComputeCyclesFrom;
176
+ Iterable <AssetId > idsToComputeCyclesFrom;
171
177
if (_newAssets.isNotEmpty) {
172
178
// New assets: work to do at phase 0, the initial build state.
173
179
phase = 0 ;
174
- idsToComputeCyclesFrom = _newAssets;
180
+ idsToComputeCyclesFrom = _newAssets.where (
181
+ (id) => ! _cycles.containsKey (id),
182
+ );
175
183
_newAssets = {};
176
184
} else {
177
185
// Work through phases <= `upToPhase` at which graphs expire,
@@ -184,9 +192,8 @@ class LibraryCycleGraphLoader {
184
192
185
193
// Edges for strongly connected components computation.
186
194
Iterable <AssetId > edgesFromId (AssetId id) {
187
- print ('Edges for $id ' );
195
+ // print('Edges for $id');
188
196
final deps = _assetDeps[id]! .valueAt (phase: phase).deps;
189
- return deps;
190
197
191
198
// Check edge against cycles that have already been computed
192
199
// at the current `phase`. Newly discovered assets at the same phase
@@ -197,29 +204,30 @@ class LibraryCycleGraphLoader {
197
204
);
198
205
}
199
206
200
- print ('Up to $upToPhase , compute $phase ' );
207
+ // print('Up to $upToPhase, compute $phase');
201
208
202
209
// Do the strongly connected components computation and convert
203
210
// from its output, a list of lists of IDs, to a list of [LibraryCycle].
204
211
final newComponentLists = stronglyConnectedComponents (
205
212
idsToComputeCyclesFrom,
206
213
edgesFromId,
207
214
);
208
- final newCycles = newComponentLists.map ((list) {
209
- // Compare to the library cycle computed at `phase - 1`. If the
210
- // cycles are the same size then they must have the same contents,
211
- // because cycles only change by growing as phases progress. In that
212
- // case, reuse the existing [LibraryCycle].
213
- final maybePhasedCycle = _cycles[list.first];
214
- if (maybePhasedCycle != null ) {
215
- final value = maybePhasedCycle.valueAt (phase: phase - 1 );
216
- if (value.ids.length == list.length) {
217
- return value;
218
- }
219
- }
220
- // The cycle is new or has changed, return a new value.
221
- return LibraryCycle ((b) => b..ids.replace (list));
222
- }).toList ();
215
+ final newCycles =
216
+ newComponentLists.map ((list) {
217
+ // Compare to the library cycle computed at `phase - 1`. If the
218
+ // cycles are the same size then they must have the same contents,
219
+ // because cycles only change by growing as phases progress. In that
220
+ // case, reuse the existing [LibraryCycle].
221
+ final maybePhasedCycle = _cycles[list.first];
222
+ if (maybePhasedCycle != null ) {
223
+ final value = maybePhasedCycle.valueAt (phase: phase - 1 );
224
+ if (value.ids.length == list.length) {
225
+ return value;
226
+ }
227
+ }
228
+ // The cycle is new or has changed, return a new value.
229
+ return LibraryCycle ((b) => b..ids.replace (list));
230
+ }).toList ();
223
231
224
232
// Build graphs from cycles.
225
233
_buildGraphs (phase, newCycles: newCycles);
@@ -229,9 +237,10 @@ class LibraryCycleGraphLoader {
229
237
// it gets a new dep that leads back to the cycle then that whole path
230
238
// joins the cycle. Get this expirey phase from the graph built by
231
239
// `_buildGraphs`.
232
- final expiresAfter = _graphs[cycle.ids.first]!
233
- .expiringValueAt (phase: phase)
234
- .expiresAfter;
240
+ final expiresAfter =
241
+ _graphs[cycle.ids.first]!
242
+ .expiringValueAt (phase: phase)
243
+ .expiresAfter;
235
244
236
245
// Merge the computed cycle into any existing phased value for each ID.
237
246
// The phased value can differ by ID: they are in the same cycle at this
@@ -240,18 +249,23 @@ class LibraryCycleGraphLoader {
240
249
// Nevertheless, the case in which the phased values are the same is a
241
250
// common one, so use a temporary map from old value to new value to
242
251
// avoid creating many equal but not identical phased values.
243
- final updatedValueByOldValue = Map <PhasedValue <LibraryCycle >?,
244
- PhasedValue <LibraryCycle >>.identity ();
252
+ final updatedValueByOldValue =
253
+ Map <
254
+ PhasedValue <LibraryCycle >?,
255
+ PhasedValue <LibraryCycle >
256
+ >.identity ();
245
257
246
258
for (final id in cycle.ids) {
247
259
final existingCycle = _cycles[id];
248
260
_cycles[id] = updatedValueByOldValue.putIfAbsent (existingCycle, () {
249
261
if (existingCycle == null ) {
250
262
return PhasedValue .of (cycle, expiresAfter: expiresAfter);
251
263
}
252
- final newValue =
253
- ExpiringValue <LibraryCycle >(cycle, expiresAfter: expiresAfter);
254
- if (existingCycle.values.contains (newValue)) return existingCycle;
264
+ final newValue = ExpiringValue <LibraryCycle >(
265
+ cycle,
266
+ expiresAfter: expiresAfter,
267
+ );
268
+ //if (existingCycle.values.contains(newValue)) return existingCycle;
255
269
return existingCycle.followedBy (newValue);
256
270
});
257
271
}
@@ -329,18 +343,23 @@ class LibraryCycleGraphLoader {
329
343
// Nevertheless, the case in which the phased values are the same is a
330
344
// common one, so use a temporary map from old value to new value to
331
345
// avoid creating many equal but not identical phased values.
332
- final updatedValueByOldValue = Map <PhasedValue <LibraryCycleGraph >?,
333
- PhasedValue <LibraryCycleGraph >>.identity ();
346
+ final updatedValueByOldValue =
347
+ Map <
348
+ PhasedValue <LibraryCycleGraph >?,
349
+ PhasedValue <LibraryCycleGraph >
350
+ >.identity ();
334
351
335
352
for (final idToUpdate in root.ids) {
336
353
final oldValue = _graphs[idToUpdate];
337
354
_graphs[idToUpdate] = updatedValueByOldValue.putIfAbsent (oldValue, () {
338
355
if (oldValue == null ) {
339
356
return PhasedValue .of (graph.build (), expiresAfter: expiresAfter);
340
357
}
341
- final newValue =
342
- ExpiringValue (graph.build (), expiresAfter: expiresAfter);
343
- if (oldValue.values.contains (newValue)) return oldValue;
358
+ final newValue = ExpiringValue (
359
+ graph.build (),
360
+ expiresAfter: expiresAfter,
361
+ );
362
+ //if (oldValue.values.contains(newValue)) return oldValue;
344
363
return oldValue.followedBy (newValue);
345
364
});
346
365
}
@@ -358,9 +377,11 @@ class LibraryCycleGraphLoader {
358
377
) async {
359
378
if (_runningAtPhases.isNotEmpty &&
360
379
assetDepsLoader.phase >= _runningAtPhases.last) {
361
- throw StateError ('Cannot recurse at phase ${assetDepsLoader .phase }, '
362
- 'already running at an equal or earlier phase. '
363
- 'Already running at : $_runningAtPhases ' );
380
+ throw StateError (
381
+ 'Cannot recurse at phase ${assetDepsLoader .phase }, '
382
+ 'already running at an equal or earlier phase. '
383
+ 'Already running at : $_runningAtPhases ' ,
384
+ );
364
385
}
365
386
_runningAtPhases.add (assetDepsLoader.phase);
366
387
try {
0 commit comments