Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, 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 code_transformer.src.resolver_impl; | 5 library code_transformer.src.resolver_impl; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'package:analyzer/analyzer.dart' show parseCompilationUnit; | 8 import 'package:analyzer/analyzer.dart' show parseCompilationUnit; |
| 9 import 'package:analyzer/src/generated/ast.dart'; | 9 import 'package:analyzer/src/generated/ast.dart'; |
| 10 import 'package:analyzer/src/generated/element.dart'; | 10 import 'package:analyzer/src/generated/element.dart'; |
| (...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 73 | 73 |
| 74 LibraryElement getLibrary(AssetId assetId) { | 74 LibraryElement getLibrary(AssetId assetId) { |
| 75 var source = sources[assetId]; | 75 var source = sources[assetId]; |
| 76 return source == null ? null : _context.computeLibraryElement(source); | 76 return source == null ? null : _context.computeLibraryElement(source); |
| 77 } | 77 } |
| 78 | 78 |
| 79 Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { | 79 Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { |
| 80 // Can only have one resolve in progress at a time, so chain the current | 80 // Can only have one resolve in progress at a time, so chain the current |
| 81 // resolution to be after the last one. | 81 // resolution to be after the last one. |
| 82 var phaseComplete = new Completer(); | 82 var phaseComplete = new Completer(); |
| 83 var future = _lastPhaseComplete.then((_) { | 83 var future = _lastPhaseComplete.whenComplete(() { |
| 84 _currentPhaseComplete = phaseComplete; | 84 _currentPhaseComplete = phaseComplete; |
| 85 return _performResolve(transform, | 85 return _performResolve(transform, |
| 86 entryPoints == null ? [transform.primaryInput.id] : entryPoints); | 86 entryPoints == null ? [transform.primaryInput.id] : entryPoints); |
| 87 }).then((_) => this); | 87 }).then((_) => this); |
| 88 // Advance the lastPhaseComplete to be done when this phase is all done. | 88 // Advance the lastPhaseComplete to be done when this phase is all done. |
| 89 _lastPhaseComplete = phaseComplete.future; | 89 _lastPhaseComplete = phaseComplete.future; |
| 90 return future; | 90 return future; |
| 91 } | 91 } |
| 92 | 92 |
| 93 void release() { | 93 void release() { |
| (...skipping 28 matching lines...) Expand all Loading... | |
| 122 var source = sources[assetId]; | 122 var source = sources[assetId]; |
| 123 if (source == null) { | 123 if (source == null) { |
| 124 source = new _AssetBasedSource(assetId, this); | 124 source = new _AssetBasedSource(assetId, this); |
| 125 sources[assetId] = source; | 125 sources[assetId] = source; |
| 126 } | 126 } |
| 127 source.updateDependencies(contents); | 127 source.updateDependencies(contents); |
| 128 toUpdate.add(new _PendingUpdate(source, contents)); | 128 toUpdate.add(new _PendingUpdate(source, contents)); |
| 129 source.dependentAssets.where((id) => !visited.contains(id)) | 129 source.dependentAssets.where((id) => !visited.contains(id)) |
| 130 .forEach(processAsset); | 130 .forEach(processAsset); |
| 131 }, onError: (e) { | 131 }, onError: (e) { |
| 132 _context.applyChanges(new ChangeSet()..removedSource(sources[assetId])); | 132 var source = sources[assetId]; |
| 133 sources.remove(assetId); | 133 if (source != null && source.exists()) { |
| 134 _context.applyChanges( | |
| 135 new ChangeSet()..removedSource(source)); | |
| 136 sources[assetId].updateContents(null); | |
| 137 } | |
| 134 })); | 138 })); |
| 135 } | 139 } |
| 136 entryPoints.forEach(processAsset); | 140 entryPoints.forEach(processAsset); |
| 137 | 141 |
| 138 // Once we have all asset sources updated with the new contents then | 142 // Once we have all asset sources updated with the new contents then |
| 139 // resolve everything. | 143 // resolve everything. |
| 140 return visiting.future.then((_) { | 144 return visiting.future.then((_) { |
| 141 var changeSet = new ChangeSet(); | 145 var changeSet = new ChangeSet(); |
| 142 toUpdate.forEach((pending) => pending.apply(changeSet)); | 146 toUpdate.forEach((pending) => pending.apply(changeSet)); |
| 143 var unreachableAssets = new Set.from(sources.keys).difference(visited); | 147 var unreachableAssets = sources.keys.toSet() |
| 148 .difference(visited) | |
| 149 .map((id) => sources[id]); | |
| 144 for (var unreachable in unreachableAssets) { | 150 for (var unreachable in unreachableAssets) { |
| 145 changeSet.removedSource(sources[unreachable]); | 151 changeSet.removedSource(unreachable); |
| 146 sources.remove(unreachable); | 152 unreachable.updateContents(null); |
| 153 sources.remove(unreachable.assetId); | |
| 147 } | 154 } |
| 148 | 155 |
| 149 // Update the analyzer context with the latest sources | 156 // Update the analyzer context with the latest sources |
| 150 _context.applyChanges(changeSet); | 157 _context.applyChanges(changeSet); |
| 151 // Force resolve each entry point (the getter will ensure the library is | 158 // Force resolve each entry point (the getter will ensure the library is |
| 152 // computed first). | 159 // computed first). |
| 153 _entryLibraries = entryPoints | 160 _entryLibraries = entryPoints |
| 154 .map((id) => _context.computeLibraryElement(sources[id])).toList(); | 161 .map((id) => _context.computeLibraryElement(sources[id])).toList(); |
| 155 }); | 162 }); |
| 156 } | 163 } |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 316 /// Returns true if the contents of this asset have changed. | 323 /// Returns true if the contents of this asset have changed. |
| 317 bool updateContents(String contents) { | 324 bool updateContents(String contents) { |
| 318 if (contents == _contents) return false; | 325 if (contents == _contents) return false; |
| 319 _contents = contents; | 326 _contents = contents; |
| 320 ++_revision; | 327 ++_revision; |
| 321 return true; | 328 return true; |
| 322 } | 329 } |
| 323 | 330 |
| 324 /// Contents of the file. | 331 /// Contents of the file. |
| 325 TimestampedData<String> get contents => | 332 TimestampedData<String> get contents => |
| 326 new TimestampedData<String>(modificationStamp, _contents); | 333 new TimestampedData<String>(modificationStamp, _contents); |
|
Brian Wilkerson
2014/03/28 18:20:52
This method should throw an exception if _contents
blois
2014/03/28 18:29:04
Done.
| |
| 327 | 334 |
| 328 /// Contents of the file. | 335 /// Contents of the file. |
| 329 String get rawContents => _contents; | 336 String get rawContents => _contents; |
| 330 | 337 |
| 331 /// Logger for the current transform. | 338 /// Logger for the current transform. |
| 332 /// | 339 /// |
| 333 /// Only valid while the resolver is updating assets. | 340 /// Only valid while the resolver is updating assets. |
| 334 TransformLogger get _logger => _resolver._currentTransform.logger; | 341 TransformLogger get _logger => _resolver._currentTransform.logger; |
| 335 | 342 |
| 336 /// Gets all imports/parts/exports which resolve to assets (non-Dart files). | 343 /// Gets all imports/parts/exports which resolve to assets (non-Dart files). |
| 337 Iterable<AssetId> get dependentAssets => _dependentAssets; | 344 Iterable<AssetId> get dependentAssets => _dependentAssets; |
| 338 | 345 |
| 339 bool exists() => true; | 346 bool exists() => _contents != null; |
| 340 | 347 |
| 341 bool operator ==(Object other) => | 348 bool operator ==(Object other) => |
| 342 other is _AssetBasedSource && assetId == other.assetId; | 349 other is _AssetBasedSource && assetId == other.assetId; |
| 343 | 350 |
| 344 int get hashCode => assetId.hashCode; | 351 int get hashCode => assetId.hashCode; |
| 345 | 352 |
| 346 void getContentsToReceiver(Source_ContentReceiver receiver) { | 353 void getContentsToReceiver(Source_ContentReceiver receiver) { |
| 347 receiver.accept(rawContents, modificationStamp); | 354 receiver.accept(rawContents, modificationStamp); |
| 348 } | 355 } |
| 349 | 356 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 402 } | 409 } |
| 403 } | 410 } |
| 404 | 411 |
| 405 /// Implementation of Analyzer's UriResolver for Barback based assets. | 412 /// Implementation of Analyzer's UriResolver for Barback based assets. |
| 406 class _AssetUriResolver implements UriResolver { | 413 class _AssetUriResolver implements UriResolver { |
| 407 final ResolverImpl _resolver; | 414 final ResolverImpl _resolver; |
| 408 _AssetUriResolver(this._resolver); | 415 _AssetUriResolver(this._resolver); |
| 409 | 416 |
| 410 Source resolveAbsolute(Uri uri) { | 417 Source resolveAbsolute(Uri uri) { |
| 411 var assetId = _resolve(null, uri.toString(), logger, null); | 418 var assetId = _resolve(null, uri.toString(), logger, null); |
| 419 if (assetId == null) { | |
| 420 logger.error('Unable to resolve asset ID for "$uri"'); | |
| 421 return null; | |
| 422 } | |
| 412 var source = _resolver.sources[assetId]; | 423 var source = _resolver.sources[assetId]; |
| 413 /// All resolved assets should be available by this point. | 424 // Analyzer expects that sources which are referenced but do not exist yet |
| 425 // still exist, so just make an empty source. | |
| 414 if (source == null) { | 426 if (source == null) { |
| 415 logger.error('Unable to find asset for "$uri"'); | 427 source = new _AssetBasedSource(assetId, _resolver); |
| 428 _resolver.sources[assetId] = source; | |
| 416 } | 429 } |
| 417 return source; | 430 return source; |
| 418 } | 431 } |
| 419 | 432 |
| 420 Source fromEncoding(UriKind kind, Uri uri) => | 433 Source fromEncoding(UriKind kind, Uri uri) => |
| 421 throw new UnsupportedError('fromEncoding is not supported'); | 434 throw new UnsupportedError('fromEncoding is not supported'); |
| 422 | 435 |
| 423 Uri restoreAbsolute(Source source) => | 436 Uri restoreAbsolute(Source source) => |
| 424 throw new UnsupportedError('restoreAbsolute is not supported'); | 437 throw new UnsupportedError('restoreAbsolute is not supported'); |
| 425 | 438 |
| (...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 571 _completer.complete(results); | 584 _completer.complete(results); |
| 572 } | 585 } |
| 573 }, onError: (e, s) { | 586 }, onError: (e, s) { |
| 574 if (_failedTask != null) return; | 587 if (_failedTask != null) return; |
| 575 _failedTask = task; | 588 _failedTask = task; |
| 576 _completer.completeError(e, s); | 589 _completer.completeError(e, s); |
| 577 }); | 590 }); |
| 578 } | 591 } |
| 579 | 592 |
| 580 /** | 593 /** |
| 581 * A Future that complets with a List of the values from all the added | 594 * A Future that completes with a List of the values from all the added |
| 582 * tasks, when they have all completed. | 595 * tasks, when they have all completed. |
| 583 * | 596 * |
| 584 * If any task fails, this Future will receive the error. Only the first | 597 * If any task fails, this Future will receive the error. Only the first |
| 585 * error will be sent to the Future. | 598 * error will be sent to the Future. |
| 586 */ | 599 */ |
| 587 Future<List<E>> get future => _completer.future; | 600 Future<List<E>> get future => _completer.future; |
| 588 } | 601 } |
| 589 | 602 |
| 590 /// A pending update to notify the resolver that a [Source] has been added or | 603 /// A pending update to notify the resolver that a [Source] has been added or |
| 591 /// changed. This is used by the `_performResolve` algorithm above to apply all | 604 /// changed. This is used by the `_performResolve` algorithm above to apply all |
| 592 /// changes after it first discovers the transitive closure of files that are | 605 /// changes after it first discovers the transitive closure of files that are |
| 593 /// reachable from the sources. | 606 /// reachable from the sources. |
| 594 class _PendingUpdate { | 607 class _PendingUpdate { |
| 595 _AssetBasedSource source; | 608 _AssetBasedSource source; |
| 596 String content; | 609 String content; |
| 597 | 610 |
| 598 _PendingUpdate(this.source, this.content); | 611 _PendingUpdate(this.source, this.content); |
| 599 | 612 |
| 600 void apply(ChangeSet changeSet) { | 613 void apply(ChangeSet changeSet) { |
| 601 if (!source.updateContents(content)) return; | 614 if (!source.updateContents(content)) return; |
| 602 if (source._revision == 1 && source._contents != null) { | 615 if (source._revision == 1 && source._contents != null) { |
| 603 changeSet.addedSource(source); | 616 changeSet.addedSource(source); |
| 604 } else { | 617 } else { |
| 605 changeSet.changedSource(source); | 618 changeSet.changedSource(source); |
| 606 } | 619 } |
| 607 } | 620 } |
| 608 } | 621 } |
| OLD | NEW |