@@ -112,21 +112,10 @@ class AnalysisDriverModel {
112
112
113
113
// If requested, find transitive imports.
114
114
if (transitive) {
115
- await _graph.load (buildStep, entryPoints);
115
+ final previouslyMissingFiles = await _graph.load (buildStep, entryPoints);
116
+ _syncedOntoResourceProvider.removeAll (previouslyMissingFiles);
116
117
idsToSyncOntoResourceProvider = _graph.nodes.keys.toList ();
117
118
inputIds = _graph.inputsFor (entryPoints);
118
-
119
- // Check for inputs that were missing when the directive graph was read
120
- // but have since been written by another build action.
121
- for (final id in inputIds
122
- .where ((id) => ! id.path.endsWith (_transitiveDigestExtension))) {
123
- if (_graph.nodes[id]! .isMissing) {
124
- if (await buildStep.canRead (id)) {
125
- idsToSyncOntoResourceProvider.add (id);
126
- _syncedOntoResourceProvider.remove (id);
127
- }
128
- }
129
- }
130
119
}
131
120
132
121
// Notify [buildStep] of its inputs.
@@ -203,33 +192,50 @@ class _Graph {
203
192
final Map <AssetId , _Node > nodes = {};
204
193
205
194
/// Walks the import graph from [ids] loading into [nodes] .
206
- Future <void > load (AssetReader reader, Iterable <AssetId > ids) async {
195
+ ///
196
+ /// Checks files that are in the graph as missing to determine whether they
197
+ /// are now available.
198
+ ///
199
+ /// Returns the set of files that were in the graph as missing and have now
200
+ /// been loaded.
201
+ Future <Set <AssetId >> load (AssetReader reader, Iterable <AssetId > ids) async {
207
202
// TODO(davidmorgan): check if List is faster.
208
203
final nextIds = Queue .of (ids);
204
+ final processed = < AssetId > {};
205
+ final previouslyMissingFiles = < AssetId > {};
209
206
while (nextIds.isNotEmpty) {
210
207
final nextId = nextIds.removeFirst ();
211
208
212
- // Skip if already seen.
213
- if (nodes.containsKey (nextId)) continue ;
209
+ if (! processed.add (nextId)) continue ;
214
210
215
- final hasTransitiveDigestAsset =
216
- await reader.canRead (nextId.addExtension (_transitiveDigestExtension));
217
-
218
- // Skip if not readable.
219
- if (! await reader.canRead (nextId)) {
220
- nodes[nextId] = _Node .missing (
221
- id: nextId, hasTransitiveDigestAsset: hasTransitiveDigestAsset);
222
- continue ;
211
+ // Read nodes not yet loaded or that were missing when loaded.
212
+ var node = nodes[nextId];
213
+ if (node == null || node.isMissing) {
214
+ if (await reader.canRead (nextId)) {
215
+ // If it was missing when loaded, record that.
216
+ if (node != null && node.isMissing) {
217
+ previouslyMissingFiles.add (nextId);
218
+ }
219
+ // Load the node.
220
+ final hasTransitiveDigestAsset = await reader
221
+ .canRead (nextId.addExtension (_transitiveDigestExtension));
222
+ final content = await reader.readAsString (nextId);
223
+ final deps = _parseDependencies (content, nextId);
224
+ node = _Node (
225
+ id: nextId,
226
+ deps: deps,
227
+ hasTransitiveDigestAsset: hasTransitiveDigestAsset);
228
+ } else {
229
+ node ?? = _Node .missing (id: nextId, hasTransitiveDigestAsset: false );
230
+ }
231
+ nodes[nextId] = node;
223
232
}
224
233
225
- final content = await reader.readAsString (nextId);
226
- final deps = _parseDependencies (content, nextId);
227
- nodes[nextId] = _Node (
228
- id: nextId,
229
- deps: deps,
230
- hasTransitiveDigestAsset: hasTransitiveDigestAsset);
231
- nextIds.addAll (deps.where ((id) => ! nodes.containsKey (id)));
234
+ // Continue to deps even for already-loaded nodes, to check missing files.
235
+ nextIds.addAll (node.deps.where ((id) => ! processed.contains (id)));
232
236
}
237
+
238
+ return previouslyMissingFiles;
233
239
}
234
240
235
241
void clear () {
0 commit comments