Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(826)

Side by Side Diff: pkg/barback/lib/src/phase.dart

Issue 22961002: Add more metadata to non-programmatic barback exceptions. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 7 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
2 // for details. All rights reserved. Use of this source code is governed by a 2 // for details. All rights reserved. Use of this source code is governed by a
3 // BSD-style license that can be found in the LICENSE file. 3 // BSD-style license that can be found in the LICENSE file.
4 4
5 library barback.phase; 5 library barback.phase;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:collection';
9 8
10 import 'asset.dart'; 9 import 'asset.dart';
11 import 'asset_cascade.dart'; 10 import 'asset_cascade.dart';
12 import 'asset_id.dart'; 11 import 'asset_id.dart';
13 import 'asset_node.dart'; 12 import 'asset_node.dart';
14 import 'asset_set.dart'; 13 import 'asset_set.dart';
15 import 'errors.dart'; 14 import 'errors.dart';
16 import 'stream_pool.dart'; 15 import 'stream_pool.dart';
17 import 'transform_node.dart'; 16 import 'transform_node.dart';
18 import 'transformer.dart'; 17 import 'transformer.dart';
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 /// Whenever an asset is added or modified, we need to asynchronously 61 /// Whenever an asset is added or modified, we need to asynchronously
63 /// determine which transformers can use it as their primary input. We can't 62 /// determine which transformers can use it as their primary input. We can't
64 /// start processing until we know which transformers to run, and this allows 63 /// start processing until we know which transformers to run, and this allows
65 /// us to wait until we do. 64 /// us to wait until we do.
66 var _adjustTransformersFutures = new Map<AssetId, Future>(); 65 var _adjustTransformersFutures = new Map<AssetId, Future>();
67 66
68 /// New asset nodes that were added while [_adjustTransformers] was still 67 /// New asset nodes that were added while [_adjustTransformers] was still
69 /// being run on an old version of that asset. 68 /// being run on an old version of that asset.
70 var _pendingNewInputs = new Map<AssetId, AssetNode>(); 69 var _pendingNewInputs = new Map<AssetId, AssetNode>();
71 70
72 /// A map of output ids to the asset node outputs for those ids. 71 /// A map of output ids to the asset node outputs for those ids and the
72 /// transforms that produced those asset nodes.
73 /// 73 ///
74 /// Usually there's only one node for a given output id. However, it's 74 /// Usually there's only one node for a given output id. However, it's
75 /// possible for multiple transformers in this phase to output an asset with 75 /// possible for multiple transformers in this phase to output an asset with
76 /// the same id. In that case, the chronologically first output emitted is 76 /// the same id. In that case, the chronologically first output emitted is
77 /// passed forward. We keep track of the other nodes so that if that output is 77 /// passed forward. We keep track of the other nodes so that if that output is
78 /// removed, we know which asset to replace it with. 78 /// removed, we know which asset to replace it with.
79 final _outputs = new Map<AssetId, Queue<AssetNode>>(); 79 final _outputs = new Map<AssetId, List<Pair<AssetNode, TransformNode>>>();
Bob Nystrom 2013/08/13 00:04:29 Using a Pair here makes the code pretty hairy. How
nweiz 2013/08/13 19:15:11 Good idea. This will make it easier to do analysis
80 80
81 /// A stream that emits an event whenever this phase becomes dirty and needs 81 /// A stream that emits an event whenever this phase becomes dirty and needs
82 /// to be run. 82 /// to be run.
83 /// 83 ///
84 /// This may emit events when the phase was already dirty or while processing 84 /// This may emit events when the phase was already dirty or while processing
85 /// transforms. Events are emitted synchronously to ensure that the dirty 85 /// transforms. Events are emitted synchronously to ensure that the dirty
86 /// state is thoroughly propagated as soon as any assets are changed. 86 /// state is thoroughly propagated as soon as any assets are changed.
87 Stream get onDirty => _onDirtyPool.stream; 87 Stream get onDirty => _onDirtyPool.stream;
88 final _onDirtyPool = new StreamPool.broadcast(); 88 final _onDirtyPool = new StreamPool.broadcast();
89 89
(...skipping 222 matching lines...) Expand 10 before | Expand all | Expand 10 after
312 var dirtyTransforms = 312 var dirtyTransforms =
313 flatten(_transforms.values.map((transforms) => transforms.toList())) 313 flatten(_transforms.values.map((transforms) => transforms.toList()))
314 .where((transform) => transform.isDirty).toList(); 314 .where((transform) => transform.isDirty).toList();
315 if (dirtyTransforms.isEmpty) return null; 315 if (dirtyTransforms.isEmpty) return null;
316 316
317 var collisions = new Set<AssetId>(); 317 var collisions = new Set<AssetId>();
318 return Future.wait(dirtyTransforms.map((transform) { 318 return Future.wait(dirtyTransforms.map((transform) {
319 return transform.apply().then((outputs) { 319 return transform.apply().then((outputs) {
320 for (var output in outputs) { 320 for (var output in outputs) {
321 if (_outputs.containsKey(output.id)) { 321 if (_outputs.containsKey(output.id)) {
322 _outputs[output.id].add(output); 322 _outputs[output.id].add(
323 new Pair<AssetNode, TransformNode>(output, transform));
323 collisions.add(output.id); 324 collisions.add(output.id);
324 } else { 325 } else {
325 _outputs[output.id] = new Queue<AssetNode>.from([output]); 326 _outputs[output.id] = new List<Pair<AssetNode, TransformNode>>.from(
327 [new Pair<AssetNode, TransformNode>(output, transform)]);
326 _next.addInput(output); 328 _next.addInput(output);
327 } 329 }
328 330
329 _handleOutputRemoval(output); 331 _handleOutputRemoval(output);
330 } 332 }
331 }); 333 });
332 })).then((_) { 334 })).then((_) {
333 // Report collisions in a deterministic order. 335 // Report collisions in a deterministic order.
334 collisions = collisions.toList(); 336 collisions = collisions.toList();
335 collisions.sort((a, b) => a.compareTo(b)); 337 collisions.sort((a, b) => a.compareTo(b));
336 for (var collision in collisions) { 338 for (var collision in collisions) {
337 // Ensure that there's still a collision. It's possible it was resolved 339 // Ensure that there's still a collision. It's possible it was resolved
338 // while another transform was running. 340 // while another transform was running.
339 if (_outputs[collision].length <= 1) continue; 341 if (_outputs[collision].length <= 1) return;
Bob Nystrom 2013/08/13 00:04:29 Shouldn't this still be continue?
nweiz 2013/08/13 19:15:11 Yes, merge error.
340 cascade.reportError(new AssetCollisionException(collision)); 342 cascade.reportError(new AssetCollisionException(
343 _outputs[collision].map((pair) => pair.last.info),
344 collision));
341 } 345 }
342 }); 346 });
343 } 347 }
344 348
345 /// Properly resolve collisions when [output] is removed. 349 /// Properly resolve collisions when [output] is removed.
346 void _handleOutputRemoval(AssetNode output) { 350 void _handleOutputRemoval(AssetNode output) {
347 output.whenRemoved.then((_) { 351 output.whenRemoved.then((_) {
348 var assets = _outputs[output.id]; 352 var assetsAndTransforms = _outputs[output.id];
349 if (assets.length == 1) { 353 if (assetsAndTransforms.length == 1) {
350 assert(assets.single == output); 354 assert(assetsAndTransforms.single.first == output);
351 _outputs.remove(output.id); 355 _outputs.remove(output.id);
352 return; 356 return;
353 } 357 }
354 358
355 // If there was more than one asset, we're resolving a collision -- 359 // If there was more than one asset, we're resolving a collision --
356 // possibly partially. 360 // possibly partially.
357 var wasFirst = assets.first == output; 361 var wasFirst = assetsAndTransforms.first.first == output;
358 assets.remove(output); 362 assetsAndTransforms.removeWhere((pair) => pair.first == output);
359 363
360 // If this was the first asset, we need to pass the next asset 364 // If this was the first asset, we need to pass the next asset
361 // (chronologically) to the next phase. Pump the event queue first to give 365 // (chronologically) to the next phase. Pump the event queue first to give
362 // [_next] a chance to handle the removal of its input before getting a 366 // [_next] a chance to handle the removal of its input before getting a
363 // new input. 367 // new input.
364 if (wasFirst) newFuture(() => _next.addInput(assets.first)); 368 if (wasFirst) {
369 newFuture(() => _next.addInput(assetsAndTransforms.first.first));
370 }
365 371
366 // If there's still a collision, report it. This lets the user know 372 // If there's still a collision, report it. This lets the user know
367 // if they've successfully resolved the collision or not. 373 // if they've successfully resolved the collision or not.
368 if (assets.length > 1) { 374 if (assetsAndTransforms.length > 1) {
369 // Pump the event queue to ensure that the removal of the input triggers 375 // Pump the event queue to ensure that the removal of the input triggers
370 // a new build to which we can attach the error. 376 // a new build to which we can attach the error.
371 newFuture(() => 377 newFuture(() => cascade.reportError(new AssetCollisionException(
372 cascade.reportError(new AssetCollisionException(output.id))); 378 assetsAndTransforms.map((pair) => pair.last.info),
379 output.id)));
373 } 380 }
374 }); 381 });
375 } 382 }
376 } 383 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698