Chromium Code Reviews| OLD | NEW |
|---|---|
| 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.transform_node; | 5 library barback.transform_node; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 | 8 |
| 9 import 'package:source_maps/span.dart'; | |
| 10 | |
| 11 import 'asset.dart'; | 9 import 'asset.dart'; |
| 12 import 'asset_id.dart'; | 10 import 'asset_id.dart'; |
| 13 import 'asset_node.dart'; | 11 import 'asset_node.dart'; |
| 14 import 'asset_set.dart'; | 12 import 'asset_set.dart'; |
| 15 import 'declaring_transform.dart'; | 13 import 'declaring_transform.dart'; |
| 16 import 'errors.dart'; | 14 import 'errors.dart'; |
| 17 import 'lazy_transformer.dart'; | 15 import 'lazy_transformer.dart'; |
| 18 import 'log.dart'; | 16 import 'log.dart'; |
| 19 import 'phase.dart'; | 17 import 'phase.dart'; |
| 18 import 'stream_pool.dart'; | |
| 20 import 'transform.dart'; | 19 import 'transform.dart'; |
| 21 import 'transformer.dart'; | 20 import 'transformer.dart'; |
| 22 import 'utils.dart'; | 21 import 'utils.dart'; |
| 23 | 22 |
| 24 /// Describes a transform on a set of assets and its relationship to the build | 23 /// Describes a transform on a set of assets and its relationship to the build |
| 25 /// dependency graph. | 24 /// dependency graph. |
| 26 /// | 25 /// |
| 27 /// Keeps track of whether it's dirty and needs to be run and which assets it | 26 /// Keeps track of whether it's dirty and needs to be run and which assets it |
| 28 /// depends on. | 27 /// depends on. |
| 29 class TransformNode { | 28 class TransformNode { |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 63 /// processing transforms. Events are emitted synchronously to ensure that the | 62 /// processing transforms. Events are emitted synchronously to ensure that the |
| 64 /// dirty state is thoroughly propagated as soon as any assets are changed. | 63 /// dirty state is thoroughly propagated as soon as any assets are changed. |
| 65 Stream get onDirty => _onDirtyController.stream; | 64 Stream get onDirty => _onDirtyController.stream; |
| 66 final _onDirtyController = new StreamController.broadcast(sync: true); | 65 final _onDirtyController = new StreamController.broadcast(sync: true); |
| 67 | 66 |
| 68 /// A stream that emits an event whenever this transform logs an entry. | 67 /// A stream that emits an event whenever this transform logs an entry. |
| 69 /// | 68 /// |
| 70 /// This is synchronous because error logs can cause the transform to fail, so | 69 /// This is synchronous because error logs can cause the transform to fail, so |
| 71 /// we need to ensure that their processing isn't delayed until after the | 70 /// we need to ensure that their processing isn't delayed until after the |
| 72 /// transform or build has finished. | 71 /// transform or build has finished. |
| 73 Stream<LogEntry> get onLog => _onLogController.stream; | 72 Stream<LogEntry> get onLog => _onLogPool.stream; |
| 74 final _onLogController = new StreamController<LogEntry>.broadcast(sync: true); | 73 final _onLogPool = new StreamPool<LogEntry>.broadcast(); |
| 75 | 74 |
| 76 TransformNode(this.phase, Transformer transformer, this.primary, | 75 TransformNode(this.phase, Transformer transformer, this.primary, |
| 77 this._location) | 76 this._location) |
| 78 : transformer = transformer, | 77 : transformer = transformer, |
| 79 _isLazy = transformer is LazyTransformer { | 78 _isLazy = transformer is LazyTransformer { |
| 80 _primarySubscription = primary.onStateChange.listen((state) { | 79 _primarySubscription = primary.onStateChange.listen((state) { |
| 81 if (state.isRemoved) { | 80 if (state.isRemoved) { |
| 82 remove(); | 81 remove(); |
| 83 } else { | 82 } else { |
| 84 _dirty(); | 83 _dirty(); |
| (...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 193 // If the node was removed before it could be loaded, treat it as though | 192 // If the node was removed before it could be loaded, treat it as though |
| 194 // it never existed and throw a MissingInputException. | 193 // it never existed and throw a MissingInputException. |
| 195 throw new MissingInputException(info, id); | 194 throw new MissingInputException(info, id); |
| 196 }); | 195 }); |
| 197 }); | 196 }); |
| 198 } | 197 } |
| 199 | 198 |
| 200 /// Applies the transform so that it produces concrete (as opposed to lazy) | 199 /// Applies the transform so that it produces concrete (as opposed to lazy) |
| 201 /// outputs. | 200 /// outputs. |
| 202 Future<Set<AssetNode>> _applyImmediate() { | 201 Future<Set<AssetNode>> _applyImmediate() { |
| 203 var newOutputs = new AssetSet(); | 202 var transformController = new TransformController(this); |
| 204 var transform = new Transform(this, newOutputs, _log); | 203 _onLogPool.add(transformController.onLog); |
| 205 | 204 |
| 206 return syncFuture(() => transformer.apply(transform)).then((_) { | 205 return syncFuture(() { |
| 206 return transformer.apply(transformController.transform); | |
| 207 }).whenComplete(transformController.close).then((_) { | |
| 207 if (_isDirty) return new Set(); | 208 if (_isDirty) return new Set(); |
| 208 | 209 |
| 210 var newOutputs = new AssetSet.from(transformController.outputs); | |
|
Bob Nystrom
2014/02/27 23:41:18
outputs already is an AssetSet. Is there a reason
nweiz
2014/02/28 01:19:08
It just felt kind of weird to modify another class
Bob Nystrom
2014/02/28 18:56:39
I look at it more like claiming ownership. It feel
| |
| 209 // Any ids that are for a different package are invalid. | 211 // Any ids that are for a different package are invalid. |
| 210 var invalidIds = newOutputs | 212 var invalidIds = newOutputs |
| 211 .map((asset) => asset.id) | 213 .map((asset) => asset.id) |
| 212 .where((id) => id.package != phase.cascade.package) | 214 .where((id) => id.package != phase.cascade.package) |
| 213 .toSet(); | 215 .toSet(); |
| 214 for (var id in invalidIds) { | 216 for (var id in invalidIds) { |
| 215 newOutputs.removeId(id); | 217 newOutputs.removeId(id); |
| 216 // TODO(nweiz): report this as a warning rather than a failing error. | 218 // TODO(nweiz): report this as a warning rather than a failing error. |
| 217 phase.cascade.reportError(new InvalidOutputException(info, id)); | 219 phase.cascade.reportError(new InvalidOutputException(info, id)); |
| 218 } | 220 } |
| (...skipping 17 matching lines...) Expand all Loading... | |
| 236 } | 238 } |
| 237 } | 239 } |
| 238 | 240 |
| 239 return brandNewOutputs; | 241 return brandNewOutputs; |
| 240 }); | 242 }); |
| 241 } | 243 } |
| 242 | 244 |
| 243 /// Applies the transform in declarative mode so that it produces lazy | 245 /// Applies the transform in declarative mode so that it produces lazy |
| 244 /// outputs. | 246 /// outputs. |
| 245 Future<Set<AssetNode>> _declareLazy() { | 247 Future<Set<AssetNode>> _declareLazy() { |
| 246 var newIds = new Set(); | 248 var transformController = new DeclaringTransformController(this); |
| 247 var transform = new DeclaringTransform(this, newIds, _log); | |
| 248 | 249 |
| 249 return syncFuture(() { | 250 return syncFuture(() { |
| 250 return (transformer as LazyTransformer).declareOutputs(transform); | 251 return (transformer as LazyTransformer) |
| 251 }).then((_) { | 252 .declareOutputs(transformController.transform); |
| 253 }).whenComplete(transformController.close).then((_) { | |
| 252 if (_isDirty) return new Set(); | 254 if (_isDirty) return new Set(); |
| 253 | 255 |
| 256 var newIds = new Set.from(transformController.outputIds); | |
|
Bob Nystrom
2014/02/27 23:41:18
Ditto. Why copy the set here?
| |
| 254 var invalidIds = | 257 var invalidIds = |
| 255 newIds.where((id) => id.package != phase.cascade.package).toSet(); | 258 newIds.where((id) => id.package != phase.cascade.package).toSet(); |
| 256 for (var id in invalidIds) { | 259 for (var id in invalidIds) { |
| 257 newIds.remove(id); | 260 newIds.remove(id); |
| 258 // TODO(nweiz): report this as a warning rather than a failing error. | 261 // TODO(nweiz): report this as a warning rather than a failing error. |
| 259 phase.cascade.reportError(new InvalidOutputException(info, id)); | 262 phase.cascade.reportError(new InvalidOutputException(info, id)); |
| 260 } | 263 } |
| 261 | 264 |
| 262 // Remove outputs that used to exist but don't anymore. | 265 // Remove outputs that used to exist but don't anymore. |
| 263 for (var id in _outputControllers.keys.toList()) { | 266 for (var id in _outputControllers.keys.toList()) { |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 274 var controller = new AssetNodeController.lazy(id, force, this); | 277 var controller = new AssetNodeController.lazy(id, force, this); |
| 275 _outputControllers[id] = controller; | 278 _outputControllers[id] = controller; |
| 276 brandNewOutputs.add(controller.node); | 279 brandNewOutputs.add(controller.node); |
| 277 } | 280 } |
| 278 } | 281 } |
| 279 | 282 |
| 280 return brandNewOutputs; | 283 return brandNewOutputs; |
| 281 }); | 284 }); |
| 282 } | 285 } |
| 283 | 286 |
| 284 void _log(AssetId asset, LogLevel level, String message, Span span) { | |
| 285 // If the log isn't already associated with an asset, use the primary. | |
| 286 if (asset == null) asset = primary.id; | |
| 287 var entry = new LogEntry(info, asset, level, message, span); | |
| 288 _onLogController.add(entry); | |
| 289 } | |
| 290 | |
| 291 String toString() => | 287 String toString() => |
| 292 "transform node in $_location for $transformer on $primary"; | 288 "transform node in $_location for $transformer on $primary"; |
| 293 } | 289 } |
| OLD | NEW |