| 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 parseDirectives; |
| 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; | 9 import 'package:analyzer/src/generated/ast.dart' hide ConstantEvaluator; |
| 10 import 'package:analyzer/src/generated/constant.dart' show ConstantEvaluator, | 10 import 'package:analyzer/src/generated/constant.dart' show ConstantEvaluator, |
| 11 EvaluationResult; | 11 EvaluationResult; |
| 12 import 'package:analyzer/src/generated/element.dart'; | 12 import 'package:analyzer/src/generated/element.dart'; |
| 13 import 'package:analyzer/src/generated/engine.dart'; | 13 import 'package:analyzer/src/generated/engine.dart'; |
| 14 import 'package:analyzer/src/generated/java_io.dart'; | |
| 15 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; | 14 import 'package:analyzer/src/generated/sdk.dart' show DartSdk; |
| 16 import 'package:analyzer/src/generated/sdk_io.dart' show DirectoryBasedDartSdk; | |
| 17 import 'package:analyzer/src/generated/source.dart'; | 15 import 'package:analyzer/src/generated/source.dart'; |
| 18 import 'package:barback/barback.dart'; | 16 import 'package:barback/barback.dart'; |
| 19 import 'package:code_transformers/assets.dart'; | 17 import 'package:code_transformers/assets.dart'; |
| 20 import 'package:path/path.dart' as native_path; | 18 import 'package:path/path.dart' as native_path; |
| 21 import 'package:source_maps/refactor.dart'; | 19 import 'package:source_maps/refactor.dart'; |
| 22 import 'package:source_maps/span.dart' show SourceFile, Span; | 20 import 'package:source_maps/span.dart' show SourceFile, Span; |
| 23 | 21 |
| 24 import 'resolver.dart'; | 22 import 'resolver.dart'; |
| 23 import 'dart_sdk.dart' show UriAnnotatedSource; |
| 25 | 24 |
| 26 // We should always be using url paths here since it's always Dart/pub code. | 25 // We should always be using url paths here since it's always Dart/pub code. |
| 27 final path = native_path.url; | 26 final path = native_path.url; |
| 28 | 27 |
| 29 /// Resolves and updates an AST based on Barback-based assets. | 28 /// Resolves and updates an AST based on Barback-based assets. |
| 30 /// | 29 /// |
| 31 /// This also provides a handful of useful APIs for traversing and working | 30 /// This also provides a handful of useful APIs for traversing and working |
| 32 /// with the resolved AST. | 31 /// with the resolved AST. |
| 33 class ResolverImpl implements Resolver { | 32 class ResolverImpl implements Resolver { |
| 34 /// Cache of all asset sources currently referenced. | 33 /// Cache of all asset sources currently referenced. |
| 35 final Map<AssetId, _AssetBasedSource> sources = | 34 final Map<AssetId, _AssetBasedSource> sources = |
| 36 <AssetId, _AssetBasedSource>{}; | 35 <AssetId, _AssetBasedSource>{}; |
| 37 | 36 |
| 38 final InternalAnalysisContext _context = | 37 final InternalAnalysisContext _context = |
| 39 AnalysisEngine.instance.createAnalysisContext(); | 38 AnalysisEngine.instance.createAnalysisContext(); |
| 40 | 39 |
| 41 /// Transform for which this is currently updating, or null when not updating. | 40 /// Transform for which this is currently updating, or null when not updating. |
| 42 Transform _currentTransform; | 41 Transform _currentTransform; |
| 43 | 42 |
| 44 /// The currently resolved entry libraries, or null if nothing is resolved. | 43 /// The currently resolved entry libraries, or null if nothing is resolved. |
| 45 List<LibraryElement> _entryLibraries; | 44 List<LibraryElement> _entryLibraries; |
| 46 Set<LibraryElement> _libraries; | 45 Set<LibraryElement> _libraries; |
| 47 | 46 |
| 48 /// Future indicating when this resolver is done in the current phase. | 47 /// Future indicating when this resolver is done in the current phase. |
| 49 Future _lastPhaseComplete = new Future.value(); | 48 Future _lastPhaseComplete = new Future.value(); |
| 50 | 49 |
| 51 /// Completer for wrapping up the current phase. | 50 /// Completer for wrapping up the current phase. |
| 52 Completer _currentPhaseComplete; | 51 Completer _currentPhaseComplete; |
| 53 | 52 |
| 54 /// Handler for all Dart SDK (dart:) sources. | 53 /// Creates a resolver with a given [sdk] implementation for resolving |
| 55 DirectoryBasedDartSdk _dartSdk; | 54 /// `dart:*` imports. |
| 56 | 55 ResolverImpl(DartSdk sdk, DartUriResolver dartUriResolver, |
| 57 /// Creates a resolver, where [sdkDir] is the root directory of the Dart SDK, | 56 {AnalysisOptions options}) { |
| 58 /// for resolving `dart:*` imports. | |
| 59 ResolverImpl(String sdkDir, {AnalysisOptions options}) { | |
| 60 if (options == null) { | 57 if (options == null) { |
| 61 options = new AnalysisOptionsImpl() | 58 options = new AnalysisOptionsImpl() |
| 62 ..cacheSize = 256 // # of sources to cache ASTs for. | 59 ..cacheSize = 256 // # of sources to cache ASTs for. |
| 63 ..preserveComments = false | 60 ..preserveComments = false |
| 64 ..analyzeFunctionBodies = true; | 61 ..analyzeFunctionBodies = true; |
| 65 } | 62 } |
| 66 _context.analysisOptions = options; | 63 _context.analysisOptions = options; |
| 67 | 64 sdk.context.analysisOptions = options; |
| 68 _dartSdk = new _DirectoryBasedDartSdkProxy(new JavaFile(sdkDir)); | 65 _context.sourceFactory = new SourceFactory([dartUriResolver, |
| 69 _dartSdk.context.analysisOptions = options; | |
| 70 | |
| 71 _context.sourceFactory = new SourceFactory([ | |
| 72 new DartUriResolverProxy(_dartSdk), | |
| 73 new _AssetUriResolver(this)]); | 66 new _AssetUriResolver(this)]); |
| 74 } | 67 } |
| 75 | 68 |
| 76 LibraryElement getLibrary(AssetId assetId) { | 69 LibraryElement getLibrary(AssetId assetId) { |
| 77 var source = sources[assetId]; | 70 var source = sources[assetId]; |
| 78 return source == null ? null : _context.computeLibraryElement(source); | 71 return source == null ? null : _context.computeLibraryElement(source); |
| 79 } | 72 } |
| 80 | 73 |
| 81 Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { | 74 Future<Resolver> resolve(Transform transform, [List<AssetId> entryPoints]) { |
| 82 // Can only have one resolve in progress at a time, so chain the current | 75 // Can only have one resolve in progress at a time, so chain the current |
| (...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 241 Uri getImportUri(LibraryElement lib, {AssetId from}) => | 234 Uri getImportUri(LibraryElement lib, {AssetId from}) => |
| 242 _getSourceUri(lib, from: from); | 235 _getSourceUri(lib, from: from); |
| 243 | 236 |
| 244 | 237 |
| 245 /// Similar to getImportUri but will get the part URI for parts rather than | 238 /// Similar to getImportUri but will get the part URI for parts rather than |
| 246 /// the library URI. | 239 /// the library URI. |
| 247 Uri _getSourceUri(Element element, {AssetId from}) { | 240 Uri _getSourceUri(Element element, {AssetId from}) { |
| 248 var source = element.source; | 241 var source = element.source; |
| 249 if (source is _AssetBasedSource) { | 242 if (source is _AssetBasedSource) { |
| 250 return source.getSourceUri(from); | 243 return source.getSourceUri(from); |
| 251 } else if (source is _DartSourceProxy) { | 244 } else if (source is UriAnnotatedSource) { |
| 252 return source.uri; | 245 return source.uri; |
| 253 } | 246 } |
| 254 // Should not be able to encounter any other source types. | 247 // Should not be able to encounter any other source types. |
| 255 throw new StateError('Unable to resolve URI for ${source.runtimeType}'); | 248 throw new StateError('Unable to resolve URI for ${source.runtimeType}'); |
| 256 } | 249 } |
| 257 | 250 |
| 258 AssetId getSourceAssetId(Element element) { | 251 AssetId getSourceAssetId(Element element) { |
| 259 var source = element.source; | 252 var source = element.source; |
| 260 if (source is _AssetBasedSource) return source.assetId; | 253 if (source is _AssetBasedSource) return source.assetId; |
| 261 return null; | 254 return null; |
| (...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 313 | 306 |
| 314 /// The file contents. | 307 /// The file contents. |
| 315 String _contents; | 308 String _contents; |
| 316 | 309 |
| 317 _AssetBasedSource(this.assetId, this._resolver); | 310 _AssetBasedSource(this.assetId, this._resolver); |
| 318 | 311 |
| 319 /// Update the dependencies of this source. This parses [contents] but avoids | 312 /// Update the dependencies of this source. This parses [contents] but avoids |
| 320 /// any analyzer resolution. | 313 /// any analyzer resolution. |
| 321 void updateDependencies(String contents) { | 314 void updateDependencies(String contents) { |
| 322 if (contents == _contents) return; | 315 if (contents == _contents) return; |
| 323 var unit = parseCompilationUnit(contents, suppressErrors: true); | 316 var unit = parseDirectives(contents, suppressErrors: true); |
| 324 _dependentAssets = unit.directives | 317 _dependentAssets = unit.directives |
| 325 .where((d) => (d is ImportDirective || d is PartDirective || | 318 .where((d) => (d is ImportDirective || d is PartDirective || |
| 326 d is ExportDirective)) | 319 d is ExportDirective)) |
| 327 .map((d) => _resolve(assetId, d.uri.stringValue, _logger, | 320 .map((d) => _resolve(assetId, d.uri.stringValue, _logger, |
| 328 _getSpan(d, contents))) | 321 _getSpan(d, contents))) |
| 329 .where((id) => id != null).toSet(); | 322 .where((id) => id != null).toSet(); |
| 330 } | 323 } |
| 331 | 324 |
| 332 /// Update the contents of this file with [contents]. | 325 /// Update the contents of this file with [contents]. |
| 333 /// | 326 /// |
| (...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 446 | 439 |
| 447 Source fromEncoding(UriKind kind, Uri uri) => | 440 Source fromEncoding(UriKind kind, Uri uri) => |
| 448 throw new UnsupportedError('fromEncoding is not supported'); | 441 throw new UnsupportedError('fromEncoding is not supported'); |
| 449 | 442 |
| 450 Uri restoreAbsolute(Source source) => | 443 Uri restoreAbsolute(Source source) => |
| 451 throw new UnsupportedError('restoreAbsolute is not supported'); | 444 throw new UnsupportedError('restoreAbsolute is not supported'); |
| 452 | 445 |
| 453 TransformLogger get logger => _resolver._currentTransform.logger; | 446 TransformLogger get logger => _resolver._currentTransform.logger; |
| 454 } | 447 } |
| 455 | 448 |
| 456 | |
| 457 /// Dart SDK which wraps all Dart sources to ensure they are tracked with Uris. | |
| 458 /// | |
| 459 /// Just a simple wrapper to make it easy to make sure that all sources we | |
| 460 /// encounter are either _AssetBasedSource or _DartSourceProxy. | |
| 461 class _DirectoryBasedDartSdkProxy extends DirectoryBasedDartSdk { | |
| 462 _DirectoryBasedDartSdkProxy(JavaFile sdkDirectory) : super(sdkDirectory); | |
| 463 | |
| 464 Source mapDartUri(String dartUri) => | |
| 465 _DartSourceProxy.wrap(super.mapDartUri(dartUri), Uri.parse(dartUri)); | |
| 466 } | |
| 467 | |
| 468 | |
| 469 /// Dart SDK resolver which wraps all Dart sources to ensure they are tracked | |
| 470 /// with URIs. | |
| 471 class DartUriResolverProxy implements DartUriResolver { | |
| 472 final DartUriResolver _proxy; | |
| 473 DartUriResolverProxy(DirectoryBasedDartSdk sdk) : | |
| 474 _proxy = new DartUriResolver(sdk); | |
| 475 | |
| 476 Source resolveAbsolute(Uri uri) => | |
| 477 _DartSourceProxy.wrap(_proxy.resolveAbsolute(uri), uri); | |
| 478 | |
| 479 DartSdk get dartSdk => _proxy.dartSdk; | |
| 480 | |
| 481 Source fromEncoding(UriKind kind, Uri uri) => | |
| 482 throw new UnsupportedError('fromEncoding is not supported'); | |
| 483 | |
| 484 Uri restoreAbsolute(Source source) => | |
| 485 throw new UnsupportedError('restoreAbsolute is not supported'); | |
| 486 } | |
| 487 | |
| 488 /// Source file for dart: sources which track the sources with dart: URIs. | |
| 489 /// | |
| 490 /// This is primarily to support [Resolver.getImportUri] for Dart SDK (dart:) | |
| 491 /// based libraries. | |
| 492 class _DartSourceProxy implements Source { | |
| 493 | |
| 494 /// Absolute URI which this source can be imported from | |
| 495 final Uri uri; | |
| 496 | |
| 497 /// Underlying source object. | |
| 498 final Source _proxy; | |
| 499 | |
| 500 _DartSourceProxy(this._proxy, this.uri); | |
| 501 | |
| 502 /// Ensures that [source] is a _DartSourceProxy. | |
| 503 static _DartSourceProxy wrap(Source source, Uri uri) { | |
| 504 if (source == null || source is _DartSourceProxy) return source; | |
| 505 return new _DartSourceProxy(source, uri); | |
| 506 } | |
| 507 | |
| 508 Source resolveRelative(Uri relativeUri) { | |
| 509 // Assume that the type can be accessed via this URI, since these | |
| 510 // should only be parts for dart core files. | |
| 511 return wrap(_proxy.resolveRelative(relativeUri), uri); | |
| 512 } | |
| 513 | |
| 514 bool exists() => _proxy.exists(); | |
| 515 | |
| 516 bool operator ==(Object other) => | |
| 517 (other is _DartSourceProxy && _proxy == other._proxy); | |
| 518 | |
| 519 int get hashCode => _proxy.hashCode; | |
| 520 | |
| 521 TimestampedData<String> get contents => _proxy.contents; | |
| 522 | |
| 523 String get encoding => _proxy.encoding; | |
| 524 | |
| 525 String get fullName => _proxy.fullName; | |
| 526 | |
| 527 int get modificationStamp => _proxy.modificationStamp; | |
| 528 | |
| 529 String get shortName => _proxy.shortName; | |
| 530 | |
| 531 UriKind get uriKind => _proxy.uriKind; | |
| 532 | |
| 533 bool get isInSystemLibrary => _proxy.isInSystemLibrary; | |
| 534 } | |
| 535 | |
| 536 /// Get an asset ID for a URL relative to another source asset. | 449 /// Get an asset ID for a URL relative to another source asset. |
| 537 AssetId _resolve(AssetId source, String url, TransformLogger logger, | 450 AssetId _resolve(AssetId source, String url, TransformLogger logger, |
| 538 Span span) { | 451 Span span) { |
| 539 if (url == null || url == '') return null; | 452 if (url == null || url == '') return null; |
| 540 var uri = Uri.parse(url); | 453 var uri = Uri.parse(url); |
| 541 | 454 |
| 542 // Workaround for dartbug.com/17156- pub transforms package: imports from | 455 // Workaround for dartbug.com/17156- pub transforms package: imports from |
| 543 // files of the transformers package to have absolute /packages/ URIs. | 456 // files of the transformers package to have absolute /packages/ URIs. |
| 544 if (uri.scheme == '' && path.isAbsolute(url) | 457 if (uri.scheme == '' && path.isAbsolute(url) |
| 545 && uri.pathSegments[0] == 'packages') { | 458 && uri.pathSegments[0] == 'packages') { |
| (...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 626 | 539 |
| 627 void apply(ChangeSet changeSet) { | 540 void apply(ChangeSet changeSet) { |
| 628 if (!source.updateContents(content)) return; | 541 if (!source.updateContents(content)) return; |
| 629 if (source._revision == 1 && source._contents != null) { | 542 if (source._revision == 1 && source._contents != null) { |
| 630 changeSet.addedSource(source); | 543 changeSet.addedSource(source); |
| 631 } else { | 544 } else { |
| 632 changeSet.changedSource(source); | 545 changeSet.changedSource(source); |
| 633 } | 546 } |
| 634 } | 547 } |
| 635 } | 548 } |
| OLD | NEW |