Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(108)

Side by Side Diff: pkg/analysis_server/lib/src/context_manager.dart

Issue 1257933002: Convert ContextManager to recursively watch analysis roots. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | pkg/analysis_server/test/context_manager_test.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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:convert';
10 import 'dart:core' hide Resource; 10 import 'dart:core' hide Resource;
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 * objects. 62 * objects.
63 */ 63 */
64 ContextInfo parent; 64 ContextInfo parent;
65 65
66 /** 66 /**
67 * The package description file path for this context. 67 * The package description file path for this context.
68 */ 68 */
69 String packageDescriptionPath; 69 String packageDescriptionPath;
70 70
71 /** 71 /**
72 * Stream subscription we are using to watch the context's directory for 72 * Paths to files which determine the folder disposition and package map.
73 * changes. 73 *
74 * TODO(paulberry): if any of these files are outside of [folder], they won't
75 * be watched for changes. I believe the use case for watching these files
76 * is no longer relevant.
74 */ 77 */
75 StreamSubscription<WatchEvent> changeSubscription; 78 Set<String> _dependencies = new Set<String>();
76
77 /**
78 * Stream subscriptions we are using to watch the files
79 * used to determine the package map. Organized as a map from path to
80 * subscription.
81 *
82 * For paths that are inside [folder], the subscription is null, since the
83 * entire contents of the folder are automatically being watched.
84 */
85 final Map<String, StreamSubscription<WatchEvent>> _dependencySubscriptions =
86 <String, StreamSubscription<WatchEvent>>{};
87 79
88 /** 80 /**
89 * The analysis context that was created for the [folder]. 81 * The analysis context that was created for the [folder].
90 */ 82 */
91 AnalysisContext context; 83 AnalysisContext context;
92 84
93 /** 85 /**
94 * Map from full path to the [Source] object, for each source that has been 86 * Map from full path to the [Source] object, for each source that has been
95 * added to the context. 87 * added to the context.
96 */ 88 */
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
154 return info; 146 return info;
155 } 147 }
156 } 148 }
157 return null; 149 return null;
158 } 150 }
159 151
160 /** 152 /**
161 * Determine if the given [path] is one of the dependencies most recently 153 * Determine if the given [path] is one of the dependencies most recently
162 * passed to [setDependencies]. 154 * passed to [setDependencies].
163 */ 155 */
164 bool hasDependency(String path) => _dependencySubscriptions.containsKey(path); 156 bool hasDependency(String path) => _dependencies.contains(path);
165 157
166 /// Returns `true` if [path] should be ignored. 158 /// Returns `true` if [path] should be ignored.
167 bool ignored(String path) => pathFilter.ignored(path); 159 bool ignored(String path) => pathFilter.ignored(path);
168 160
169 /** 161 /**
170 * Returns `true` if [path] is the package description file for this context 162 * Returns `true` if [path] is the package description file for this context
171 * (pubspec.yaml or .packages). 163 * (pubspec.yaml or .packages).
172 */ 164 */
173 bool isPathToPackageDescription(String path) => 165 bool isPathToPackageDescription(String path) =>
174 path == packageDescriptionPath; 166 path == packageDescriptionPath;
175 167
176 /** 168 /**
177 * Update the set of dependencies for this context. Watchers are 169 * Update the set of dependencies for this context.
178 * automatically set up for the dependencies (if necessary) to ensure that
179 * [ContextManagerImpl._handleWatchEvent] is called when they are modified.
180 */ 170 */
181 void setDependencies(Iterable<String> newDependencies) { 171 void setDependencies(Iterable<String> newDependencies) {
182 for (String oldDependency in _dependencySubscriptions.keys.toList()) { 172 _dependencies = newDependencies.toSet();
183 if (!newDependencies.contains(oldDependency)) {
184 StreamSubscription<WatchEvent> subscription =
185 _dependencySubscriptions[oldDependency];
186 if (subscription != null) {
187 subscription.cancel();
188 }
189 _dependencySubscriptions.remove(oldDependency);
190 }
191 }
192 for (String newDependency in newDependencies) {
193 if (!_dependencySubscriptions.containsKey(newDependency)) {
194 StreamSubscription<WatchEvent> subscription;
195 if (!folder.contains(newDependency)) {
196 Resource resource =
197 contextManager.resourceProvider.getResource(newDependency);
198 if (resource is File) {
199 subscription = resource.changes.listen((WatchEvent event) {
200 contextManager._handleWatchEvent(folder, this, event);
201 }, onError: (error, StackTrace stackTrace) {
202 // Gracefully degrade if file is or becomes unwatchable
203 contextManager._instrumentationService.logException(
204 error, stackTrace);
205 subscription.cancel();
206 _dependencySubscriptions[newDependency] = null;
207 });
208 }
209 }
210 _dependencySubscriptions[newDependency] = subscription;
211 }
212 }
213 } 173 }
214 } 174 }
215 175
216 /** 176 /**
217 * Class that maintains a mapping from included/excluded paths to a set of 177 * Class that maintains a mapping from included/excluded paths to a set of
218 * folders that should correspond to analysis contexts. 178 * folders that should correspond to analysis contexts.
219 */ 179 */
220 abstract class ContextManager { 180 abstract class ContextManager {
221 // TODO(brianwilkerson) Support: 181 // TODO(brianwilkerson) Support:
222 // setting the default analysis options 182 // setting the default analysis options
(...skipping 203 matching lines...) Expand 10 before | Expand all | Expand 10 after
426 386
427 @override 387 @override
428 ContextManagerCallbacks callbacks; 388 ContextManagerCallbacks callbacks;
429 389
430 /** 390 /**
431 * Virtual [ContextInfo] which acts as the ancestor of all other 391 * Virtual [ContextInfo] which acts as the ancestor of all other
432 * [ContextInfo]s. 392 * [ContextInfo]s.
433 */ 393 */
434 final ContextInfo _rootInfo = new ContextInfo._root(); 394 final ContextInfo _rootInfo = new ContextInfo._root();
435 395
396 /**
397 * Stream subscription we are using to watch each analysis root directory for
398 * changes.
399 */
400 final Map<Folder, StreamSubscription<WatchEvent>> _changeSubscriptions =
401 <Folder, StreamSubscription<WatchEvent>>{};
402
436 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider, 403 ContextManagerImpl(this.resourceProvider, this.packageResolverProvider,
437 this._packageMapProvider, this._instrumentationService) { 404 this._packageMapProvider, this._instrumentationService) {
438 pathContext = resourceProvider.pathContext; 405 pathContext = resourceProvider.pathContext;
439 } 406 }
440 407
441 @override 408 @override
442 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) { 409 List<AnalysisContext> contextsInAnalysisRoot(Folder analysisRoot) {
443 List<AnalysisContext> contexts = <AnalysisContext>[]; 410 List<AnalysisContext> contexts = <AnalysisContext>[];
444 ContextInfo innermostContainingInfo = 411 ContextInfo innermostContainingInfo =
445 _getInnermostContextInfoFor(analysisRoot.path); 412 _getInnermostContextInfoFor(analysisRoot.path);
(...skipping 138 matching lines...) Expand 10 before | Expand all | Expand 10 after
584 info.packageRoot = newPackageRoot; 551 info.packageRoot = newPackageRoot;
585 _recomputeFolderDisposition(info); 552 _recomputeFolderDisposition(info);
586 } 553 }
587 } 554 }
588 // create new contexts 555 // create new contexts
589 for (Folder includedFolder in includedFolders) { 556 for (Folder includedFolder in includedFolders) {
590 bool wasIncluded = contextInfos.any((info) { 557 bool wasIncluded = contextInfos.any((info) {
591 return info.folder.isOrContains(includedFolder.path); 558 return info.folder.isOrContains(includedFolder.path);
592 }); 559 });
593 if (!wasIncluded) { 560 if (!wasIncluded) {
561 _changeSubscriptions[includedFolder] =
562 includedFolder.changes.listen(_handleWatchEvent);
594 _createContexts(_rootInfo, includedFolder, false); 563 _createContexts(_rootInfo, includedFolder, false);
595 } 564 }
596 } 565 }
597 // remove newly excluded sources 566 // remove newly excluded sources
598 for (ContextInfo info in _rootInfo.descendants) { 567 for (ContextInfo info in _rootInfo.descendants) {
599 // prepare excluded sources 568 // prepare excluded sources
600 Map<String, Source> excludedSources = new HashMap<String, Source>(); 569 Map<String, Source> excludedSources = new HashMap<String, Source>();
601 info.sources.forEach((String path, Source source) { 570 info.sources.forEach((String path, Source source) {
602 if (_isExcludedBy(excludedPaths, path) && 571 if (_isExcludedBy(excludedPaths, path) &&
603 !_isExcludedBy(oldExcludedPaths, path)) { 572 !_isExcludedBy(oldExcludedPaths, path)) {
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after
699 } else if (child is Folder) { 668 } else if (child is Folder) {
700 String shortName = child.shortName; 669 String shortName = child.shortName;
701 if (shortName == PACKAGES_NAME) { 670 if (shortName == PACKAGES_NAME) {
702 continue; 671 continue;
703 } 672 }
704 _addSourceFiles(changeSet, child, info); 673 _addSourceFiles(changeSet, child, info);
705 } 674 }
706 } 675 }
707 } 676 }
708 677
709 /**
710 * Cancel all dependency subscriptions for the given context.
711 */
712 void _cancelDependencySubscriptions(ContextInfo info) {
713 info.setDependencies(const <String>[]);
714 }
715
716 void _checkForPackagespecUpdate( 678 void _checkForPackagespecUpdate(
717 String path, ContextInfo info, Folder folder) { 679 String path, ContextInfo info, Folder folder) {
718 // Check to see if this is the .packages file for this context and if so, 680 // Check to see if this is the .packages file for this context and if so,
719 // update the context's source factory. 681 // update the context's source factory.
720 if (pathContext.basename(path) == PACKAGE_SPEC_NAME && 682 if (pathContext.basename(path) == PACKAGE_SPEC_NAME &&
721 info.isPathToPackageDescription(path)) { 683 info.isPathToPackageDescription(path)) {
722 File packagespec = resourceProvider.getFile(path); 684 File packagespec = resourceProvider.getFile(path);
723 if (packagespec.exists) { 685 if (packagespec.exists) {
724 Packages packages = _readPackagespec(packagespec); 686 Packages packages = _readPackagespec(packagespec);
725 if (packages != null) { 687 if (packages != null) {
(...skipping 21 matching lines...) Expand all
747 if (context != contextN) { 709 if (context != contextN) {
748 for (Source source in contextN.sources) { 710 for (Source source in contextN.sources) {
749 flushedFiles.remove(source.fullName); 711 flushedFiles.remove(source.fullName);
750 } 712 }
751 } 713 }
752 } 714 }
753 return flushedFiles.toList(growable: false); 715 return flushedFiles.toList(growable: false);
754 } 716 }
755 717
756 /** 718 /**
757 * Compute the appropriate [FolderDisposition] for [info]. Use 719 * Compute the appropriate [FolderDisposition] for [folder]. Use
758 * [addDependency] to indicate which files needed to be consulted in order to 720 * [addDependency] to indicate which files needed to be consulted in order to
759 * figure out the [FolderDisposition]; these dependencies will be watched in 721 * figure out the [FolderDisposition]; these dependencies will be watched in
760 * order to determine when it is necessary to call this function again. 722 * order to determine when it is necessary to call this function again.
761 * 723 *
762 * TODO(paulberry): use [addDependency] for tracking all folder disposition 724 * TODO(paulberry): use [addDependency] for tracking all folder disposition
763 * dependencies (currently we only use it to track "pub list" dependencies). 725 * dependencies (currently we only use it to track "pub list" dependencies).
764 */ 726 */
765 FolderDisposition _computeFolderDisposition( 727 FolderDisposition _computeFolderDisposition(
766 Folder folder, ContextInfo info, void addDependency(String path)) { 728 Folder folder, void addDependency(String path)) {
767 if (info.packageRoot != null) { 729 String packageRoot = normalizedPackageRoots[folder.path];
730 if (packageRoot != null) {
768 // TODO(paulberry): We shouldn't be using JavaFile here because it 731 // TODO(paulberry): We shouldn't be using JavaFile here because it
769 // makes the code untestable (see dartbug.com/23909). 732 // makes the code untestable (see dartbug.com/23909).
770 JavaFile packagesDir = new JavaFile(info.packageRoot); 733 JavaFile packagesDir = new JavaFile(packageRoot);
771 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>(); 734 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>();
772 if (packagesDir.isDirectory()) { 735 if (packagesDir.isDirectory()) {
773 for (JavaFile file in packagesDir.listFiles()) { 736 for (JavaFile file in packagesDir.listFiles()) {
774 // Ensure symlinks in packages directory are canonicalized 737 // Ensure symlinks in packages directory are canonicalized
775 // to prevent 'type X cannot be assigned to type X' warnings 738 // to prevent 'type X cannot be assigned to type X' warnings
776 String path; 739 String path;
777 try { 740 try {
778 path = file.getCanonicalPath(); 741 path = file.getCanonicalPath();
779 } catch (e, s) { 742 } catch (e, s) {
780 // Ignore packages that do not exist 743 // Ignore packages that do not exist
781 _instrumentationService.logException(e, s); 744 _instrumentationService.logException(e, s);
782 continue; 745 continue;
783 } 746 }
784 Resource res = resourceProvider.getResource(path); 747 Resource res = resourceProvider.getResource(path);
785 if (res is Folder) { 748 if (res is Folder) {
786 packageMap[file.getName()] = <Folder>[res]; 749 packageMap[file.getName()] = <Folder>[res];
787 } 750 }
788 } 751 }
789 return new PackageMapDisposition(packageMap, 752 return new PackageMapDisposition(packageMap, packageRoot: packageRoot);
790 packageRoot: info.packageRoot);
791 } 753 }
792 // The package root does not exist (or is not a folder). Since 754 // The package root does not exist (or is not a folder). Since
793 // [setRoots] ignores any package roots that don't exist (or aren't 755 // [setRoots] ignores any package roots that don't exist (or aren't
794 // folders), the only way we should be able to get here is due to a race 756 // folders), the only way we should be able to get here is due to a race
795 // condition. In any case, the package root folder is gone, so we can't 757 // condition. In any case, the package root folder is gone, so we can't
796 // resolve packages. 758 // resolve packages.
797 return new NoPackageFolderDisposition(packageRoot: info.packageRoot); 759 return new NoPackageFolderDisposition(packageRoot: packageRoot);
798 } else { 760 } else {
799 callbacks.beginComputePackageMap(); 761 callbacks.beginComputePackageMap();
800 if (packageResolverProvider != null) { 762 if (packageResolverProvider != null) {
801 UriResolver resolver = packageResolverProvider(folder); 763 UriResolver resolver = packageResolverProvider(folder);
802 if (resolver != null) { 764 if (resolver != null) {
803 return new CustomPackageResolverDisposition(resolver); 765 return new CustomPackageResolverDisposition(resolver);
804 } 766 }
805 } 767 }
806 PackageMapInfo packageMapInfo; 768 PackageMapInfo packageMapInfo;
807 ServerPerformanceStatistics.pub.makeCurrentWhile(() { 769 ServerPerformanceStatistics.pub.makeCurrentWhile(() {
(...skipping 13 matching lines...) Expand all
821 /** 783 /**
822 * Create a new empty context associated with [folder], having parent 784 * Create a new empty context associated with [folder], having parent
823 * [parent] and using [packagespecFile] to resolve package URI's. 785 * [parent] and using [packagespecFile] to resolve package URI's.
824 */ 786 */
825 ContextInfo _createContext( 787 ContextInfo _createContext(
826 ContextInfo parent, Folder folder, File packagespecFile) { 788 ContextInfo parent, Folder folder, File packagespecFile) {
827 ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile, 789 ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile,
828 normalizedPackageRoots[folder.path]); 790 normalizedPackageRoots[folder.path]);
829 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); 791 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder);
830 processOptionsForContext(info, options); 792 processOptionsForContext(info, options);
831 info.changeSubscription = folder.changes.listen((WatchEvent event) { 793 FolderDisposition disposition;
832 _handleWatchEvent(folder, info, event); 794 List<String> dependencies = <String>[];
833 });
834 try {
835 FolderDisposition disposition;
836 List<String> dependencies = <String>[];
837 795
838 if (ENABLE_PACKAGESPEC_SUPPORT) { 796 if (ENABLE_PACKAGESPEC_SUPPORT) {
839 // Try .packages first. 797 // Try .packages first.
840 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { 798 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) {
841 Packages packages = _readPackagespec(packagespecFile); 799 Packages packages = _readPackagespec(packagespecFile);
842 disposition = new PackagesFileDisposition(packages); 800 disposition = new PackagesFileDisposition(packages);
843 }
844 } 801 }
802 }
845 803
846 // Next resort to a package uri resolver. 804 // Next resort to a package uri resolver.
847 if (disposition == null) { 805 if (disposition == null) {
848 disposition = _computeFolderDisposition(folder, info, dependencies.add); 806 disposition = _computeFolderDisposition(folder, dependencies.add);
849 } 807 }
850 808
851 info.setDependencies(dependencies); 809 info.setDependencies(dependencies);
852 info.context = callbacks.addContext(folder, disposition); 810 info.context = callbacks.addContext(folder, disposition);
853 info.context.name = folder.path; 811 info.context.name = folder.path;
854 } catch (_) {
855 info.changeSubscription.cancel();
856 rethrow;
857 }
858 return info; 812 return info;
859 } 813 }
860 814
861 /** 815 /**
862 * Potentially create a new context associated with the given [folder]. 816 * Potentially create a new context associated with the given [folder].
863 * 817 *
864 * If there are subfolders with 'pubspec.yaml' files, separate contexts are 818 * If there are subfolders with 'pubspec.yaml' files, separate contexts are
865 * created for them and excluded from the context associated with the 819 * created for them and excluded from the context associated with the
866 * [folder]. 820 * [folder].
867 * 821 *
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after
910 ChangeSet changeSet = new ChangeSet(); 864 ChangeSet changeSet = new ChangeSet();
911 _addSourceFiles(changeSet, folder, parent); 865 _addSourceFiles(changeSet, folder, parent);
912 callbacks.applyChangesToContext(folder, changeSet); 866 callbacks.applyChangesToContext(folder, changeSet);
913 } 867 }
914 } 868 }
915 869
916 /** 870 /**
917 * Clean up and destroy the context associated with the given folder. 871 * Clean up and destroy the context associated with the given folder.
918 */ 872 */
919 void _destroyContext(ContextInfo info) { 873 void _destroyContext(ContextInfo info) {
920 info.changeSubscription.cancel(); 874 if (_changeSubscriptions.containsKey(info.folder)) {
921 _cancelDependencySubscriptions(info); 875 _changeSubscriptions[info.folder].cancel();
876 }
922 callbacks.removeContext(info.folder, _computeFlushedFiles(info)); 877 callbacks.removeContext(info.folder, _computeFlushedFiles(info));
923 bool wasRemoved = info.parent.children.remove(info); 878 bool wasRemoved = info.parent.children.remove(info);
924 assert(wasRemoved); 879 assert(wasRemoved);
925 } 880 }
926 881
927 /** 882 /**
928 * Extract a new [packagespecFile]-based context from [oldInfo]. 883 * Extract a new [packagespecFile]-based context from [oldInfo].
929 */ 884 */
930 void _extractContext(ContextInfo oldInfo, File packagespecFile) { 885 void _extractContext(ContextInfo oldInfo, File packagespecFile) {
931 Folder newFolder = packagespecFile.parent; 886 Folder newFolder = packagespecFile.parent;
(...skipping 44 matching lines...) Expand 10 before | Expand all | Expand 10 after
976 } 931 }
977 while (true) { 932 while (true) {
978 ContextInfo childInfo = info.findChildInfoFor(path); 933 ContextInfo childInfo = info.findChildInfoFor(path);
979 if (childInfo == null) { 934 if (childInfo == null) {
980 return info; 935 return info;
981 } 936 }
982 info = childInfo; 937 info = childInfo;
983 } 938 }
984 } 939 }
985 940
986 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { 941 void _handleWatchEvent(WatchEvent event) {
942 // Figure out which context this event applies to.
987 // TODO(brianwilkerson) If a file is explicitly included in one context 943 // TODO(brianwilkerson) If a file is explicitly included in one context
988 // but implicitly referenced in another context, we will only send a 944 // but implicitly referenced in another context, we will only send a
989 // changeSet to the context that explicitly includes the file (because 945 // changeSet to the context that explicitly includes the file (because
990 // that's the only context that's watching the file). 946 // that's the only context that's watching the file).
947 ContextInfo info = _getInnermostContextInfoFor(event.path);
948 if (info == null) {
949 // This event doesn't apply to any context. This could happen due to a
950 // race condition (e.g. a context was removed while one of its events was
951 // in the event loop). The event is inapplicable now, so just ignore it.
952 return;
953 }
991 _instrumentationService.logWatchEvent( 954 _instrumentationService.logWatchEvent(
992 folder.path, event.path, event.type.toString()); 955 info.folder.path, event.path, event.type.toString());
993 String path = event.path; 956 String path = event.path;
994 // First handle changes that affect folderDisposition (since these need to 957 // First handle changes that affect folderDisposition (since these need to
995 // be processed regardless of whether they are part of an excluded/ignored 958 // be processed regardless of whether they are part of an excluded/ignored
996 // path). 959 // path).
997 if (info.hasDependency(path)) { 960 if (info.hasDependency(path)) {
998 _recomputeFolderDisposition(info); 961 _recomputeFolderDisposition(info);
999 } 962 }
1000 // maybe excluded globally 963 // maybe excluded globally
1001 if (_isExcluded(path)) { 964 if (_isExcluded(path)) {
1002 return; 965 return;
1003 } 966 }
1004 // maybe excluded from the context, so other context will handle it 967 // maybe excluded from the context, so other context will handle it
1005 if (info.excludes(path)) { 968 if (info.excludes(path)) {
1006 return; 969 return;
1007 } 970 }
1008 if (info.ignored(path)) { 971 if (info.ignored(path)) {
1009 return; 972 return;
1010 } 973 }
1011 // handle the change 974 // handle the change
1012 switch (event.type) { 975 switch (event.type) {
1013 case ChangeType.ADD: 976 case ChangeType.ADD:
1014 if (_isInPackagesDir(path, folder)) { 977 if (_isInPackagesDir(path, info.folder)) {
1015 return; 978 return;
1016 } 979 }
1017 980
1018 Resource resource = resourceProvider.getResource(path); 981 Resource resource = resourceProvider.getResource(path);
1019 982
1020 if (ENABLE_PACKAGESPEC_SUPPORT) { 983 if (ENABLE_PACKAGESPEC_SUPPORT) {
1021 String directoryPath = pathContext.dirname(path); 984 String directoryPath = pathContext.dirname(path);
1022 985
1023 // Check to see if we need to create a new context. 986 // Check to see if we need to create a new context.
1024 if (info.isTopLevel) { 987 if (info.isTopLevel) {
(...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after
1056 1019
1057 // If the file went away and was replaced by a folder before we 1020 // If the file went away and was replaced by a folder before we
1058 // had a chance to process the event, resource might be a Folder. In 1021 // had a chance to process the event, resource might be a Folder. In
1059 // that case don't add it. 1022 // that case don't add it.
1060 if (resource is File) { 1023 if (resource is File) {
1061 File file = resource; 1024 File file = resource;
1062 if (callbacks.shouldFileBeAnalyzed(file)) { 1025 if (callbacks.shouldFileBeAnalyzed(file)) {
1063 ChangeSet changeSet = new ChangeSet(); 1026 ChangeSet changeSet = new ChangeSet();
1064 Source source = createSourceInContext(info.context, file); 1027 Source source = createSourceInContext(info.context, file);
1065 changeSet.addedSource(source); 1028 changeSet.addedSource(source);
1066 callbacks.applyChangesToContext(folder, changeSet); 1029 callbacks.applyChangesToContext(info.folder, changeSet);
1067 info.sources[path] = source; 1030 info.sources[path] = source;
1068 } 1031 }
1069 } 1032 }
1070 break; 1033 break;
1071 case ChangeType.REMOVE: 1034 case ChangeType.REMOVE:
1072 1035
1073 // If package spec info is removed, check to see if we can merge context s. 1036 // If package spec info is removed, check to see if we can merge context s.
1074 // Note that it's important to verify that there is NEITHER a .packages nor a 1037 // Note that it's important to verify that there is NEITHER a .packages nor a
1075 // lingering pubspec.yaml before merging. 1038 // lingering pubspec.yaml before merging.
1076 if (!info.isTopLevel) { 1039 if (!info.isTopLevel) {
(...skipping 26 matching lines...) Expand all
1103 } 1066 }
1104 } 1067 }
1105 } 1068 }
1106 1069
1107 List<Source> sources = info.context.getSourcesWithFullName(path); 1070 List<Source> sources = info.context.getSourcesWithFullName(path);
1108 if (!sources.isEmpty) { 1071 if (!sources.isEmpty) {
1109 ChangeSet changeSet = new ChangeSet(); 1072 ChangeSet changeSet = new ChangeSet();
1110 sources.forEach((Source source) { 1073 sources.forEach((Source source) {
1111 changeSet.removedSource(source); 1074 changeSet.removedSource(source);
1112 }); 1075 });
1113 callbacks.applyChangesToContext(folder, changeSet); 1076 callbacks.applyChangesToContext(info.folder, changeSet);
1114 info.sources.remove(path); 1077 info.sources.remove(path);
1115 } 1078 }
1116 break; 1079 break;
1117 case ChangeType.MODIFY: 1080 case ChangeType.MODIFY:
1118 List<Source> sources = info.context.getSourcesWithFullName(path); 1081 List<Source> sources = info.context.getSourcesWithFullName(path);
1119 if (!sources.isEmpty) { 1082 if (!sources.isEmpty) {
1120 ChangeSet changeSet = new ChangeSet(); 1083 ChangeSet changeSet = new ChangeSet();
1121 sources.forEach((Source source) { 1084 sources.forEach((Source source) {
1122 changeSet.changedSource(source); 1085 changeSet.changedSource(source);
1123 }); 1086 });
1124 callbacks.applyChangesToContext(folder, changeSet); 1087 callbacks.applyChangesToContext(info.folder, changeSet);
1125 } 1088 }
1126 break; 1089 break;
1127 } 1090 }
1128 1091
1129 //TODO(pquitslund): find the right place for this 1092 //TODO(pquitslund): find the right place for this
1130 _checkForPackagespecUpdate(path, info, folder); 1093 _checkForPackagespecUpdate(path, info, info.folder);
1131 } 1094 }
1132 1095
1133 /** 1096 /**
1134 * Returns `true` if the given [path] is excluded by [excludedPaths]. 1097 * Returns `true` if the given [path] is excluded by [excludedPaths].
1135 */ 1098 */
1136 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path); 1099 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path);
1137 1100
1138 /** 1101 /**
1139 * Returns `true` if the given [path] is excluded by [excludedPaths]. 1102 * Returns `true` if the given [path] is excluded by [excludedPaths].
1140 */ 1103 */
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
1197 * Recompute the [FolderDisposition] for the context described by [info], 1160 * Recompute the [FolderDisposition] for the context described by [info],
1198 * and update the client appropriately. 1161 * and update the client appropriately.
1199 */ 1162 */
1200 void _recomputeFolderDisposition(ContextInfo info) { 1163 void _recomputeFolderDisposition(ContextInfo info) {
1201 // TODO(paulberry): when computePackageMap is changed into an 1164 // TODO(paulberry): when computePackageMap is changed into an
1202 // asynchronous API call, we'll want to suspend analysis for this context 1165 // asynchronous API call, we'll want to suspend analysis for this context
1203 // while we're rerunning "pub list", since any analysis we complete while 1166 // while we're rerunning "pub list", since any analysis we complete while
1204 // "pub list" is in progress is just going to get thrown away anyhow. 1167 // "pub list" is in progress is just going to get thrown away anyhow.
1205 List<String> dependencies = <String>[]; 1168 List<String> dependencies = <String>[];
1206 FolderDisposition disposition = 1169 FolderDisposition disposition =
1207 _computeFolderDisposition(info.folder, info, dependencies.add); 1170 _computeFolderDisposition(info.folder, dependencies.add);
1208 info.setDependencies(dependencies); 1171 info.setDependencies(dependencies);
1209 callbacks.updateContextPackageUriResolver(info.folder, disposition); 1172 callbacks.updateContextPackageUriResolver(info.folder, disposition);
1210 } 1173 }
1211 1174
1212 /** 1175 /**
1213 * Create and return a source representing the given [file] within the given 1176 * Create and return a source representing the given [file] within the given
1214 * [context]. 1177 * [context].
1215 */ 1178 */
1216 static Source createSourceInContext(AnalysisContext context, File file) { 1179 static Source createSourceInContext(AnalysisContext context, File file) {
1217 // TODO(brianwilkerson) Optimize this, by allowing support for source 1180 // TODO(brianwilkerson) Optimize this, by allowing support for source
(...skipping 151 matching lines...) Expand 10 before | Expand all | Expand 10 after
1369 1332
1370 PackagesFileDisposition(this.packages) {} 1333 PackagesFileDisposition(this.packages) {}
1371 1334
1372 @override 1335 @override
1373 String get packageRoot => null; 1336 String get packageRoot => null;
1374 1337
1375 @override 1338 @override
1376 Iterable<UriResolver> createPackageUriResolvers( 1339 Iterable<UriResolver> createPackageUriResolvers(
1377 ResourceProvider resourceProvider) => const <UriResolver>[]; 1340 ResourceProvider resourceProvider) => const <UriResolver>[];
1378 } 1341 }
OLDNEW
« no previous file with comments | « no previous file | pkg/analysis_server/test/context_manager_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698