 Chromium Code Reviews
 Chromium Code Reviews Issue 914373004:
  Use package: URIs for files in lib  (Closed) 
  Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
    
  
    Issue 914373004:
  Use package: URIs for files in lib  (Closed) 
  Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart| 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 context.directory.manager; | 5 library context.directory.manager; | 
| 6 | 6 | 
| 7 import 'dart:async'; | 7 import 'dart:async'; | 
| 8 import 'dart:collection'; | 8 import 'dart:collection'; | 
| 9 | 9 | 
| 10 import 'package:analyzer/file_system/file_system.dart'; | 10 import 'package:analyzer/file_system/file_system.dart'; | 
| (...skipping 18 matching lines...) Expand all Loading... | |
| 29 */ | 29 */ | 
| 30 const String PUBSPEC_NAME = 'pubspec.yaml'; | 30 const String PUBSPEC_NAME = 'pubspec.yaml'; | 
| 31 | 31 | 
| 32 | 32 | 
| 33 /** | 33 /** | 
| 34 * Class that maintains a mapping from included/excluded paths to a set of | 34 * Class that maintains a mapping from included/excluded paths to a set of | 
| 35 * folders that should correspond to analysis contexts. | 35 * folders that should correspond to analysis contexts. | 
| 36 */ | 36 */ | 
| 37 abstract class ContextManager { | 37 abstract class ContextManager { | 
| 38 /** | 38 /** | 
| 39 * The name of the `lib` directory. | |
| 40 */ | |
| 41 static const String LIB_DIR_NAME = 'lib'; | |
| 42 | |
| 43 /** | |
| 39 * [_ContextInfo] object for each included directory in the most | 44 * [_ContextInfo] object for each included directory in the most | 
| 40 * recent successful call to [setRoots]. | 45 * recent successful call to [setRoots]. | 
| 41 */ | 46 */ | 
| 42 Map<Folder, _ContextInfo> _contexts = new HashMap<Folder, _ContextInfo>(); | 47 Map<Folder, _ContextInfo> _contexts = new HashMap<Folder, _ContextInfo>(); | 
| 43 | 48 | 
| 44 /** | 49 /** | 
| 45 * The [ResourceProvider] using which paths are converted into [Resource]s. | 50 * The [ResourceProvider] using which paths are converted into [Resource]s. | 
| 46 */ | 51 */ | 
| 47 final ResourceProvider resourceProvider; | 52 final ResourceProvider resourceProvider; | 
| 48 | 53 | 
| (...skipping 29 matching lines...) Expand all Loading... | |
| 78 * Provider which is used to determine the mapping from package name to | 83 * Provider which is used to determine the mapping from package name to | 
| 79 * package folder. | 84 * package folder. | 
| 80 */ | 85 */ | 
| 81 final PackageMapProvider _packageMapProvider; | 86 final PackageMapProvider _packageMapProvider; | 
| 82 | 87 | 
| 83 ContextManager(this.resourceProvider, this._packageMapProvider) { | 88 ContextManager(this.resourceProvider, this._packageMapProvider) { | 
| 84 pathContext = resourceProvider.pathContext; | 89 pathContext = resourceProvider.pathContext; | 
| 85 } | 90 } | 
| 86 | 91 | 
| 87 /** | 92 /** | 
| 88 * Called when a new context needs to be created. | 93 * Create and return a new analysis context. | 
| 89 */ | 94 */ | 
| 90 void addContext(Folder folder, UriResolver packageUriResolver); | 95 AnalysisContext addContext(Folder folder, UriResolver packageUriResolver); | 
| 91 | 96 | 
| 92 /** | 97 /** | 
| 93 * Called when the set of files associated with a context have changed (or | 98 * Called when the set of files associated with a context have changed (or | 
| 94 * some of those files have been modified). [changeSet] is the set of | 99 * some of those files have been modified). [changeSet] is the set of | 
| 95 * changes that need to be applied to the context. | 100 * changes that need to be applied to the context. | 
| 96 */ | 101 */ | 
| 97 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 102 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 
| 98 | 103 | 
| 99 /** | 104 /** | 
| 100 * We are about to start computing the package map. | 105 * We are about to start computing the package map. | 
| (...skipping 174 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 275 continue; | 280 continue; | 
| 276 } | 281 } | 
| 277 _addPreviouslyExcludedSources(info, changeSet, child, oldExcludedPaths); | 282 _addPreviouslyExcludedSources(info, changeSet, child, oldExcludedPaths); | 
| 278 } | 283 } | 
| 279 } | 284 } | 
| 280 } | 285 } | 
| 281 | 286 | 
| 282 /** | 287 /** | 
| 283 * Resursively adds all Dart and HTML files to the [changeSet]. | 288 * Resursively adds all Dart and HTML files to the [changeSet]. | 
| 284 */ | 289 */ | 
| 285 void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextInfo info) { | 290 void _addSourceFiles(ChangeSet changeSet, Folder folder, _ContextInfo info, | 
| 291 bool pubspecExists, bool createPackageUri) { | |
| 286 if (info.excludesResource(folder) || folder.shortName.startsWith('.')) { | 292 if (info.excludesResource(folder) || folder.shortName.startsWith('.')) { | 
| 287 return; | 293 return; | 
| 288 } | 294 } | 
| 289 List<Resource> children = folder.getChildren(); | 295 List<Resource> children = folder.getChildren(); | 
| 290 for (Resource child in children) { | 296 for (Resource child in children) { | 
| 291 String path = child.path; | 297 String path = child.path; | 
| 292 // ignore excluded files or folders | 298 // ignore excluded files or folders | 
| 293 if (_isExcluded(path)) { | 299 if (_isExcluded(path)) { | 
| 294 continue; | 300 continue; | 
| 295 } | 301 } | 
| 296 // add files, recurse into folders | 302 // add files, recurse into folders | 
| 297 if (child is File) { | 303 if (child is File) { | 
| 298 if (_shouldFileBeAnalyzed(child)) { | 304 if (_shouldFileBeAnalyzed(child)) { | 
| 299 Source source = child.createSource(); | 305 Source source = child.createSource(); | 
| 306 if (createPackageUri) { | |
| 
Paul Berry
2015/02/12 21:56:09
I think we could achieve the same effect with less
 
Brian Wilkerson
2015/02/13 17:46:07
Your comment got me to thinking more deeply about
 | |
| 307 Uri uri = info.context.sourceFactory.restoreUri(source); | |
| 308 source = child.createSource(uri); | |
| 309 } | |
| 300 changeSet.addedSource(source); | 310 changeSet.addedSource(source); | 
| 301 info.sources[path] = source; | 311 info.sources[path] = source; | 
| 302 } | 312 } | 
| 303 } else if (child is Folder) { | 313 } else if (child is Folder) { | 
| 304 if (child.shortName == PACKAGES_NAME) { | 314 String shortName = child.shortName; | 
| 315 if (shortName == PACKAGES_NAME) { | |
| 305 continue; | 316 continue; | 
| 306 } | 317 } | 
| 307 _addSourceFiles(changeSet, child, info); | 318 if (pubspecExists && | 
| 319 !createPackageUri && | |
| 320 shortName == LIB_DIR_NAME && | |
| 321 child.parent == info.folder) { | |
| 322 createPackageUri = true; | |
| 323 } | |
| 324 _addSourceFiles( | |
| 325 changeSet, | |
| 326 child, | |
| 327 info, | |
| 328 pubspecExists, | |
| 329 createPackageUri); | |
| 308 } | 330 } | 
| 309 } | 331 } | 
| 310 } | 332 } | 
| 311 | 333 | 
| 312 /** | 334 /** | 
| 313 * Compute the appropriate package URI resolver for [folder], and store | 335 * Compute the appropriate package URI resolver for [folder], and store | 
| 314 * dependency information in [info]. Return `null` if no package map can | 336 * dependency information in [info]. Return `null` if no package map can | 
| 315 * be computed. | 337 * be computed. | 
| 316 */ | 338 */ | 
| 317 UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) { | 339 UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) { | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 331 resourceProvider, | 353 resourceProvider, | 
| 332 packageMapInfo.packageMap); | 354 packageMapInfo.packageMap); | 
| 333 // TODO(paulberry): if any of the dependencies is outside of [folder], | 355 // TODO(paulberry): if any of the dependencies is outside of [folder], | 
| 334 // we'll need to watch their parent folders as well. | 356 // we'll need to watch their parent folders as well. | 
| 335 } | 357 } | 
| 336 } | 358 } | 
| 337 | 359 | 
| 338 /** | 360 /** | 
| 339 * Create a new empty context associated with [folder]. | 361 * Create a new empty context associated with [folder]. | 
| 340 */ | 362 */ | 
| 341 _ContextInfo _createContext(Folder folder, List<_ContextInfo> children) { | 363 _ContextInfo _createContext(Folder folder, File pubspecFile, | 
| 342 _ContextInfo info = | 364 List<_ContextInfo> children) { | 
| 343 new _ContextInfo(folder, children, normalizedPackageRoots[folder.path]); | 365 _ContextInfo info = new _ContextInfo( | 
| 366 folder, | |
| 367 pubspecFile, | |
| 368 children, | |
| 369 normalizedPackageRoots[folder.path]); | |
| 344 _contexts[folder] = info; | 370 _contexts[folder] = info; | 
| 345 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 371 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 
| 346 _handleWatchEvent(folder, info, event); | 372 _handleWatchEvent(folder, info, event); | 
| 347 }); | 373 }); | 
| 348 UriResolver packageUriResolver = _computePackageUriResolver(folder, info); | 374 UriResolver packageUriResolver = _computePackageUriResolver(folder, info); | 
| 349 addContext(folder, packageUriResolver); | 375 info.context = addContext(folder, packageUriResolver); | 
| 350 return info; | 376 return info; | 
| 351 } | 377 } | 
| 352 | 378 | 
| 353 /** | 379 /** | 
| 354 * Creates a new context associated with [folder]. | 380 * Creates a new context associated with [folder]. | 
| 355 * | 381 * | 
| 356 * If there are subfolders with 'pubspec.yaml' files, separate contexts | 382 * If there are subfolders with 'pubspec.yaml' files, separate contexts | 
| 357 * are created for them, and excluded from the context associated with | 383 * are created for them, and excluded from the context associated with | 
| 358 * [folder]. | 384 * [folder]. | 
| 359 * | 385 * | 
| 360 * If [folder] itself contains a 'pubspec.yaml' file, subfolders are ignored. | 386 * If [folder] itself contains a 'pubspec.yaml' file, subfolders are ignored. | 
| 361 * | 387 * | 
| 362 * If [withPubspecOnly] is `true`, a context will be created only if there | 388 * If [withPubspecOnly] is `true`, a context will be created only if there | 
| 363 * is a 'pubspec.yaml' file in [folder]. | 389 * is a 'pubspec.yaml' file in [folder]. | 
| 364 * | 390 * | 
| 365 * Returns create pubspec-based contexts. | 391 * Returns create pubspec-based contexts. | 
| 366 */ | 392 */ | 
| 367 List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) { | 393 List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) { | 
| 368 // check if there is a pubspec in the folder | 394 // check whether there is a pubspec in the folder | 
| 369 { | 395 File pubspecFile = folder.getChild(PUBSPEC_NAME); | 
| 370 File pubspecFile = folder.getChild(PUBSPEC_NAME); | 396 bool pubspecExists = pubspecFile.exists; | 
| 371 if (pubspecFile.exists) { | 397 if (pubspecExists) { | 
| 372 _ContextInfo info = _createContextWithSources(folder, <_ContextInfo>[]); | 398 _ContextInfo info = _createContextWithSources( | 
| 373 return [info]; | 399 folder, | 
| 374 } | 400 pubspecFile, | 
| 401 pubspecExists, | |
| 402 <_ContextInfo>[]); | |
| 403 return [info]; | |
| 375 } | 404 } | 
| 376 // try to find subfolders with pubspec files | 405 // try to find subfolders with pubspec files | 
| 377 List<_ContextInfo> children = <_ContextInfo>[]; | 406 List<_ContextInfo> children = <_ContextInfo>[]; | 
| 378 for (Resource child in folder.getChildren()) { | 407 for (Resource child in folder.getChildren()) { | 
| 379 if (child is Folder) { | 408 if (child is Folder) { | 
| 380 List<_ContextInfo> childContexts = _createContexts(child, true); | 409 List<_ContextInfo> childContexts = _createContexts(child, true); | 
| 381 children.addAll(childContexts); | 410 children.addAll(childContexts); | 
| 382 } | 411 } | 
| 383 } | 412 } | 
| 384 // no pubspec, done | 413 // no pubspec, done | 
| 385 if (withPubspecOnly) { | 414 if (withPubspecOnly) { | 
| 386 return children; | 415 return children; | 
| 387 } | 416 } | 
| 388 // OK, create a context without a pubspec | 417 // OK, create a context without a pubspec | 
| 389 _createContextWithSources(folder, children); | 418 _createContextWithSources(folder, pubspecFile, pubspecExists, children); | 
| 390 return children; | 419 return children; | 
| 391 } | 420 } | 
| 392 | 421 | 
| 393 /** | 422 /** | 
| 394 * Create a new context associated with [folder] and fills its with sources. | 423 * Create a new context associated with the given [folder]. The [pubspecFile] | 
| 424 * is the `pubspec.yaml` file contained in the folder, and [pubspecExists] is | |
| 425 * `true` if the file exists. Add any sources that are not included in one of | |
| 426 * the [children] to the context. | |
| 395 */ | 427 */ | 
| 396 _ContextInfo _createContextWithSources(Folder folder, | 428 _ContextInfo _createContextWithSources(Folder folder, File pubspecFile, | 
| 397 List<_ContextInfo> children) { | 429 bool pubspecExists, List<_ContextInfo> children) { | 
| 398 _ContextInfo info = _createContext(folder, children); | 430 _ContextInfo info = _createContext(folder, pubspecFile, children); | 
| 399 ChangeSet changeSet = new ChangeSet(); | 431 ChangeSet changeSet = new ChangeSet(); | 
| 400 _addSourceFiles(changeSet, folder, info); | 432 _addSourceFiles(changeSet, folder, info, pubspecExists, false); | 
| 401 applyChangesToContext(folder, changeSet); | 433 applyChangesToContext(folder, changeSet); | 
| 402 return info; | 434 return info; | 
| 403 } | 435 } | 
| 404 | 436 | 
| 405 /** | 437 /** | 
| 406 * Clean up and destroy the context associated with the given folder. | 438 * Clean up and destroy the context associated with the given folder. | 
| 407 */ | 439 */ | 
| 408 void _destroyContext(Folder folder) { | 440 void _destroyContext(Folder folder) { | 
| 409 _contexts[folder].changeSubscription.cancel(); | 441 _contexts[folder].changeSubscription.cancel(); | 
| 410 _contexts.remove(folder); | 442 _contexts.remove(folder); | 
| 411 removeContext(folder); | 443 removeContext(folder); | 
| 412 } | 444 } | 
| 413 | 445 | 
| 414 /** | 446 /** | 
| 415 * Extract a new [pubspecFile]-based context from [oldInfo]. | 447 * Extract a new [pubspecFile]-based context from [oldInfo]. | 
| 416 */ | 448 */ | 
| 417 void _extractContext(_ContextInfo oldInfo, File pubspecFile) { | 449 void _extractContext(_ContextInfo oldInfo, File pubspecFile) { | 
| 418 Folder newFolder = pubspecFile.parent; | 450 Folder newFolder = pubspecFile.parent; | 
| 419 _ContextInfo newInfo = _createContext(newFolder, []); | 451 _ContextInfo newInfo = _createContext(newFolder, pubspecFile, []); | 
| 420 newInfo.parent = oldInfo; | 452 newInfo.parent = oldInfo; | 
| 421 // prepare sources to extract | 453 // prepare sources to extract | 
| 422 Map<String, Source> extractedSources = new HashMap<String, Source>(); | 454 Map<String, Source> extractedSources = new HashMap<String, Source>(); | 
| 423 oldInfo.sources.forEach((path, source) { | 455 oldInfo.sources.forEach((path, source) { | 
| 424 if (newFolder.contains(path)) { | 456 if (newFolder.contains(path)) { | 
| 425 extractedSources[path] = source; | 457 extractedSources[path] = source; | 
| 426 } | 458 } | 
| 427 }); | 459 }); | 
| 428 // update new context | 460 // update new context | 
| 429 { | 461 { | 
| (...skipping 192 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 622 */ | 654 */ | 
| 623 String pubspecPath; | 655 String pubspecPath; | 
| 624 | 656 | 
| 625 /** | 657 /** | 
| 626 * Stream subscription we are using to watch the context's directory for | 658 * Stream subscription we are using to watch the context's directory for | 
| 627 * changes. | 659 * changes. | 
| 628 */ | 660 */ | 
| 629 StreamSubscription<WatchEvent> changeSubscription; | 661 StreamSubscription<WatchEvent> changeSubscription; | 
| 630 | 662 | 
| 631 /** | 663 /** | 
| 664 * The analysis context that was created for the [folder]. | |
| 665 */ | |
| 666 AnalysisContext context; | |
| 667 | |
| 668 /** | |
| 632 * Map from full path to the [Source] object, for each source that has been | 669 * Map from full path to the [Source] object, for each source that has been | 
| 633 * added to the context. | 670 * added to the context. | 
| 634 */ | 671 */ | 
| 635 Map<String, Source> sources = new HashMap<String, Source>(); | 672 Map<String, Source> sources = new HashMap<String, Source>(); | 
| 636 | 673 | 
| 637 /** | 674 /** | 
| 638 * Dependencies of the context's package map. | 675 * Dependencies of the context's package map. | 
| 639 * If any of these files changes, the package map needs to be recomputed. | 676 * If any of these files changes, the package map needs to be recomputed. | 
| 640 */ | 677 */ | 
| 641 Set<String> packageMapDependencies; | 678 Set<String> packageMapDependencies; | 
| 642 | 679 | 
| 643 _ContextInfo(this.folder, this.children, this.packageRoot) { | 680 _ContextInfo(this.folder, File pubspecFile, this.children, this.packageRoot) { | 
| 644 pubspecPath = folder.getChild(PUBSPEC_NAME).path; | 681 pubspecPath = pubspecFile.path; | 
| 645 for (_ContextInfo child in children) { | 682 for (_ContextInfo child in children) { | 
| 646 child.parent = this; | 683 child.parent = this; | 
| 647 } | 684 } | 
| 648 } | 685 } | 
| 649 | 686 | 
| 650 /** | 687 /** | 
| 651 * Returns `true` if this context is root folder based. | 688 * Returns `true` if this context is root folder based. | 
| 652 */ | 689 */ | 
| 653 bool get isRoot => parent == null; | 690 bool get isRoot => parent == null; | 
| 654 | 691 | 
| (...skipping 13 matching lines...) Expand all Loading... | |
| 668 return excludes(resource.path); | 705 return excludes(resource.path); | 
| 669 } | 706 } | 
| 670 | 707 | 
| 671 /** | 708 /** | 
| 672 * Returns `true` if [path] is the pubspec file of this context. | 709 * Returns `true` if [path] is the pubspec file of this context. | 
| 673 */ | 710 */ | 
| 674 bool isPubspec(String path) { | 711 bool isPubspec(String path) { | 
| 675 return path == pubspecPath; | 712 return path == pubspecPath; | 
| 676 } | 713 } | 
| 677 } | 714 } | 
| OLD | NEW |