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 'asset.dart'; | 9 import 'asset.dart'; |
| 10 import 'asset_id.dart'; | 10 import 'asset_id.dart'; |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 38 /// A string describing the location of [this] in the transformer graph. | 38 /// A string describing the location of [this] in the transformer graph. |
| 39 final String _location; | 39 final String _location; |
| 40 | 40 |
| 41 /// The subscription to [primary]'s [AssetNode.onStateChange] stream. | 41 /// The subscription to [primary]'s [AssetNode.onStateChange] stream. |
| 42 StreamSubscription _primarySubscription; | 42 StreamSubscription _primarySubscription; |
| 43 | 43 |
| 44 /// The subscription to [phase]'s [Phase.onAsset] stream. | 44 /// The subscription to [phase]'s [Phase.onAsset] stream. |
| 45 StreamSubscription<AssetNode> _phaseSubscription; | 45 StreamSubscription<AssetNode> _phaseSubscription; |
| 46 | 46 |
| 47 /// Whether [this] is dirty and still has more processing to do. | 47 /// Whether [this] is dirty and still has more processing to do. |
| 48 bool get isDirty => _state != _State.NOT_PRIMARY && _state != _State.APPLIED; | 48 bool get isDirty => _state != _State.NOT_PRIMARY && |
| 49 _state != _State.APPLIED && _state != _State.DECLARED; | |
| 49 | 50 |
| 50 /// Whether this transform is lazy and this transform has yet to be forced. | 51 /// Whether this transform is deferred. |
| 51 /// | 52 /// |
| 52 /// A transform being lazy is distinct from a transformer being lazy. A | 53 /// A transform is deferred if either its transformer is lazy or if its |
| 53 /// transformer that's declaring but not lazy will have lazy transforms for | 54 /// transformer is declaring and its primary input comes from a deferred |
| 54 /// primary inputs that are themselves lazy. | 55 /// transformer. |
| 55 bool _isLazy; | 56 final bool deferred; |
| 57 | |
| 58 /// Whether this is a deferred transform waiting for [force] to be called to | |
| 59 /// generate inputs. | |
| 60 /// | |
| 61 /// This defaults to `true` for deferred transforms and `false` otherwise. | |
| 62 /// During or after running `isPrimary` or `declareOutputs`, this may become | |
| 63 /// `false`, indicating that the transform has been forced and should generate | |
| 64 /// outputs as soon as possible. It will only be set back to `true` if an | |
| 65 /// input changes *after* `apply` has completed. | |
| 66 bool _awaitingForce; | |
| 56 | 67 |
| 57 /// The subscriptions to each input's [AssetNode.onStateChange] stream. | 68 /// The subscriptions to each input's [AssetNode.onStateChange] stream. |
| 58 final _inputSubscriptions = new Map<AssetId, StreamSubscription>(); | 69 final _inputSubscriptions = new Map<AssetId, StreamSubscription>(); |
| 59 | 70 |
| 60 /// The controllers for the asset nodes emitted by this node. | 71 /// The controllers for the asset nodes emitted by this node. |
| 61 final _outputControllers = new Map<AssetId, AssetNodeController>(); | 72 final _outputControllers = new Map<AssetId, AssetNodeController>(); |
| 62 | 73 |
| 63 /// The ids of inputs the transformer tried and failed to read last time it | 74 /// The ids of inputs the transformer tried and failed to read last time it |
| 64 /// ran. | 75 /// ran. |
| 65 final _missingInputs = new Set<AssetId>(); | 76 final _missingInputs = new Set<AssetId>(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 93 /// This is synchronous because error logs can cause the transform to fail, so | 104 /// This is synchronous because error logs can cause the transform to fail, so |
| 94 /// we need to ensure that their processing isn't delayed until after the | 105 /// we need to ensure that their processing isn't delayed until after the |
| 95 /// transform or build has finished. | 106 /// transform or build has finished. |
| 96 Stream<LogEntry> get onLog => _onLogPool.stream; | 107 Stream<LogEntry> get onLog => _onLogPool.stream; |
| 97 final _onLogPool = new StreamPool<LogEntry>.broadcast(); | 108 final _onLogPool = new StreamPool<LogEntry>.broadcast(); |
| 98 | 109 |
| 99 /// A controller for log entries emitted by this node. | 110 /// A controller for log entries emitted by this node. |
| 100 final _onLogController = new StreamController<LogEntry>.broadcast(sync: true); | 111 final _onLogController = new StreamController<LogEntry>.broadcast(sync: true); |
| 101 | 112 |
| 102 /// The current state of [this]. | 113 /// The current state of [this]. |
| 103 var _state = _State.COMPUTING_IS_PRIMARY; | 114 var _state = _State.DECLARING; |
| 104 | 115 |
| 105 /// Whether [this] has been marked as removed. | 116 /// Whether [this] has been marked as removed. |
| 106 bool get _isRemoved => _onAssetController.isClosed; | 117 bool get _isRemoved => _onAssetController.isClosed; |
| 107 | 118 |
| 108 /// Whether the most recent run of this transform has declared that it | 119 /// Whether the most recent run of this transform has declared that it |
| 109 /// consumes the primary input. | 120 /// consumes the primary input. |
| 110 /// | 121 /// |
| 111 /// Defaults to `false`. This is not meaningful unless [_state] is | 122 /// Defaults to `false`. This is not meaningful unless [_state] is |
| 112 /// [_State.APPLIED]. | 123 /// [_State.APPLIED] or [_State.DECLARED]. |
| 113 bool _consumePrimary = false; | 124 bool _consumePrimary = false; |
| 114 | 125 |
| 115 /// The set of output ids that [transformer] declared it would emit. | 126 /// The set of output ids that [transformer] declared it would emit. |
| 116 /// | 127 /// |
| 117 /// This is only non-null if [transformer] is a [DeclaringTransformer] and its | 128 /// This is only non-null if [transformer] is a [DeclaringTransformer] and its |
| 118 /// [declareOutputs] has been run successfully. | 129 /// [declareOutputs] has been run successfully. |
| 119 Set<AssetId> _declaredOutputs; | 130 Set<AssetId> _declaredOutputs; |
| 120 | 131 |
| 121 TransformNode(this.phase, Transformer transformer, AssetNode primary, | 132 TransformNode(this.phase, Transformer transformer, AssetNode primary, |
| 122 this._location) | 133 this._location) |
| 123 : transformer = transformer, | 134 : transformer = transformer, |
| 124 primary = primary, | 135 primary = primary, |
| 125 _isLazy = transformer is LazyTransformer || | 136 deferred = transformer is LazyTransformer || |
| 126 (transformer is DeclaringTransformer && primary.isLazy) { | 137 (transformer is DeclaringTransformer && |
| 138 primary.transform != null && | |
| 139 primary.transform.deferred) { | |
|
Bob Nystrom
2014/04/14 19:20:25
Instead of checking for a null transform here, wha
nweiz
2014/04/14 21:55:07
Done.
| |
| 140 _awaitingForce = deferred; | |
| 141 | |
| 127 _onLogPool.add(_onLogController.stream); | 142 _onLogPool.add(_onLogController.stream); |
| 128 | 143 |
| 129 if (!_isLazy) primary.force(); | 144 if (!deferred) primary.force(); |
| 130 | 145 |
| 131 _primarySubscription = primary.onStateChange.listen((state) { | 146 _primarySubscription = primary.onStateChange.listen((state) { |
| 132 if (state.isRemoved) { | 147 if (state.isRemoved) { |
| 133 remove(); | 148 remove(); |
| 134 } else { | 149 } else { |
| 150 if (state.isDirty && !deferred) primary.force(); | |
| 135 _dirty(); | 151 _dirty(); |
| 136 } | 152 } |
| 137 }); | 153 }); |
| 138 | 154 |
| 139 _phaseSubscription = phase.previous.onAsset.listen((node) { | 155 _phaseSubscription = phase.previous.onAsset.listen((node) { |
| 140 if (_missingInputs.contains(node.id)) _dirty(); | 156 if (!_missingInputs.contains(node.id)) return; |
| 157 if (!deferred) node.force(); | |
| 158 _dirty(); | |
| 141 }); | 159 }); |
| 142 | 160 |
| 143 _isPrimary(); | 161 _isPrimary(); |
| 144 } | 162 } |
| 145 | 163 |
| 146 /// The [TransformInfo] describing this node. | 164 /// The [TransformInfo] describing this node. |
| 147 /// | 165 /// |
| 148 /// [TransformInfo] is the publicly-visible representation of a transform | 166 /// [TransformInfo] is the publicly-visible representation of a transform |
| 149 /// node. | 167 /// node. |
| 150 TransformInfo get info => new TransformInfo(transformer, primary.id); | 168 TransformInfo get info => new TransformInfo(transformer, primary.id); |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 162 _primarySubscription.cancel(); | 180 _primarySubscription.cancel(); |
| 163 _phaseSubscription.cancel(); | 181 _phaseSubscription.cancel(); |
| 164 _clearInputSubscriptions(); | 182 _clearInputSubscriptions(); |
| 165 _clearOutputs(); | 183 _clearOutputs(); |
| 166 if (_passThroughController != null) { | 184 if (_passThroughController != null) { |
| 167 _passThroughController.setRemoved(); | 185 _passThroughController.setRemoved(); |
| 168 _passThroughController = null; | 186 _passThroughController = null; |
| 169 } | 187 } |
| 170 } | 188 } |
| 171 | 189 |
| 172 /// If [transformer] is lazy, ensures that its concrete outputs will be | 190 /// If [this] is deferred, ensures that its concrete outputs will be |
| 173 /// generated. | 191 /// generated. |
| 174 void force() { | 192 void force() { |
| 175 // TODO(nweiz): we might want to have a timeout after which, if the | 193 if (!_awaitingForce) return; |
| 176 // transform's outputs have gone unused, we switch it back to lazy mode. | |
| 177 if (!_isLazy) return; | |
| 178 primary.force(); | 194 primary.force(); |
| 179 _isLazy = false; | 195 _awaitingForce = false; |
| 180 _dirty(); | 196 _dirty(); |
| 181 } | 197 } |
| 182 | 198 |
| 183 /// Marks this transform as dirty. | 199 /// Marks this transform as dirty. |
| 184 /// | 200 /// |
| 185 /// This causes all of the transform's outputs to be marked as dirty as well. | 201 /// This causes all of the transform's outputs to be marked as dirty as well. |
| 186 void _dirty() { | 202 void _dirty() { |
| 187 if (_state == _State.NOT_PRIMARY) { | 203 if (_state == _State.NOT_PRIMARY) { |
| 188 _emitPassThrough(); | 204 _emitPassThrough(); |
| 189 return; | 205 return; |
| 190 } | 206 } |
| 191 if (_state == _State.COMPUTING_IS_PRIMARY || _isLazy) return; | 207 |
| 208 // If we're in the process of running [isPrimary] or [declareOutputs], we're | |
|
Bob Nystrom
2014/04/14 19:20:25
"we're" -> "we"
nweiz
2014/04/14 21:55:07
Done.
| |
| 209 // already know that [apply] needs to be run so there's nothing we need to | |
| 210 // mark as dirty. | |
| 211 if (_state == _State.DECLARING) return; | |
| 212 | |
| 213 // If we're waiting until [force] is called to run [apply], we don't to run | |
|
Bob Nystrom
2014/04/14 19:20:25
"don't to" -> "don't want to".
nweiz
2014/04/14 21:55:07
Done.
| |
| 214 // [apply] too early. | |
| 215 if (_awaitingForce) return; | |
| 216 | |
| 217 if (_state == _State.APPLIED && deferred) { | |
| 218 // Transition to DECLARED, indicating that we know what outputs [apply] | |
| 219 // will emit but we're waiting to emit them concretely until [force] is | |
| 220 // called. | |
| 221 _state = _State.DECLARED; | |
| 222 _awaitingForce = true; | |
| 223 for (var controller in _outputControllers.values) { | |
| 224 controller.setLazy(force); | |
| 225 } | |
| 226 return; | |
| 227 } | |
| 192 | 228 |
| 193 if (_passThroughController != null) _passThroughController.setDirty(); | 229 if (_passThroughController != null) _passThroughController.setDirty(); |
| 194 for (var controller in _outputControllers.values) { | 230 for (var controller in _outputControllers.values) { |
| 195 controller.setDirty(); | 231 // Don't re-mark a controller as dirty to avoid cases where we try to |
| 232 // dispatch an event while handling another event (e.g. an output is | |
| 233 // marked lazy, which causes it to be forced, which causes it to be marked | |
| 234 // dirty). | |
| 235 if (!controller.node.state.isDirty) controller.setDirty(); | |
|
Bob Nystrom
2014/04/14 19:20:25
Can this check be moved into .setDirty()?
nweiz
2014/04/14 21:55:07
Done.
| |
| 196 } | 236 } |
| 197 | 237 |
| 198 if (_state == _State.APPLIED) { | 238 if (_state == _State.APPLIED || _state == _State.DECLARED) { |
| 199 _apply(); | 239 _apply(); |
| 200 } else { | 240 } else { |
| 201 _state = _State.NEEDS_APPLY; | 241 _state = _State.NEEDS_APPLY; |
| 202 } | 242 } |
| 203 } | 243 } |
| 204 | 244 |
| 205 /// Runs [transformer.isPrimary] and adjusts [this]'s state according to the | 245 /// Runs [transformer.isPrimary] and adjusts [this]'s state according to the |
| 206 /// result. | 246 /// result. |
| 207 /// | 247 /// |
| 208 /// This will also run [_declareOutputs] and/or [_apply] as appropriate. | 248 /// This will also run [_declareOutputs] and/or [_apply] as appropriate. |
| 209 void _isPrimary() { | 249 void _isPrimary() { |
| 210 syncFuture(() => transformer.isPrimary(primary.id)) | 250 syncFuture(() => transformer.isPrimary(primary.id)) |
| 211 .catchError((error, stackTrace) { | 251 .catchError((error, stackTrace) { |
| 212 if (_isRemoved) return false; | 252 if (_isRemoved) return false; |
| 213 | 253 |
| 214 // Catch all transformer errors and pipe them to the results stream. This | 254 // Catch all transformer errors and pipe them to the results stream. This |
| 215 // is so a broken transformer doesn't take down the whole graph. | 255 // is so a broken transformer doesn't take down the whole graph. |
| 216 phase.cascade.reportError(_wrapException(error, stackTrace)); | 256 phase.cascade.reportError(_wrapException(error, stackTrace)); |
| 217 | 257 |
| 218 return false; | 258 return false; |
| 219 }).then((isPrimary) { | 259 }).then((isPrimary) { |
| 220 if (_isRemoved) return null; | 260 if (_isRemoved) return null; |
| 221 if (isPrimary) { | 261 if (isPrimary) { |
| 222 return _declareOutputs().then((_) { | 262 return _declareOutputs().then((_) { |
| 223 if (_isRemoved) return; | 263 if (_isRemoved) return; |
| 224 if (_isLazy) { | 264 if (_awaitingForce) { |
| 225 _state = _State.APPLIED; | 265 _state = _State.DECLARED; |
| 226 _onDoneController.add(null); | 266 _onDoneController.add(null); |
| 227 } else { | 267 } else { |
| 228 _apply(); | 268 _apply(); |
| 229 } | 269 } |
| 230 }); | 270 }); |
| 231 } | 271 } |
| 232 | 272 |
| 233 _emitPassThrough(); | 273 _emitPassThrough(); |
| 234 _state = _State.NOT_PRIMARY; | 274 _state = _State.NOT_PRIMARY; |
| 235 _onDoneController.add(null); | 275 _onDoneController.add(null); |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 255 .where((id) => id.package != phase.cascade.package).toSet(); | 295 .where((id) => id.package != phase.cascade.package).toSet(); |
| 256 for (var id in invalidIds) { | 296 for (var id in invalidIds) { |
| 257 _declaredOutputs.remove(id); | 297 _declaredOutputs.remove(id); |
| 258 // TODO(nweiz): report this as a warning rather than a failing error. | 298 // TODO(nweiz): report this as a warning rather than a failing error. |
| 259 phase.cascade.reportError(new InvalidOutputException(info, id)); | 299 phase.cascade.reportError(new InvalidOutputException(info, id)); |
| 260 } | 300 } |
| 261 | 301 |
| 262 if (!_declaredOutputs.contains(primary.id)) _emitPassThrough(); | 302 if (!_declaredOutputs.contains(primary.id)) _emitPassThrough(); |
| 263 | 303 |
| 264 for (var id in _declaredOutputs) { | 304 for (var id in _declaredOutputs) { |
| 265 var controller = _isLazy | 305 var controller = _awaitingForce |
| 266 ? new AssetNodeController.lazy(id, force, this) | 306 ? new AssetNodeController.lazy(id, force, this) |
| 267 : new AssetNodeController(id, this); | 307 : new AssetNodeController(id, this); |
| 268 _outputControllers[id] = controller; | 308 _outputControllers[id] = controller; |
| 269 _onAssetController.add(controller.node); | 309 _onAssetController.add(controller.node); |
| 270 } | 310 } |
| 271 }).catchError((error, stackTrace) { | 311 }).catchError((error, stackTrace) { |
| 272 if (_isRemoved) return; | 312 if (_isRemoved) return; |
| 273 phase.cascade.reportError(_wrapException(error, stackTrace)); | 313 phase.cascade.reportError(_wrapException(error, stackTrace)); |
| 274 }); | 314 }); |
| 275 } | 315 } |
| 276 | 316 |
| 277 /// Applies this transform. | 317 /// Applies this transform. |
| 278 void _apply() { | 318 void _apply() { |
| 279 assert(!_isRemoved && !_isLazy); | 319 assert(!_isRemoved && !_awaitingForce); |
| 280 | 320 |
| 281 // Clear input subscriptions here as well as in [_process] because [_apply] | 321 // Clear input subscriptions here as well as in [_process] because [_apply] |
| 282 // may be restarted independently if only a secondary input changes. | 322 // may be restarted independently if only a secondary input changes. |
| 283 _clearInputSubscriptions(); | 323 _clearInputSubscriptions(); |
| 284 _state = _State.APPLYING; | 324 _state = _State.APPLYING; |
| 285 _runApply().then((hadError) { | 325 _runApply().then((hadError) { |
| 286 if (_isRemoved) return; | 326 if (_isRemoved) return; |
| 287 | 327 |
| 288 if (_state == _State.NEEDS_APPLY) { | 328 if (_state == _State.NEEDS_APPLY) { |
| 289 _apply(); | 329 _apply(); |
| (...skipping 27 matching lines...) Expand all Loading... | |
| 317 return phase.previous.getOutput(id).then((node) { | 357 return phase.previous.getOutput(id).then((node) { |
| 318 // Throw if the input isn't found. This ensures the transformer's apply | 358 // Throw if the input isn't found. This ensures the transformer's apply |
| 319 // is exited. We'll then catch this and report it through the proper | 359 // is exited. We'll then catch this and report it through the proper |
| 320 // results stream. | 360 // results stream. |
| 321 if (node == null) { | 361 if (node == null) { |
| 322 _missingInputs.add(id); | 362 _missingInputs.add(id); |
| 323 throw new AssetNotFoundException(id); | 363 throw new AssetNotFoundException(id); |
| 324 } | 364 } |
| 325 | 365 |
| 326 _inputSubscriptions.putIfAbsent(node.id, () { | 366 _inputSubscriptions.putIfAbsent(node.id, () { |
| 327 return node.onStateChange.listen((_) => _dirty()); | 367 return node.onStateChange.listen((state) => _dirty()); |
| 328 }); | 368 }); |
| 329 | 369 |
| 330 return node.asset; | 370 return node.asset; |
| 331 }); | 371 }); |
| 332 } | 372 } |
| 333 | 373 |
| 334 /// Run [Transformer.apply] as soon as [primary] is available. | 374 /// Run [Transformer.apply] as soon as [primary] is available. |
| 335 /// | 375 /// |
| 336 /// Returns whether or not an error occurred while running the transformer. | 376 /// Returns whether or not an error occurred while running the transformer. |
| 337 Future<bool> _runApply() { | 377 Future<bool> _runApply() { |
| (...skipping 130 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 468 _onLogController.add( | 508 _onLogController.add( |
| 469 new LogEntry(info, primary.id, LogLevel.WARNING, message, null)); | 509 new LogEntry(info, primary.id, LogLevel.WARNING, message, null)); |
| 470 } | 510 } |
| 471 | 511 |
| 472 String toString() => | 512 String toString() => |
| 473 "transform node in $_location for $transformer on $primary"; | 513 "transform node in $_location for $transformer on $primary"; |
| 474 } | 514 } |
| 475 | 515 |
| 476 /// The enum of states that [TransformNode] can be in. | 516 /// The enum of states that [TransformNode] can be in. |
| 477 class _State { | 517 class _State { |
| 478 /// The transform is running [Transformer.isPrimary]. | 518 /// The transform is running [Transformer.isPrimary] followed by |
| 519 /// [DeclaringTransformer.declareOutputs] (for a [DeclaringTransformer]). | |
| 479 /// | 520 /// |
| 480 /// This is the initial state of the transformer. Once [Transformer.isPrimary] | 521 /// This is the initial state of the transformer, and it will only occur once |
| 481 /// finishes running, this will transition to [APPLYING] if the input is | 522 /// since [Transformer.isPrimary] and [DeclaringTransformer.declareOutputs] |
| 482 /// primary, or [NOT_PRIMARY] if it's not. | 523 /// are independent of the contents of the primary input. Once the two methods |
| 483 static final COMPUTING_IS_PRIMARY = const _State._("computing isPrimary"); | 524 /// finish running, this will transition to [NOT_PRIMARY] if the input isn't |
| 525 /// primary, [DECLARED] if the transform is deferred, and [APPLYING] otherwise . | |
|
Bob Nystrom
2014/04/14 19:20:25
Long line.
nweiz
2014/04/14 21:55:07
Done.
| |
| 526 static final DECLARING = const _State._("computing isPrimary"); | |
| 527 | |
| 528 /// The transform is deferred and has run [DeclaringTransformer.declareOutputs ] | |
| 529 /// but hasn't yet been forced. | |
| 530 /// | |
| 531 /// This will transition to [APPLYING] when one of the outputs has been | |
| 532 /// forced. | |
| 533 static final DECLARED = const _State._("declared"); | |
| 484 | 534 |
| 485 /// The transform is running [Transformer.apply]. | 535 /// The transform is running [Transformer.apply]. |
| 486 /// | 536 /// |
| 487 /// If an input changes while in this state, it will transition to | 537 /// If an input changes while in this state, it will transition to |
| 488 /// [NEEDS_APPLY]. If the [TransformNode] is still in this state when | 538 /// [NEEDS_APPLY]. If the [TransformNode] is still in this state when |
| 489 /// [Transformer.apply] finishes running, it will transition to [APPLIED]. | 539 /// [Transformer.apply] finishes running, it will transition to [APPLIED]. |
| 490 static final APPLYING = const _State._("applying"); | 540 static final APPLYING = const _State._("applying"); |
| 491 | 541 |
| 492 /// The transform is running [Transformer.apply], but an input changed after | 542 /// The transform is running [Transformer.apply], but an input changed after |
| 493 /// it started, so it will need to re-run [Transformer.apply]. | 543 /// it started, so it will need to re-run [Transformer.apply]. |
| 494 /// | 544 /// |
| 495 /// This will transition to [APPLYING] once [Transformer.apply] finishes | 545 /// This will transition to [APPLYING] once [Transformer.apply] finishes |
| 496 /// running. | 546 /// running. |
| 497 static final NEEDS_APPLY = const _State._("needs apply"); | 547 static final NEEDS_APPLY = const _State._("needs apply"); |
| 498 | 548 |
| 499 /// The transform has finished running [Transformer.apply], whether or not it | 549 /// The transform has finished running [Transformer.apply], whether or not it |
| 500 /// emitted an error. | 550 /// emitted an error. |
| 501 /// | 551 /// |
| 502 /// If the transformer is lazy, the [TransformNode] can also be in this state | 552 /// If the transformer is deferred, the [TransformNode] can also be in this |
| 503 /// when [Transformer.declareOutputs] has been run but [Transformer.apply] has | 553 /// state when [Transformer.declareOutputs] has been run but |
| 504 /// not. | 554 /// [Transformer.apply] has not. |
| 505 /// | 555 /// |
| 506 /// If an input changes, this will transition to [APPLYING]. | 556 /// If an input changes, this will transition to [DECLARED] if the transform |
| 557 /// is deferred and [APPLYING] otherwise. | |
| 507 static final APPLIED = const _State._("applied"); | 558 static final APPLIED = const _State._("applied"); |
| 508 | 559 |
| 509 /// The transform has finished running [Transformer.isPrimary], which returned | 560 /// The transform has finished running [Transformer.isPrimary], which returned |
| 510 /// `false`. | 561 /// `false`. |
| 511 /// | 562 /// |
| 512 /// This will never transition to another state. | 563 /// This will never transition to another state. |
| 513 static final NOT_PRIMARY = const _State._("not primary"); | 564 static final NOT_PRIMARY = const _State._("not primary"); |
| 514 | 565 |
| 515 final String name; | 566 final String name; |
| 516 | 567 |
| 517 const _State._(this.name); | 568 const _State._(this.name); |
| 518 | 569 |
| 519 String toString() => name; | 570 String toString() => name; |
| 520 } | 571 } |
| OLD | NEW |