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 import 'dart:convert'; | |
9 import 'dart:core' hide Resource; | 10 import 'dart:core' hide Resource; |
10 | 11 |
11 import 'package:analysis_server/src/analysis_server.dart'; | 12 import 'package:analysis_server/src/analysis_server.dart'; |
12 import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.d art'; | 13 import 'package:analysis_server/src/source/optimizing_pub_package_map_provider.d art'; |
13 import 'package:analysis_server/uri/resolver_provider.dart'; | 14 import 'package:analysis_server/uri/resolver_provider.dart'; |
14 import 'package:analyzer/file_system/file_system.dart'; | 15 import 'package:analyzer/file_system/file_system.dart'; |
15 import 'package:analyzer/instrumentation/instrumentation.dart'; | 16 import 'package:analyzer/instrumentation/instrumentation.dart'; |
16 import 'package:analyzer/source/package_map_resolver.dart'; | 17 import 'package:analyzer/source/package_map_resolver.dart'; |
17 import 'package:analyzer/src/generated/engine.dart'; | 18 import 'package:analyzer/src/generated/engine.dart'; |
18 import 'package:analyzer/src/generated/java_io.dart'; | 19 import 'package:analyzer/src/generated/java_io.dart'; |
19 import 'package:analyzer/src/generated/source.dart'; | 20 import 'package:analyzer/src/generated/source.dart'; |
20 import 'package:analyzer/src/generated/source_io.dart'; | 21 import 'package:analyzer/src/generated/source_io.dart'; |
22 import 'package:package_config/packages.dart'; | |
23 import 'package:package_config/packages_file.dart' as pkgfile show parse; | |
24 import 'package:package_config/src/packages_impl.dart' show MapPackages; | |
21 import 'package:path/path.dart' as pathos; | 25 import 'package:path/path.dart' as pathos; |
22 import 'package:watcher/watcher.dart'; | 26 import 'package:watcher/watcher.dart'; |
23 | 27 |
24 /** | 28 /** |
25 * Class that maintains a mapping from included/excluded paths to a set of | 29 * Class that maintains a mapping from included/excluded paths to a set of |
26 * folders that should correspond to analysis contexts. | 30 * folders that should correspond to analysis contexts. |
27 */ | 31 */ |
28 abstract class AbstractContextManager implements ContextManager { | 32 abstract class AbstractContextManager implements ContextManager { |
29 /** | 33 /** |
30 * The name of the `lib` directory. | 34 * The name of the `lib` directory. |
31 */ | 35 */ |
32 static const String LIB_DIR_NAME = 'lib'; | 36 static const String LIB_DIR_NAME = 'lib'; |
33 | 37 |
34 /** | 38 /** |
35 * The name of `packages` folders. | 39 * The name of `packages` folders. |
36 */ | 40 */ |
37 static const String PACKAGES_NAME = 'packages'; | 41 static const String PACKAGES_NAME = 'packages'; |
38 | 42 |
39 /** | 43 /** |
40 * File name of pubspec files. | 44 * File name of pubspec files. |
41 */ | 45 */ |
42 static const String PUBSPEC_NAME = 'pubspec.yaml'; | 46 static const String PUBSPEC_NAME = 'pubspec.yaml'; |
43 | 47 |
44 /** | 48 /** |
49 * File name of package spec files. | |
50 */ | |
51 static const String PACKAGE_SPEC_NAME = '.packages'; | |
52 | |
53 /** | |
45 * [_ContextInfo] object for each included directory in the most | 54 * [_ContextInfo] object for each included directory in the most |
46 * recent successful call to [setRoots]. | 55 * recent successful call to [setRoots]. |
47 */ | 56 */ |
48 Map<Folder, _ContextInfo> _contexts = new HashMap<Folder, _ContextInfo>(); | 57 Map<Folder, _ContextInfo> _contexts = new HashMap<Folder, _ContextInfo>(); |
49 | 58 |
50 /** | 59 /** |
51 * The [ResourceProvider] using which paths are converted into [Resource]s. | 60 * The [ResourceProvider] using which paths are converted into [Resource]s. |
52 */ | 61 */ |
53 final ResourceProvider resourceProvider; | 62 final ResourceProvider resourceProvider; |
54 | 63 |
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
99 final InstrumentationService _instrumentationService; | 108 final InstrumentationService _instrumentationService; |
100 | 109 |
101 AbstractContextManager(this.resourceProvider, this.packageResolverProvider, | 110 AbstractContextManager(this.resourceProvider, this.packageResolverProvider, |
102 this._packageMapProvider, this._instrumentationService) { | 111 this._packageMapProvider, this._instrumentationService) { |
103 pathContext = resourceProvider.pathContext; | 112 pathContext = resourceProvider.pathContext; |
104 } | 113 } |
105 | 114 |
106 /** | 115 /** |
107 * Create and return a new analysis context. | 116 * Create and return a new analysis context. |
108 */ | 117 */ |
109 AnalysisContext addContext(Folder folder, UriResolver packageUriResolver); | 118 AnalysisContext addContext( |
119 Folder folder, UriResolver packageUriResolver, Packages packages); | |
110 | 120 |
111 /** | 121 /** |
112 * Called when the set of files associated with a context have changed (or | 122 * Called when the set of files associated with a context have changed (or |
113 * some of those files have been modified). [changeSet] is the set of | 123 * some of those files have been modified). [changeSet] is the set of |
114 * changes that need to be applied to the context. | 124 * changes that need to be applied to the context. |
115 */ | 125 */ |
116 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); | 126 void applyChangesToContext(Folder contextFolder, ChangeSet changeSet); |
117 | 127 |
118 /** | 128 /** |
119 * We are about to start computing the package map. | 129 * We are about to start computing the package map. |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
291 | 301 |
292 /** | 302 /** |
293 * Return `true` if the given [file] should be analyzed. | 303 * Return `true` if the given [file] should be analyzed. |
294 */ | 304 */ |
295 bool shouldFileBeAnalyzed(File file); | 305 bool shouldFileBeAnalyzed(File file); |
296 | 306 |
297 /** | 307 /** |
298 * Called when the package map for a context has changed. | 308 * Called when the package map for a context has changed. |
299 */ | 309 */ |
300 void updateContextPackageUriResolver( | 310 void updateContextPackageUriResolver( |
301 Folder contextFolder, UriResolver packageUriResolver); | 311 Folder contextFolder, UriResolver packageUriResolver, Packages packages); |
302 | 312 |
303 /** | 313 /** |
304 * Resursively adds all Dart and HTML files to the [changeSet]. | 314 * Resursively adds all Dart and HTML files to the [changeSet]. |
305 */ | 315 */ |
306 void _addPreviouslyExcludedSources(_ContextInfo info, ChangeSet changeSet, | 316 void _addPreviouslyExcludedSources(_ContextInfo info, ChangeSet changeSet, |
307 Folder folder, List<String> oldExcludedPaths) { | 317 Folder folder, List<String> oldExcludedPaths) { |
308 if (info.excludesResource(folder)) { | 318 if (info.excludesResource(folder)) { |
309 return; | 319 return; |
310 } | 320 } |
311 List<Resource> children; | 321 List<Resource> children; |
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
384 /** | 394 /** |
385 * Cancel all dependency subscriptions for the given context. | 395 * Cancel all dependency subscriptions for the given context. |
386 */ | 396 */ |
387 void _cancelDependencySubscriptions(_ContextInfo info) { | 397 void _cancelDependencySubscriptions(_ContextInfo info) { |
388 for (StreamSubscription<WatchEvent> s in info.dependencySubscriptions) { | 398 for (StreamSubscription<WatchEvent> s in info.dependencySubscriptions) { |
389 s.cancel(); | 399 s.cancel(); |
390 } | 400 } |
391 info.dependencySubscriptions.clear(); | 401 info.dependencySubscriptions.clear(); |
392 } | 402 } |
393 | 403 |
404 void _checkForPackagespecUpdate( | |
405 String path, _ContextInfo info, Folder folder) { | |
406 // Check to see if this is the .packages file for this context and if so, | |
407 // update the context's source factory. | |
408 if (pathContext.basename(path) == PACKAGE_SPEC_NAME && | |
409 info.isPathToPackageDescription(path)) { | |
410 File packagespec = resourceProvider.getFile(path); | |
411 if (packagespec.exists) { | |
412 Packages packages = _readPackagespec(packagespec); | |
413 updateContextPackageUriResolver(folder, null, packages); | |
414 } | |
415 } | |
416 } | |
417 | |
394 /** | 418 /** |
395 * Compute the appropriate package URI resolver for [folder], and store | 419 * Compute the appropriate package URI resolver for [folder], and store |
396 * dependency information in [info]. Return `null` if no package map can | 420 * dependency information in [info]. Return `null` if no package map can |
397 * be computed. | 421 * be computed. |
398 */ | 422 */ |
399 UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) { | 423 UriResolver _computePackageUriResolver(Folder folder, _ContextInfo info) { |
400 _cancelDependencySubscriptions(info); | 424 _cancelDependencySubscriptions(info); |
401 if (info.packageRoot != null) { | 425 if (info.packageRoot != null) { |
402 info.packageMapInfo = null; | 426 info.packageMapInfo = null; |
403 JavaFile packagesDir = new JavaFile(info.packageRoot); | 427 JavaFile packagesDir = new JavaFile(info.packageRoot); |
(...skipping 60 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
464 resourceProvider, packageMapInfo.packageMap); | 488 resourceProvider, packageMapInfo.packageMap); |
465 // TODO(paulberry): if any of the dependencies is outside of [folder], | 489 // TODO(paulberry): if any of the dependencies is outside of [folder], |
466 // we'll need to watch their parent folders as well. | 490 // we'll need to watch their parent folders as well. |
467 } | 491 } |
468 } | 492 } |
469 | 493 |
470 /** | 494 /** |
471 * Create a new empty context associated with [folder]. | 495 * Create a new empty context associated with [folder]. |
472 */ | 496 */ |
473 _ContextInfo _createContext( | 497 _ContextInfo _createContext( |
474 Folder folder, File pubspecFile, List<_ContextInfo> children) { | 498 Folder folder, File pubspecFile, List<_ContextInfo> children) { |
Brian Wilkerson
2015/07/17 18:02:57
Perhaps rename 'pubspecFile' to 'packageSpec' for
pquitslund
2015/07/17 19:30:02
Done.
| |
475 _ContextInfo info = new _ContextInfo( | 499 _ContextInfo info = new _ContextInfo( |
476 folder, pubspecFile, children, normalizedPackageRoots[folder.path]); | 500 folder, pubspecFile, children, normalizedPackageRoots[folder.path]); |
477 _contexts[folder] = info; | 501 _contexts[folder] = info; |
478 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 502 info.changeSubscription = folder.changes.listen((WatchEvent event) { |
479 _handleWatchEvent(folder, info, event); | 503 _handleWatchEvent(folder, info, event); |
480 }); | 504 }); |
481 try { | 505 try { |
482 UriResolver packageUriResolver = _computePackageUriResolver(folder, info); | 506 Packages packages; |
483 info.context = addContext(folder, packageUriResolver); | 507 UriResolver packageUriResolver; |
508 | |
509 // Try .packages first. | |
510 if (pathos.basename(pubspecFile.path) == PACKAGE_SPEC_NAME) { | |
511 packages = _readPackagespec(pubspecFile); | |
512 } | |
513 | |
514 // Next resort to a package uri resolver. | |
515 if (packages == null) { | |
516 packageUriResolver = _computePackageUriResolver(folder, info); | |
517 } | |
518 | |
519 info.context = addContext(folder, packageUriResolver, packages); | |
484 info.context.name = folder.path; | 520 info.context.name = folder.path; |
485 } catch (_) { | 521 } catch (_) { |
486 info.changeSubscription.cancel(); | 522 info.changeSubscription.cancel(); |
487 rethrow; | 523 rethrow; |
488 } | 524 } |
489 return info; | 525 return info; |
490 } | 526 } |
491 | 527 |
492 /** | 528 /** |
493 * Potentially create a new context associated with the given [folder]. | 529 * Potentially create a new context associated with the given [folder]. |
494 * | 530 * |
495 * If there are subfolders with 'pubspec.yaml' files, separate contexts are | 531 * If there are subfolders with 'pubspec.yaml' files, separate contexts are |
496 * created for them and excluded from the context associated with the | 532 * created for them and excluded from the context associated with the |
497 * [folder]. | 533 * [folder]. |
498 * | 534 * |
499 * If [withPubspecOnly] is `true`, a context will be created only if there | 535 * If [withPackageSpecOnly] is `true`, a context will be created only if there |
500 * is a 'pubspec.yaml' file in the [folder]. | 536 * is a 'pubspec.yaml' or '.packages' file in the [folder]. |
501 * | 537 * |
502 * Returns create pubspec-based contexts. | 538 * Returns created contexts. |
503 */ | 539 */ |
504 List<_ContextInfo> _createContexts(Folder folder, bool withPubspecOnly) { | 540 List<_ContextInfo> _createContexts(Folder folder, bool withPackageSpecOnly) { |
505 // try to find subfolders with pubspec files | 541 // Try to find subfolders with pubspecs or .packages files. |
506 List<_ContextInfo> children = <_ContextInfo>[]; | 542 List<_ContextInfo> children = <_ContextInfo>[]; |
507 try { | 543 try { |
508 for (Resource child in folder.getChildren()) { | 544 for (Resource child in folder.getChildren()) { |
509 if (child is Folder) { | 545 if (child is Folder) { |
510 children.addAll(_createContexts(child, true)); | 546 children.addAll(_createContexts(child, true)); |
511 } | 547 } |
512 } | 548 } |
513 } on FileSystemException { | 549 } on FileSystemException { |
514 // The directory either doesn't exist or cannot be read. Either way, there | 550 // The directory either doesn't exist or cannot be read. Either way, there |
515 // are no subfolders that need to be added. | 551 // are no subfolders that need to be added. |
516 } | 552 } |
517 // check whether there is a pubspec in the folder | 553 |
518 File pubspecFile = folder.getChild(PUBSPEC_NAME); | 554 // Start by looking for .packages. |
519 if (pubspecFile.exists) { | 555 File packageSpec = folder.getChild(PACKAGE_SPEC_NAME); |
556 | |
557 // Fall back to looking for a pubspec. | |
558 if (!packageSpec.exists) { | |
559 packageSpec = folder.getChild(PUBSPEC_NAME); | |
560 } | |
561 | |
562 if (packageSpec.exists) { | |
520 return <_ContextInfo>[ | 563 return <_ContextInfo>[ |
521 _createContextWithSources(folder, pubspecFile, children) | 564 _createContextWithSources(folder, packageSpec, children) |
522 ]; | 565 ]; |
523 } | 566 } |
524 // no pubspec, done | 567 // No packagespec? Done. |
525 if (withPubspecOnly) { | 568 if (withPackageSpecOnly) { |
526 return children; | 569 return children; |
527 } | 570 } |
528 // OK, create a context without a pubspec | 571 // OK, create a context without a packagespec. |
529 return <_ContextInfo>[ | 572 return <_ContextInfo>[ |
530 _createContextWithSources(folder, pubspecFile, children) | 573 _createContextWithSources(folder, packageSpec, children) |
531 ]; | 574 ]; |
532 } | 575 } |
533 | 576 |
534 /** | 577 /** |
535 * Create a new context associated with the given [folder]. The [pubspecFile] | 578 * Create a new context associated with the given [folder]. The [pubspecFile] |
536 * is the `pubspec.yaml` file contained in the folder. Add any sources that | 579 * is the `pubspec.yaml` file contained in the folder. Add any sources that |
537 * are not included in one of the [children] to the context. | 580 * are not included in one of the [children] to the context. |
538 */ | 581 */ |
539 _ContextInfo _createContextWithSources( | 582 _ContextInfo _createContextWithSources( |
540 Folder folder, File pubspecFile, List<_ContextInfo> children) { | 583 Folder folder, File pubspecFile, List<_ContextInfo> children) { |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
606 if (info.excludes(path)) { | 649 if (info.excludes(path)) { |
607 return; | 650 return; |
608 } | 651 } |
609 // handle the change | 652 // handle the change |
610 switch (event.type) { | 653 switch (event.type) { |
611 case ChangeType.ADD: | 654 case ChangeType.ADD: |
612 if (_isInPackagesDir(path, folder)) { | 655 if (_isInPackagesDir(path, folder)) { |
613 return; | 656 return; |
614 } | 657 } |
615 Resource resource = resourceProvider.getResource(path); | 658 Resource resource = resourceProvider.getResource(path); |
616 // pubspec was added in a sub-folder, extract a new context | 659 |
617 if (_isPubspec(path) && info.isRoot && !info.isPubspec(path)) { | 660 String directoryPath = pathContext.dirname(path); |
618 _extractContext(info, resource); | 661 |
619 return; | 662 // Check to see if we need to create a new context. |
663 if (info.isRoot) { | |
664 | |
665 // Only create a new context if this is not the same directory | |
666 // described by our info object. | |
667 if (info.folder.path != directoryPath) { | |
Brian Wilkerson
2015/07/17 18:02:57
If a .packages file is added to the context's root
pquitslund
2015/07/17 19:30:02
Actually, I think this is handled in _createContex
| |
668 if (pathContext.basename(path) == PUBSPEC_NAME) { | |
669 // Check for a sibling .packages file. | |
670 if (!resourceProvider | |
671 .getFile(pathos.join(directoryPath, '.packages')).exists) { | |
Brian Wilkerson
2015/07/17 18:02:58
nit: use PACKAGE_SPEC_NAME (here and below)
pquitslund
2015/07/17 19:30:02
Done.
| |
672 _extractContext(info, resource); | |
673 return; | |
674 } | |
675 } | |
676 if (pathContext.basename(path) == PACKAGE_SPEC_NAME) { | |
677 // Check for a sibling pubspec.yaml file. | |
678 if (!resourceProvider | |
679 .getFile(pathos.join(directoryPath, 'pubspec.yaml')).exists) { | |
Brian Wilkerson
2015/07/17 18:02:57
nit: use PUBSPEC_NAME (here and below)
pquitslund
2015/07/17 19:30:02
Done.
| |
680 _extractContext(info, resource); | |
681 return; | |
682 } | |
683 } | |
684 } | |
620 } | 685 } |
686 | |
621 // If the file went away and was replaced by a folder before we | 687 // If the file went away and was replaced by a folder before we |
622 // had a chance to process the event, resource might be a Folder. In | 688 // had a chance to process the event, resource might be a Folder. In |
623 // that case don't add it. | 689 // that case don't add it. |
624 if (resource is File) { | 690 if (resource is File) { |
625 File file = resource; | 691 File file = resource; |
626 if (shouldFileBeAnalyzed(file)) { | 692 if (shouldFileBeAnalyzed(file)) { |
627 ChangeSet changeSet = new ChangeSet(); | 693 ChangeSet changeSet = new ChangeSet(); |
628 Source source = createSourceInContext(info.context, file); | 694 Source source = createSourceInContext(info.context, file); |
629 changeSet.addedSource(source); | 695 changeSet.addedSource(source); |
630 applyChangesToContext(folder, changeSet); | 696 applyChangesToContext(folder, changeSet); |
631 info.sources[path] = source; | 697 info.sources[path] = source; |
632 } | 698 } |
633 } | 699 } |
634 break; | 700 break; |
635 case ChangeType.REMOVE: | 701 case ChangeType.REMOVE: |
636 // pubspec was removed, merge the context into its parent | 702 |
637 if (info.isPubspec(path) && !info.isRoot) { | 703 // If package spec info is removed, check to see if we can merge context s. |
638 _mergeContext(info); | 704 // Note that it's important to verify that there is NEITHER a .packages nor a |
639 return; | 705 // lingering pubspec.yaml before merging. |
706 if (!info.isRoot) { | |
707 String directoryPath = pathContext.dirname(path); | |
708 | |
709 // Only merge if this is the same directory described by our info obje ct. | |
710 if (info.folder.path == directoryPath) { | |
711 if (pathContext.basename(path) == PUBSPEC_NAME) { | |
712 // Check for a sibling .packages file. | |
713 if (!resourceProvider | |
714 .getFile(pathos.join(directoryPath, '.packages')).exists) { | |
715 _mergeContext(info); | |
716 return; | |
717 } | |
718 } | |
719 if (pathContext.basename(path) == PACKAGE_SPEC_NAME) { | |
720 // Check for a sibling pubspec.yaml file. | |
721 if (!resourceProvider | |
722 .getFile(pathos.join(directoryPath, 'pubspec.yaml')).exists) { | |
723 _mergeContext(info); | |
724 return; | |
725 } | |
726 } | |
727 } | |
640 } | 728 } |
729 | |
641 List<Source> sources = info.context.getSourcesWithFullName(path); | 730 List<Source> sources = info.context.getSourcesWithFullName(path); |
642 if (!sources.isEmpty) { | 731 if (!sources.isEmpty) { |
643 ChangeSet changeSet = new ChangeSet(); | 732 ChangeSet changeSet = new ChangeSet(); |
644 sources.forEach((Source source) { | 733 sources.forEach((Source source) { |
645 changeSet.removedSource(source); | 734 changeSet.removedSource(source); |
646 }); | 735 }); |
647 applyChangesToContext(folder, changeSet); | 736 applyChangesToContext(folder, changeSet); |
648 info.sources.remove(path); | 737 info.sources.remove(path); |
649 } | 738 } |
650 break; | 739 break; |
651 case ChangeType.MODIFY: | 740 case ChangeType.MODIFY: |
Brian Wilkerson
2015/07/17 18:02:57
Do we handle changes to the .packages file somewhe
pquitslund
2015/07/17 19:30:02
Yes. That's outside the switch. (See below.)
Ce
| |
652 List<Source> sources = info.context.getSourcesWithFullName(path); | 741 List<Source> sources = info.context.getSourcesWithFullName(path); |
653 if (!sources.isEmpty) { | 742 if (!sources.isEmpty) { |
654 ChangeSet changeSet = new ChangeSet(); | 743 ChangeSet changeSet = new ChangeSet(); |
655 sources.forEach((Source source) { | 744 sources.forEach((Source source) { |
656 changeSet.changedSource(source); | 745 changeSet.changedSource(source); |
657 }); | 746 }); |
658 applyChangesToContext(folder, changeSet); | 747 applyChangesToContext(folder, changeSet); |
659 } | 748 } |
660 break; | 749 break; |
661 } | 750 } |
662 | 751 |
752 //TODO(pquitslund): find the right place for this | |
753 _checkForPackagespecUpdate(path, info, folder); | |
pquitslund
2015/07/17 19:30:02
Here's where we test for .packages changes.
| |
754 | |
663 if (info.packageMapInfo != null && | 755 if (info.packageMapInfo != null && |
664 info.packageMapInfo.isChangedDependency(path, resourceProvider)) { | 756 info.packageMapInfo.isChangedDependency(path, resourceProvider)) { |
665 _recomputePackageUriResolver(info); | 757 _recomputePackageUriResolver(info); |
666 } | 758 } |
667 } | 759 } |
668 | 760 |
669 /** | 761 /** |
670 * Returns `true` if the given [path] is excluded by [excludedPaths]. | 762 * Returns `true` if the given [path] is excluded by [excludedPaths]. |
671 */ | 763 */ |
672 bool _isExcluded(String path) { | 764 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path); |
673 return _isExcludedBy(excludedPaths, path); | |
674 } | |
675 | 765 |
676 /** | 766 /** |
677 * Returns `true` if the given [path] is excluded by [excludedPaths]. | 767 * Returns `true` if the given [path] is excluded by [excludedPaths]. |
678 */ | 768 */ |
679 bool _isExcludedBy(List<String> excludedPaths, String path) { | 769 bool _isExcludedBy(List<String> excludedPaths, String path) { |
680 return excludedPaths.any((excludedPath) { | 770 return excludedPaths.any((excludedPath) { |
681 if (pathContext.isWithin(excludedPath, path)) { | 771 if (pathContext.isWithin(excludedPath, path)) { |
682 return true; | 772 return true; |
683 } | 773 } |
684 return path == excludedPath; | 774 return path == excludedPath; |
685 }); | 775 }); |
686 } | 776 } |
687 | 777 |
688 /** | 778 /** |
689 * Determine if the path from [folder] to [path] contains a 'packages' | 779 * Determine if the path from [folder] to [path] contains a 'packages' |
690 * directory. | 780 * directory. |
691 */ | 781 */ |
692 bool _isInPackagesDir(String path, Folder folder) { | 782 bool _isInPackagesDir(String path, Folder folder) { |
693 String relativePath = pathContext.relative(path, from: folder.path); | 783 String relativePath = pathContext.relative(path, from: folder.path); |
694 List<String> pathParts = pathContext.split(relativePath); | 784 List<String> pathParts = pathContext.split(relativePath); |
695 return pathParts.contains(PACKAGES_NAME); | 785 return pathParts.contains(PACKAGES_NAME); |
696 } | 786 } |
697 | 787 |
698 /** | 788 /** |
699 * Returns `true` if the given absolute [path] is a pubspec file. | |
700 */ | |
701 bool _isPubspec(String path) { | |
702 return pathContext.basename(path) == PUBSPEC_NAME; | |
703 } | |
704 | |
705 /** | |
706 * Merges [info] context into its parent. | 789 * Merges [info] context into its parent. |
707 */ | 790 */ |
708 void _mergeContext(_ContextInfo info) { | 791 void _mergeContext(_ContextInfo info) { |
709 // destroy the context | 792 // destroy the context |
710 _destroyContext(info.folder); | 793 _destroyContext(info.folder); |
711 // add files to the parent context | 794 // add files to the parent context |
712 _ContextInfo parentInfo = info.parent; | 795 _ContextInfo parentInfo = info.parent; |
713 if (parentInfo != null) { | 796 if (parentInfo != null) { |
714 parentInfo.children.remove(info); | 797 parentInfo.children.remove(info); |
715 ChangeSet changeSet = new ChangeSet(); | 798 ChangeSet changeSet = new ChangeSet(); |
716 info.sources.forEach((path, source) { | 799 info.sources.forEach((path, source) { |
717 parentInfo.sources[path] = source; | 800 parentInfo.sources[path] = source; |
718 changeSet.addedSource(source); | 801 changeSet.addedSource(source); |
719 }); | 802 }); |
720 applyChangesToContext(parentInfo.folder, changeSet); | 803 applyChangesToContext(parentInfo.folder, changeSet); |
721 } | 804 } |
722 } | 805 } |
723 | 806 |
807 Packages _readPackagespec(File specFile) { | |
808 //TODO(pquitslund): error-handling? | |
Brian Wilkerson
2015/07/17 18:02:57
Yes. If we cannot read the file, I think we should
pquitslund
2015/07/17 19:30:02
Cool. Added a try/catch and a TODO to create an e
| |
809 String contents = specFile.readAsStringSync(); | |
810 Map<String, Uri> map = | |
811 pkgfile.parse(UTF8.encode(contents), new Uri.file(specFile.path)); | |
812 return new MapPackages(map); | |
813 } | |
814 | |
724 /** | 815 /** |
725 * Recompute the package URI resolver for the context described by [info], | 816 * Recompute the package URI resolver for the context described by [info], |
726 * and update the client appropriately. | 817 * and update the client appropriately. |
727 */ | 818 */ |
728 void _recomputePackageUriResolver(_ContextInfo info) { | 819 void _recomputePackageUriResolver(_ContextInfo info) { |
729 // TODO(paulberry): when computePackageMap is changed into an | 820 // TODO(paulberry): when computePackageMap is changed into an |
730 // asynchronous API call, we'll want to suspend analysis for this context | 821 // asynchronous API call, we'll want to suspend analysis for this context |
731 // while we're rerunning "pub list", since any analysis we complete while | 822 // while we're rerunning "pub list", since any analysis we complete while |
732 // "pub list" is in progress is just going to get thrown away anyhow. | 823 // "pub list" is in progress is just going to get thrown away anyhow. |
733 UriResolver packageUriResolver = | 824 UriResolver packageUriResolver = |
734 _computePackageUriResolver(info.folder, info); | 825 _computePackageUriResolver(info.folder, info); |
735 updateContextPackageUriResolver(info.folder, packageUriResolver); | 826 updateContextPackageUriResolver(info.folder, packageUriResolver, null); |
736 } | 827 } |
737 | 828 |
738 /** | 829 /** |
739 * Create and return a source representing the given [file] within the given | 830 * Create and return a source representing the given [file] within the given |
740 * [context]. | 831 * [context]. |
741 */ | 832 */ |
742 static Source createSourceInContext(AnalysisContext context, File file) { | 833 static Source createSourceInContext(AnalysisContext context, File file) { |
743 // TODO(brianwilkerson) Optimize this, by allowing support for source | 834 // TODO(brianwilkerson) Optimize this, by allowing support for source |
744 // factories to restore URI's from a file path rather than a source. | 835 // factories to restore URI's from a file path rather than a source. |
745 Source source = file.createSource(); | 836 Source source = file.createSource(); |
(...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
868 * The package root for this context, or null if there is no package root. | 959 * The package root for this context, or null if there is no package root. |
869 */ | 960 */ |
870 String packageRoot; | 961 String packageRoot; |
871 | 962 |
872 /** | 963 /** |
873 * The [_ContextInfo] that encloses this one. | 964 * The [_ContextInfo] that encloses this one. |
874 */ | 965 */ |
875 _ContextInfo parent; | 966 _ContextInfo parent; |
876 | 967 |
877 /** | 968 /** |
878 * The `pubspec.yaml` file path for this context. | 969 * The package description file path for this context. |
879 */ | 970 */ |
880 String pubspecPath; | 971 String packageDescriptionPath; |
881 | 972 |
882 /** | 973 /** |
883 * Stream subscription we are using to watch the context's directory for | 974 * Stream subscription we are using to watch the context's directory for |
884 * changes. | 975 * changes. |
885 */ | 976 */ |
886 StreamSubscription<WatchEvent> changeSubscription; | 977 StreamSubscription<WatchEvent> changeSubscription; |
887 | 978 |
888 /** | 979 /** |
889 * Stream subscriptions we are using to watch the files | 980 * Stream subscriptions we are using to watch the files |
890 * used to determine the package map. | 981 * used to determine the package map. |
(...skipping 13 matching lines...) Expand all Loading... | |
904 Map<String, Source> sources = new HashMap<String, Source>(); | 995 Map<String, Source> sources = new HashMap<String, Source>(); |
905 | 996 |
906 /** | 997 /** |
907 * Info returned by the last call to | 998 * Info returned by the last call to |
908 * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the | 999 * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the |
909 * package map hasn't been computed for this context yet. | 1000 * package map hasn't been computed for this context yet. |
910 */ | 1001 */ |
911 OptimizingPubPackageMapInfo packageMapInfo; | 1002 OptimizingPubPackageMapInfo packageMapInfo; |
912 | 1003 |
913 _ContextInfo(this.folder, File pubspecFile, this.children, this.packageRoot) { | 1004 _ContextInfo(this.folder, File pubspecFile, this.children, this.packageRoot) { |
914 pubspecPath = pubspecFile.path; | 1005 packageDescriptionPath = pubspecFile.path; |
915 for (_ContextInfo child in children) { | 1006 for (_ContextInfo child in children) { |
916 child.parent = this; | 1007 child.parent = this; |
917 } | 1008 } |
918 } | 1009 } |
919 | 1010 |
920 /** | 1011 /** |
921 * Returns `true` if this context is root folder based. | 1012 * Returns `true` if this context is root folder based. |
922 */ | 1013 */ |
923 bool get isRoot => parent == null; | 1014 bool get isRoot => parent == null; |
924 | 1015 |
925 /** | 1016 /** |
926 * Returns `true` if [path] is excluded, as it is in one of the children. | 1017 * Returns `true` if [path] is excluded, as it is in one of the children. |
927 */ | 1018 */ |
928 bool excludes(String path) { | 1019 bool excludes(String path) { |
929 return children.any((child) { | 1020 return children.any((child) { |
930 return child.folder.contains(path); | 1021 return child.folder.contains(path); |
931 }); | 1022 }); |
932 } | 1023 } |
933 | 1024 |
934 /** | 1025 /** |
935 * Returns `true` if [resource] is excluded, as it is in one of the children. | 1026 * Returns `true` if [resource] is excluded, as it is in one of the children. |
936 */ | 1027 */ |
937 bool excludesResource(Resource resource) { | 1028 bool excludesResource(Resource resource) => excludes(resource.path); |
938 return excludes(resource.path); | |
939 } | |
940 | 1029 |
941 /** | 1030 /** |
942 * Returns `true` if [path] is the pubspec file of this context. | 1031 * Returns `true` if [path] is the package description file for this context |
1032 * (pubspec.yaml or .packages). | |
943 */ | 1033 */ |
944 bool isPubspec(String path) { | 1034 bool isPathToPackageDescription(String path) => |
945 return path == pubspecPath; | 1035 path == packageDescriptionPath; |
946 } | |
947 } | 1036 } |
OLD | NEW |