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

Unified Diff: pkg/barback/lib/src/phase_output.dart

Issue 23038018: Factor a PhaseOutput class out of Phase. (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 side-by-side diff with in-line comments
Download patch
« pkg/barback/lib/src/asset_node.dart ('K') | « pkg/barback/lib/src/phase.dart ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: pkg/barback/lib/src/phase_output.dart
diff --git a/pkg/barback/lib/src/phase_output.dart b/pkg/barback/lib/src/phase_output.dart
new file mode 100644
index 0000000000000000000000000000000000000000..ae309d9820eba63990cd6e77601aabc457d5a267
--- /dev/null
+++ b/pkg/barback/lib/src/phase_output.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library barback.phase_output;
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'asset_cascade.dart';
+import 'asset_id.dart';
+import 'asset_node.dart';
+import 'errors.dart';
+import 'phase_input.dart';
+import 'stream_pool.dart';
+import 'transformer.dart';
+import 'utils.dart';
+
+/// A class that handles a single output of a phase.
+///
+/// Normally there's only a single [AssetNode] for a phase's output, but it's
+/// possible that multiple transformers in the same phase emit assets with the
+/// same id, causing collisions. This handles those collisions by forwarding the
+/// chronologically first asset.
+class PhaseOutput {
+ /// The phase for which this is an output.
+ final Phase _phase;
+
+ /// The asset node for this output.
+ AssetNode get output => _outputController.node;
+ final AssetNodeController _outputController;
+
+ /// The assets for this output.
+ ///
+ /// If there's no collision, this will only have one element. Otherwise, it
+ /// will be ordered by which asset was added first.
+ final _assets = new Queue<AssetNode>();
+
+ /// The [AssetCollisionException] for this output, or null if there is no
+ /// collision currently.
+ AssetCollisionException get collisionException {
+ if (_assets.length == 1) return null;
+ return new AssetCollisionException(
+ _assets.where((asset) => asset.transform != null)
+ .map((asset) => asset.transform.info),
+ output.id);
+ }
+
+ PhaseOutput(this._phase, AssetNode output)
+ : _outputController = new AssetNodeController.from(output) {
+ assert(!output.state.isRemoved);
+ add(output);
+ }
+
+ /// Adds an asset node as an output with this id.
+ void add(AssetNode node) {
+ assert(node.id == output.id);
+ _assets.add(node);
+ _watchAsset(node);
+ }
+
+ /// Watches [node] for state changes and adjusts [_assets] and [output]
+ /// appropriately when they occur.
+ void _watchAsset(AssetNode node) {
+ node.onStateChange.listen((state) {
+ if (state.isRemoved) {
+ _removeAsset(node);
+ return;
+ }
+ if (_assets.first != node) return;
+
+ if (state.isAvailable) {
+ _outputController.setAvailable(node.asset);
+ } else {
+ assert(state.isDirty);
+ _outputController.setDirty();
+ }
+ });
+ }
+
+ /// Removes [node] as an output.
+ void _removeAsset(AssetNode node) {
+ if (_assets.length == 1) {
+ assert(_assets.single == node);
+ _outputController.setRemoved();
+ return;
+ }
+
+ // If there was more than one asset, we're resolving a collision --
+ // possibly partially.
+ var wasFirst = _assets.first == node;
+ _assets.remove(node);
+
+ // If this was the first asset, we replace it with the next asset
+ // (chronologically).
+ if (wasFirst) {
+ var newOutput = _assets.first;
+ _outputController.setTransform(newOutput.transform);
+ if (newOutput.state.isAvailable) {
+ if (output.state.isAvailable) _outputController.setDirty();
+ _outputController.setAvailable(newOutput.asset);
+ } else {
+ assert(newOutput.isDirty);
+ if (!output.isDirty) _outputController.setDirty();
+ }
+ }
+
+ // If there's still a collision, report it. This lets the user know
+ // if they've successfully resolved the collision or not.
+ if (_assets.length > 1) {
+ // Pump the event queue to ensure that the removal of the input triggers
+ // a new build to which we can attach the error.
+ // TODO(nweiz): report this through the output asset.
+ newFuture(() => _phase.cascade.reportError(collisionException));
+ }
+ }
+}
« pkg/barback/lib/src/asset_node.dart ('K') | « pkg/barback/lib/src/phase.dart ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698