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

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

Issue 255483002: Expand barback's notion of dirtiness to understand declaredness. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: code review Created 6 years, 7 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.transform_node; 5 library barback.transform_node;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 8
9 import 'asset.dart'; 9 import 'asset.dart';
10 import 'asset_id.dart'; 10 import 'asset_id.dart';
11 import 'asset_node.dart'; 11 import 'asset_node.dart';
12 import 'declaring_transform.dart'; 12 import 'declaring_transform.dart';
13 import 'declaring_transformer.dart'; 13 import 'declaring_transformer.dart';
14 import 'errors.dart'; 14 import 'errors.dart';
15 import 'lazy_transformer.dart'; 15 import 'lazy_transformer.dart';
16 import 'log.dart'; 16 import 'log.dart';
17 import 'node_status.dart';
17 import 'node_streams.dart'; 18 import 'node_streams.dart';
18 import 'phase.dart'; 19 import 'phase.dart';
19 import 'transform.dart'; 20 import 'transform.dart';
20 import 'transformer.dart'; 21 import 'transformer.dart';
21 import 'utils.dart'; 22 import 'utils.dart';
22 23
23 /// Describes a transform on a set of assets and its relationship to the build 24 /// Describes a transform on a set of assets and its relationship to the build
24 /// dependency graph. 25 /// dependency graph.
25 /// 26 ///
26 /// Keeps track of whether it's dirty and needs to be run and which assets it 27 /// Keeps track of whether it's dirty and needs to be run and which assets it
(...skipping 10 matching lines...) Expand all
37 38
38 /// A string describing the location of [this] in the transformer graph. 39 /// A string describing the location of [this] in the transformer graph.
39 final String _location; 40 final String _location;
40 41
41 /// The subscription to [primary]'s [AssetNode.onStateChange] stream. 42 /// The subscription to [primary]'s [AssetNode.onStateChange] stream.
42 StreamSubscription _primarySubscription; 43 StreamSubscription _primarySubscription;
43 44
44 /// The subscription to [phase]'s [Phase.onAsset] stream. 45 /// The subscription to [phase]'s [Phase.onAsset] stream.
45 StreamSubscription<AssetNode> _phaseSubscription; 46 StreamSubscription<AssetNode> _phaseSubscription;
46 47
47 /// Whether [this] is dirty and still has more processing to do. 48 /// How far along [this] is in processing its assets.
48 bool get isDirty => _state != _State.NOT_PRIMARY && 49 NodeStatus get status {
49 _state != _State.APPLIED && _state != _State.DECLARED; 50 if (_state == _State.NOT_PRIMARY || _state == _State.APPLIED ||
51 _state == _State.DECLARED) {
52 return NodeStatus.IDLE;
53 }
54
55 if (transformer is DeclaringTransformer && _state != _State.DECLARING) {
56 return NodeStatus.MATERIALIZING;
57 } else {
58 return NodeStatus.RUNNING;
59 }
60 }
50 61
51 /// Whether this transform is deferred. 62 /// Whether this transform is deferred.
52 /// 63 ///
53 /// A transform is deferred if either its transformer is lazy or if its 64 /// A transform is deferred if either its transformer is lazy or if its
54 /// transformer is declaring and its primary input comes from a deferred 65 /// transformer is declaring and its primary input comes from a deferred
55 /// transformer. 66 /// transformer.
56 final bool deferred; 67 final bool deferred;
57 68
58 /// Whether this transform has been forced since it last finished applying. 69 /// Whether this transform has been forced since it last finished applying.
59 /// 70 ///
(...skipping 16 matching lines...) Expand all
76 /// consumed or overwritten. 87 /// consumed or overwritten.
77 /// 88 ///
78 /// This needs an intervening controller to ensure that the output can be 89 /// This needs an intervening controller to ensure that the output can be
79 /// marked dirty when determining whether [this] will consume or overwrite it, 90 /// marked dirty when determining whether [this] will consume or overwrite it,
80 /// and be marked removed if it does. [_passThroughController] will be null 91 /// and be marked removed if it does. [_passThroughController] will be null
81 /// if the asset is not being passed through. 92 /// if the asset is not being passed through.
82 AssetNodeController _passThroughController; 93 AssetNodeController _passThroughController;
83 94
84 /// The asset node for this transform. 95 /// The asset node for this transform.
85 final _streams = new NodeStreams(); 96 final _streams = new NodeStreams();
86 Stream get onDone => _streams.onDone; 97 Stream<NodeStatus> get onStatusChange => _streams.onStatusChange;
87 Stream<AssetNode> get onAsset => _streams.onAsset; 98 Stream<AssetNode> get onAsset => _streams.onAsset;
88 Stream<LogEntry> get onLog => _streams.onLog; 99 Stream<LogEntry> get onLog => _streams.onLog;
89 100
90 /// The current state of [this]. 101 /// The current state of [this].
91 var _state = _State.DECLARING; 102 var _state = _State.DECLARING;
92 103
93 /// Whether [this] has been marked as removed. 104 /// Whether [this] has been marked as removed.
94 bool get _isRemoved => _streams.onAssetController.isClosed; 105 bool get _isRemoved => _streams.onAssetController.isClosed;
95 106
96 /// Whether the most recent run of this transform has declared that it 107 /// Whether the most recent run of this transform has declared that it
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
184 195
185 // If [transformer] is declaring but not lazy and [primary] is available, we 196 // If [transformer] is declaring but not lazy and [primary] is available, we
186 // do want to start running [apply] even if [force] hasn't been called, 197 // do want to start running [apply] even if [force] hasn't been called,
187 // since [transformer] should run eagerly if possible. 198 // since [transformer] should run eagerly if possible.
188 var canRunDeclaringEagerly = 199 var canRunDeclaringEagerly =
189 transformer is! LazyTransformer && primary.state.isAvailable; 200 transformer is! LazyTransformer && primary.state.isAvailable;
190 if (!_forced && !canRunDeclaringEagerly) { 201 if (!_forced && !canRunDeclaringEagerly) {
191 // [forced] should only ever be false for a deferred transform. 202 // [forced] should only ever be false for a deferred transform.
192 assert(deferred); 203 assert(deferred);
193 204
194 // If we've finished applying, transition to DECLARED, indicating that we 205 // If we've finished applying, transition to MATERIALIZING, indicating
195 // know what outputs [apply] will emit but we're waiting to emit them 206 // that we know what outputs [apply] will emit but we're waiting to emit
196 // concretely until [force] is called. If we're still applying, we'll 207 // them concretely until [force] is called. If we're still applying, we'll
197 // transition to DECLARED once we finish. 208 // transition to MATERIALIZING once we finish.
198 if (_state == _State.APPLIED) _state = _State.DECLARED; 209 if (_state == _State.APPLIED) _state = _State.DECLARED;
199 for (var controller in _outputControllers.values) { 210 for (var controller in _outputControllers.values) {
200 controller.setLazy(force); 211 controller.setLazy(force);
201 } 212 }
213 _emitDeclaredOutputs();
202 return; 214 return;
203 } 215 }
204 216
205 if (_passThroughController != null) _passThroughController.setDirty(); 217 if (_passThroughController != null) _passThroughController.setDirty();
206 for (var controller in _outputControllers.values) { 218 for (var controller in _outputControllers.values) {
207 controller.setDirty(); 219 controller.setDirty();
208 } 220 }
209 221
210 if (_state == _State.APPLIED || _state == _State.DECLARED) { 222 if (_state == _State.APPLIED) {
223 if (_declaredOutputs != null) _emitDeclaredOutputs();
224 _apply();
225 } else if (_state == _State.DECLARED) {
211 _apply(); 226 _apply();
212 } else { 227 } else {
213 _state = _State.NEEDS_APPLY; 228 _state = _State.NEEDS_APPLY;
214 } 229 }
215 } 230 }
216 231
217 /// Runs [transformer.isPrimary] and adjusts [this]'s state according to the 232 /// Runs [transformer.isPrimary] and adjusts [this]'s state according to the
218 /// result. 233 /// result.
219 /// 234 ///
220 /// This will also run [_declareOutputs] and/or [_apply] as appropriate. 235 /// This will also run [_declareOutputs] and/or [_apply] as appropriate.
(...skipping 10 matching lines...) Expand all
231 }).then((isPrimary) { 246 }).then((isPrimary) {
232 if (_isRemoved) return null; 247 if (_isRemoved) return null;
233 if (isPrimary) { 248 if (isPrimary) {
234 if (!deferred) primary.force(); 249 if (!deferred) primary.force();
235 return _declareOutputs().then((_) { 250 return _declareOutputs().then((_) {
236 if (_isRemoved) return; 251 if (_isRemoved) return;
237 if (_forced) { 252 if (_forced) {
238 _apply(); 253 _apply();
239 } else { 254 } else {
240 _state = _State.DECLARED; 255 _state = _State.DECLARED;
241 _streams.onDoneController.add(null); 256 _streams.changeStatus(NodeStatus.IDLE);
242 } 257 }
243 }); 258 });
244 } 259 }
245 260
246 _emitPassThrough(); 261 _emitPassThrough();
247 _state = _State.NOT_PRIMARY; 262 _state = _State.NOT_PRIMARY;
248 _streams.onDoneController.add(null); 263 _streams.changeStatus(NodeStatus.IDLE);
249 }); 264 });
250 } 265 }
251 266
252 /// Runs [transform.declareOutputs] and emits the resulting assets as dirty 267 /// Runs [transform.declareOutputs] and emits the resulting assets as dirty
253 /// assets. 268 /// assets.
254 Future _declareOutputs() { 269 Future _declareOutputs() {
255 if (transformer is! DeclaringTransformer) return new Future.value(); 270 if (transformer is! DeclaringTransformer) return new Future.value();
256 271
257 var controller = new DeclaringTransformController(this); 272 var controller = new DeclaringTransformController(this);
258 return syncFuture(() { 273 return syncFuture(() {
259 return (transformer as DeclaringTransformer) 274 return (transformer as DeclaringTransformer)
260 .declareOutputs(controller.transform); 275 .declareOutputs(controller.transform);
261 }).then((_) { 276 }).then((_) {
262 if (_isRemoved) return; 277 if (_isRemoved) return;
263 if (controller.loggedError) return; 278 if (controller.loggedError) return;
264 279
265 _consumePrimary = controller.consumePrimary; 280 _consumePrimary = controller.consumePrimary;
266 _declaredOutputs = controller.outputIds; 281 _declaredOutputs = controller.outputIds;
267 var invalidIds = _declaredOutputs 282 var invalidIds = _declaredOutputs
268 .where((id) => id.package != phase.cascade.package).toSet(); 283 .where((id) => id.package != phase.cascade.package).toSet();
269 for (var id in invalidIds) { 284 for (var id in invalidIds) {
270 _declaredOutputs.remove(id); 285 _declaredOutputs.remove(id);
271 // TODO(nweiz): report this as a warning rather than a failing error. 286 // TODO(nweiz): report this as a warning rather than a failing error.
272 phase.cascade.reportError(new InvalidOutputException(info, id)); 287 phase.cascade.reportError(new InvalidOutputException(info, id));
273 } 288 }
274 289
275 if (!_declaredOutputs.contains(primary.id)) _emitPassThrough(); 290 if (!_declaredOutputs.contains(primary.id)) _emitPassThrough();
276 291 _emitDeclaredOutputs();
277 for (var id in _declaredOutputs) {
278 var controller = _forced
279 ? new AssetNodeController(id, this)
280 : new AssetNodeController.lazy(id, force, this);
281 _outputControllers[id] = controller;
282 _streams.onAssetController.add(controller.node);
283 }
284 }).catchError((error, stackTrace) { 292 }).catchError((error, stackTrace) {
285 if (_isRemoved) return; 293 if (_isRemoved) return;
286 phase.cascade.reportError(_wrapException(error, stackTrace)); 294 phase.cascade.reportError(_wrapException(error, stackTrace));
287 }); 295 });
288 } 296 }
289 297
298 /// Emits a dirty asset node for all outputs that were declared by the
299 /// transformer.
300 ///
301 /// This won't emit any outputs for which there already exist output
302 /// controllers. It should only be called for transforms that have declared
303 /// their outputs.
304 void _emitDeclaredOutputs() {
305 assert(_declaredOutputs != null);
306 for (var id in _declaredOutputs) {
307 if (_outputControllers.containsKey(id)) continue;
308 var controller = _forced
309 ? new AssetNodeController(id, this)
310 : new AssetNodeController.lazy(id, force, this);
311 _outputControllers[id] = controller;
312 _streams.onAssetController.add(controller.node);
313 }
314 }
315
290 /// Applies this transform. 316 /// Applies this transform.
291 void _apply() { 317 void _apply() {
292 assert(!_isRemoved); 318 assert(!_isRemoved);
293 319
294 // Clear input subscriptions here as well as in [_process] because [_apply] 320 // Clear input subscriptions here as well as in [_process] because [_apply]
295 // may be restarted independently if only a secondary input changes. 321 // may be restarted independently if only a secondary input changes.
296 _clearInputSubscriptions(); 322 _clearInputSubscriptions();
297 _state = _State.APPLYING; 323 _state = _State.APPLYING;
324 _streams.changeStatus(status);
298 _runApply().then((hadError) { 325 _runApply().then((hadError) {
299 if (_isRemoved) return; 326 if (_isRemoved) return;
300 327
301 if (_state == _State.DECLARED) return; 328 if (_state == _State.DECLARED) return;
302 329
303 if (_state == _State.NEEDS_APPLY) { 330 if (_state == _State.NEEDS_APPLY) {
304 _apply(); 331 _apply();
305 return; 332 return;
306 } 333 }
307 334
308 if (deferred) _forced = false; 335 if (deferred) _forced = false;
309 336
310 assert(_state == _State.APPLYING); 337 assert(_state == _State.APPLYING);
311 if (hadError) { 338 if (hadError) {
312 _clearOutputs(); 339 _clearOutputs();
313 // If the transformer threw an error, we don't want to emit the 340 // If the transformer threw an error, we don't want to emit the
314 // pass-through asset in case it will be overwritten by the transformer. 341 // pass-through asset in case it will be overwritten by the transformer.
315 // However, if the transformer declared that it wouldn't overwrite or 342 // However, if the transformer declared that it wouldn't overwrite or
316 // consume the pass-through asset, we can safely emit it. 343 // consume the pass-through asset, we can safely emit it.
317 if (_declaredOutputs != null && !_consumePrimary && 344 if (_declaredOutputs != null && !_consumePrimary &&
318 !_declaredOutputs.contains(primary.id)) { 345 !_declaredOutputs.contains(primary.id)) {
319 _emitPassThrough(); 346 _emitPassThrough();
320 } else { 347 } else {
321 _dontEmitPassThrough(); 348 _dontEmitPassThrough();
322 } 349 }
323 } 350 }
324 351
325 _state = _State.APPLIED; 352 _state = _State.APPLIED;
326 _streams.onDoneController.add(null); 353 _streams.changeStatus(NodeStatus.IDLE);
327 }); 354 });
328 } 355 }
329 356
330 /// Gets the asset for an input [id]. 357 /// Gets the asset for an input [id].
331 /// 358 ///
332 /// If an input with [id] cannot be found, throws an [AssetNotFoundException]. 359 /// If an input with [id] cannot be found, throws an [AssetNotFoundException].
333 Future<Asset> getInput(AssetId id) { 360 Future<Asset> getInput(AssetId id) {
334 return phase.previous.getOutput(id).then((node) { 361 return phase.previous.getOutput(id).then((node) {
335 // Throw if the input isn't found. This ensures the transformer's apply 362 // Throw if the input isn't found. This ensures the transformer's apply
336 // is exited. We'll then catch this and report it through the proper 363 // is exited. We'll then catch this and report it through the proper
(...skipping 18 matching lines...) Expand all
355 var transformController = new TransformController(this); 382 var transformController = new TransformController(this);
356 _streams.onLogPool.add(transformController.onLog); 383 _streams.onLogPool.add(transformController.onLog);
357 384
358 return primary.whenAvailable((_) { 385 return primary.whenAvailable((_) {
359 if (_isRemoved) return null; 386 if (_isRemoved) return null;
360 _state = _State.APPLYING; 387 _state = _State.APPLYING;
361 return syncFuture(() => transformer.apply(transformController.transform)); 388 return syncFuture(() => transformer.apply(transformController.transform));
362 }).then((_) { 389 }).then((_) {
363 if (deferred && !_forced && !primary.state.isAvailable) { 390 if (deferred && !_forced && !primary.state.isAvailable) {
364 _state = _State.DECLARED; 391 _state = _State.DECLARED;
365 _streams.onDoneController.add(null); 392 _streams.changeStatus(NodeStatus.IDLE);
366 return false; 393 return false;
367 } 394 }
368 395
369 if (_isRemoved) return false; 396 if (_isRemoved) return false;
370 if (_state == _State.NEEDS_APPLY) return false; 397 if (_state == _State.NEEDS_APPLY) return false;
371 if (_state == _State.DECLARING) return false; 398 if (_state == _State.DECLARING) return false;
372 if (transformController.loggedError) return true; 399 if (transformController.loggedError) return true;
373 _handleApplyResults(transformController); 400 _handleApplyResults(transformController);
374 return false; 401 return false;
375 }).catchError((error, stackTrace) { 402 }).catchError((error, stackTrace) {
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after
538 /// 565 ///
539 /// This will never transition to another state. 566 /// This will never transition to another state.
540 static final NOT_PRIMARY = const _State._("not primary"); 567 static final NOT_PRIMARY = const _State._("not primary");
541 568
542 final String name; 569 final String name;
543 570
544 const _State._(this.name); 571 const _State._(this.name);
545 572
546 String toString() => name; 573 String toString() => name;
547 } 574 }
OLDNEW
« no previous file with comments | « pkg/barback/lib/src/phase_input.dart ('k') | pkg/barback/test/package_graph/declaring_transformer_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698