| 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:convert'; |
| 10 import 'dart:core' hide Resource; | 10 import 'dart:core' hide Resource; |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 import 'package:package_config/src/packages_impl.dart' show MapPackages; | 27 import 'package:package_config/src/packages_impl.dart' show MapPackages; |
| 28 import 'package:path/path.dart' as pathos; | 28 import 'package:path/path.dart' as pathos; |
| 29 import 'package:watcher/watcher.dart'; | 29 import 'package:watcher/watcher.dart'; |
| 30 import 'package:yaml/yaml.dart'; | 30 import 'package:yaml/yaml.dart'; |
| 31 | 31 |
| 32 /** | 32 /** |
| 33 * Information tracked by the [ContextManager] for each context. | 33 * Information tracked by the [ContextManager] for each context. |
| 34 */ | 34 */ |
| 35 class ContextInfo { | 35 class ContextInfo { |
| 36 /** | 36 /** |
| 37 * The [ContextManager] which is tracking this information. |
| 38 */ |
| 39 final ContextManagerImpl contextManager; |
| 40 |
| 41 /** |
| 37 * The [Folder] for which this information object is created. | 42 * The [Folder] for which this information object is created. |
| 38 */ | 43 */ |
| 39 final Folder folder; | 44 final Folder folder; |
| 40 | 45 |
| 41 /// The [PathFilter] used to filter sources from being analyzed. | 46 /// The [PathFilter] used to filter sources from being analyzed. |
| 42 final PathFilter pathFilter; | 47 final PathFilter pathFilter; |
| 43 | 48 |
| 44 /** | 49 /** |
| 45 * The enclosed pubspec-based contexts. | 50 * The enclosed pubspec-based contexts. |
| 46 */ | 51 */ |
| (...skipping 17 matching lines...) Expand all Loading... |
| 64 String packageDescriptionPath; | 69 String packageDescriptionPath; |
| 65 | 70 |
| 66 /** | 71 /** |
| 67 * Stream subscription we are using to watch the context's directory for | 72 * Stream subscription we are using to watch the context's directory for |
| 68 * changes. | 73 * changes. |
| 69 */ | 74 */ |
| 70 StreamSubscription<WatchEvent> changeSubscription; | 75 StreamSubscription<WatchEvent> changeSubscription; |
| 71 | 76 |
| 72 /** | 77 /** |
| 73 * Stream subscriptions we are using to watch the files | 78 * Stream subscriptions we are using to watch the files |
| 74 * used to determine the package map. | 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. |
| 75 */ | 84 */ |
| 76 final List<StreamSubscription<WatchEvent>> dependencySubscriptions = | 85 final Map<String, StreamSubscription<WatchEvent>> _dependencySubscriptions = |
| 77 <StreamSubscription<WatchEvent>>[]; | 86 <String, StreamSubscription<WatchEvent>>{}; |
| 78 | 87 |
| 79 /** | 88 /** |
| 80 * The analysis context that was created for the [folder]. | 89 * The analysis context that was created for the [folder]. |
| 81 */ | 90 */ |
| 82 AnalysisContext context; | 91 AnalysisContext context; |
| 83 | 92 |
| 84 /** | 93 /** |
| 85 * Map from full path to the [Source] object, for each source that has been | 94 * Map from full path to the [Source] object, for each source that has been |
| 86 * added to the context. | 95 * added to the context. |
| 87 */ | 96 */ |
| 88 Map<String, Source> sources = new HashMap<String, Source>(); | 97 Map<String, Source> sources = new HashMap<String, Source>(); |
| 89 | 98 |
| 90 /** | 99 ContextInfo(this.contextManager, this.parent, Folder folder, |
| 91 * Info returned by the last call to | 100 File packagespecFile, this.packageRoot) |
| 92 * [OptimizingPubPackageMapProvider.computePackageMap], or `null` if the | |
| 93 * package map hasn't been computed for this context yet. | |
| 94 */ | |
| 95 PackageMapInfo packageMapInfo; | |
| 96 | |
| 97 ContextInfo( | |
| 98 this.parent, Folder folder, File packagespecFile, this.packageRoot) | |
| 99 : folder = folder, | 101 : folder = folder, |
| 100 pathFilter = new PathFilter(folder.path, null) { | 102 pathFilter = new PathFilter(folder.path, null) { |
| 101 packageDescriptionPath = packagespecFile.path; | 103 packageDescriptionPath = packagespecFile.path; |
| 102 parent.children.add(this); | 104 parent.children.add(this); |
| 103 } | 105 } |
| 104 | 106 |
| 105 /** | 107 /** |
| 106 * Create the virtual [ContextInfo] which acts as an ancestor to all other | 108 * Create the virtual [ContextInfo] which acts as an ancestor to all other |
| 107 * [ContextInfo]s. | 109 * [ContextInfo]s. |
| 108 */ | 110 */ |
| 109 ContextInfo._root() | 111 ContextInfo._root() |
| 110 : folder = null, | 112 : contextManager = null, |
| 113 folder = null, |
| 111 pathFilter = null; | 114 pathFilter = null; |
| 112 | 115 |
| 113 /** | 116 /** |
| 114 * Iterate through all [children] and their children, recursively. | 117 * Iterate through all [children] and their children, recursively. |
| 115 */ | 118 */ |
| 116 Iterable<ContextInfo> get descendants sync* { | 119 Iterable<ContextInfo> get descendants sync* { |
| 117 for (ContextInfo child in children) { | 120 for (ContextInfo child in children) { |
| 118 yield child; | 121 yield child; |
| 119 yield* child.descendants; | 122 yield* child.descendants; |
| 120 } | 123 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 147 */ | 150 */ |
| 148 ContextInfo findChildInfoFor(String path) { | 151 ContextInfo findChildInfoFor(String path) { |
| 149 for (ContextInfo info in children) { | 152 for (ContextInfo info in children) { |
| 150 if (info.folder.isOrContains(path)) { | 153 if (info.folder.isOrContains(path)) { |
| 151 return info; | 154 return info; |
| 152 } | 155 } |
| 153 } | 156 } |
| 154 return null; | 157 return null; |
| 155 } | 158 } |
| 156 | 159 |
| 160 /** |
| 161 * Determine if the given [path] is one of the dependencies most recently |
| 162 * passed to [setDependencies]. |
| 163 */ |
| 164 bool hasDependency(String path) => _dependencySubscriptions.containsKey(path); |
| 165 |
| 157 /// Returns `true` if [path] should be ignored. | 166 /// Returns `true` if [path] should be ignored. |
| 158 bool ignored(String path) => pathFilter.ignored(path); | 167 bool ignored(String path) => pathFilter.ignored(path); |
| 159 | 168 |
| 160 /** | 169 /** |
| 161 * Returns `true` if [path] is the package description file for this context | 170 * Returns `true` if [path] is the package description file for this context |
| 162 * (pubspec.yaml or .packages). | 171 * (pubspec.yaml or .packages). |
| 163 */ | 172 */ |
| 164 bool isPathToPackageDescription(String path) => | 173 bool isPathToPackageDescription(String path) => |
| 165 path == packageDescriptionPath; | 174 path == packageDescriptionPath; |
| 175 |
| 176 /** |
| 177 * Update the set of dependencies for this context. Watchers are |
| 178 * automatically set up for the dependencies (if necessary) to ensure that |
| 179 * [ContextManagerImpl._handleWatchEvent] is called when they are modified. |
| 180 */ |
| 181 void setDependencies(Iterable<String> newDependencies) { |
| 182 for (String oldDependency in _dependencySubscriptions.keys.toList()) { |
| 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 } |
| 166 } | 214 } |
| 167 | 215 |
| 168 /** | 216 /** |
| 169 * Class that maintains a mapping from included/excluded paths to a set of | 217 * Class that maintains a mapping from included/excluded paths to a set of |
| 170 * folders that should correspond to analysis contexts. | 218 * folders that should correspond to analysis contexts. |
| 171 */ | 219 */ |
| 172 abstract class ContextManager { | 220 abstract class ContextManager { |
| 173 // TODO(brianwilkerson) Support: | 221 // TODO(brianwilkerson) Support: |
| 174 // setting the default analysis options | 222 // setting the default analysis options |
| 175 // setting the default content cache | 223 // setting the default content cache |
| (...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 655 } | 703 } |
| 656 _addSourceFiles(changeSet, child, info); | 704 _addSourceFiles(changeSet, child, info); |
| 657 } | 705 } |
| 658 } | 706 } |
| 659 } | 707 } |
| 660 | 708 |
| 661 /** | 709 /** |
| 662 * Cancel all dependency subscriptions for the given context. | 710 * Cancel all dependency subscriptions for the given context. |
| 663 */ | 711 */ |
| 664 void _cancelDependencySubscriptions(ContextInfo info) { | 712 void _cancelDependencySubscriptions(ContextInfo info) { |
| 665 for (StreamSubscription<WatchEvent> s in info.dependencySubscriptions) { | 713 info.setDependencies(const <String>[]); |
| 666 s.cancel(); | |
| 667 } | |
| 668 info.dependencySubscriptions.clear(); | |
| 669 } | 714 } |
| 670 | 715 |
| 671 void _checkForPackagespecUpdate( | 716 void _checkForPackagespecUpdate( |
| 672 String path, ContextInfo info, Folder folder) { | 717 String path, ContextInfo info, Folder folder) { |
| 673 // Check to see if this is the .packages file for this context and if so, | 718 // Check to see if this is the .packages file for this context and if so, |
| 674 // update the context's source factory. | 719 // update the context's source factory. |
| 675 if (pathContext.basename(path) == PACKAGE_SPEC_NAME && | 720 if (pathContext.basename(path) == PACKAGE_SPEC_NAME && |
| 676 info.isPathToPackageDescription(path)) { | 721 info.isPathToPackageDescription(path)) { |
| 677 File packagespec = resourceProvider.getFile(path); | 722 File packagespec = resourceProvider.getFile(path); |
| 678 if (packagespec.exists) { | 723 if (packagespec.exists) { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 702 if (context != contextN) { | 747 if (context != contextN) { |
| 703 for (Source source in contextN.sources) { | 748 for (Source source in contextN.sources) { |
| 704 flushedFiles.remove(source.fullName); | 749 flushedFiles.remove(source.fullName); |
| 705 } | 750 } |
| 706 } | 751 } |
| 707 } | 752 } |
| 708 return flushedFiles.toList(growable: false); | 753 return flushedFiles.toList(growable: false); |
| 709 } | 754 } |
| 710 | 755 |
| 711 /** | 756 /** |
| 712 * Compute the appropriate [FolderDisposition] for [folder], and store | 757 * Compute the appropriate [FolderDisposition] for [info]. Use |
| 713 * dependency information in [info]. | 758 * [addDependency] to indicate which files needed to be consulted in order to |
| 759 * figure out the [FolderDisposition]; these dependencies will be watched in |
| 760 * order to determine when it is necessary to call this function again. |
| 761 * |
| 762 * TODO(paulberry): use [addDependency] for tracking all folder disposition |
| 763 * dependencies (currently we only use it to track "pub list" dependencies). |
| 714 */ | 764 */ |
| 715 FolderDisposition _computeFolderDisposition(Folder folder, ContextInfo info) { | 765 FolderDisposition _computeFolderDisposition( |
| 716 _cancelDependencySubscriptions(info); | 766 Folder folder, ContextInfo info, void addDependency(String path)) { |
| 717 if (info.packageRoot != null) { | 767 if (info.packageRoot != null) { |
| 718 info.packageMapInfo = null; | |
| 719 // TODO(paulberry): We shouldn't be using JavaFile here because it | 768 // TODO(paulberry): We shouldn't be using JavaFile here because it |
| 720 // makes the code untestable (see dartbug.com/23909). | 769 // makes the code untestable (see dartbug.com/23909). |
| 721 JavaFile packagesDir = new JavaFile(info.packageRoot); | 770 JavaFile packagesDir = new JavaFile(info.packageRoot); |
| 722 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>(); | 771 Map<String, List<Folder>> packageMap = new Map<String, List<Folder>>(); |
| 723 if (packagesDir.isDirectory()) { | 772 if (packagesDir.isDirectory()) { |
| 724 for (JavaFile file in packagesDir.listFiles()) { | 773 for (JavaFile file in packagesDir.listFiles()) { |
| 725 // Ensure symlinks in packages directory are canonicalized | 774 // Ensure symlinks in packages directory are canonicalized |
| 726 // to prevent 'type X cannot be assigned to type X' warnings | 775 // to prevent 'type X cannot be assigned to type X' warnings |
| 727 String path; | 776 String path; |
| 728 try { | 777 try { |
| (...skipping 23 matching lines...) Expand all Loading... |
| 752 if (resolver != null) { | 801 if (resolver != null) { |
| 753 return new CustomPackageResolverDisposition(resolver); | 802 return new CustomPackageResolverDisposition(resolver); |
| 754 } | 803 } |
| 755 } | 804 } |
| 756 PackageMapInfo packageMapInfo; | 805 PackageMapInfo packageMapInfo; |
| 757 ServerPerformanceStatistics.pub.makeCurrentWhile(() { | 806 ServerPerformanceStatistics.pub.makeCurrentWhile(() { |
| 758 packageMapInfo = _packageMapProvider.computePackageMap(folder); | 807 packageMapInfo = _packageMapProvider.computePackageMap(folder); |
| 759 }); | 808 }); |
| 760 callbacks.endComputePackageMap(); | 809 callbacks.endComputePackageMap(); |
| 761 for (String dependencyPath in packageMapInfo.dependencies) { | 810 for (String dependencyPath in packageMapInfo.dependencies) { |
| 762 Resource resource = resourceProvider.getResource(dependencyPath); | 811 addDependency(dependencyPath); |
| 763 if (resource is File) { | |
| 764 StreamSubscription<WatchEvent> subscription; | |
| 765 subscription = resource.changes.listen((WatchEvent event) { | |
| 766 if (info.packageMapInfo != null && | |
| 767 info.packageMapInfo.dependencies.contains(dependencyPath)) { | |
| 768 _recomputeFolderDisposition(info); | |
| 769 } | |
| 770 }, onError: (error, StackTrace stackTrace) { | |
| 771 // Gracefully degrade if file is or becomes unwatchable | |
| 772 _instrumentationService.logException(error, stackTrace); | |
| 773 subscription.cancel(); | |
| 774 info.dependencySubscriptions.remove(subscription); | |
| 775 }); | |
| 776 info.dependencySubscriptions.add(subscription); | |
| 777 } | |
| 778 } | 812 } |
| 779 info.packageMapInfo = packageMapInfo; | |
| 780 if (packageMapInfo.packageMap == null) { | 813 if (packageMapInfo.packageMap == null) { |
| 781 return new NoPackageFolderDisposition(); | 814 return new NoPackageFolderDisposition(); |
| 782 } | 815 } |
| 783 return new PackageMapDisposition(packageMapInfo.packageMap); | 816 return new PackageMapDisposition(packageMapInfo.packageMap); |
| 784 } | 817 } |
| 785 } | 818 } |
| 786 | 819 |
| 787 /** | 820 /** |
| 788 * Create a new empty context associated with [folder], having parent | 821 * Create a new empty context associated with [folder], having parent |
| 789 * [parent] and using [packagespecFile] to resolve package URI's. | 822 * [parent] and using [packagespecFile] to resolve package URI's. |
| 790 */ | 823 */ |
| 791 ContextInfo _createContext( | 824 ContextInfo _createContext( |
| 792 ContextInfo parent, Folder folder, File packagespecFile) { | 825 ContextInfo parent, Folder folder, File packagespecFile) { |
| 793 ContextInfo info = new ContextInfo( | 826 ContextInfo info = new ContextInfo(this, parent, folder, packagespecFile, |
| 794 parent, folder, packagespecFile, normalizedPackageRoots[folder.path]); | 827 normalizedPackageRoots[folder.path]); |
| 795 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); | 828 Map<String, YamlNode> options = analysisOptionsProvider.getOptions(folder); |
| 796 processOptionsForContext(info, options); | 829 processOptionsForContext(info, options); |
| 797 info.changeSubscription = folder.changes.listen((WatchEvent event) { | 830 info.changeSubscription = folder.changes.listen((WatchEvent event) { |
| 798 _handleWatchEvent(folder, info, event); | 831 _handleWatchEvent(folder, info, event); |
| 799 }); | 832 }); |
| 800 try { | 833 try { |
| 801 FolderDisposition disposition; | 834 FolderDisposition disposition; |
| 835 List<String> dependencies = <String>[]; |
| 802 | 836 |
| 803 if (ENABLE_PACKAGESPEC_SUPPORT) { | 837 if (ENABLE_PACKAGESPEC_SUPPORT) { |
| 804 // Try .packages first. | 838 // Try .packages first. |
| 805 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { | 839 if (pathos.basename(packagespecFile.path) == PACKAGE_SPEC_NAME) { |
| 806 Packages packages = _readPackagespec(packagespecFile); | 840 Packages packages = _readPackagespec(packagespecFile); |
| 807 disposition = new PackagesFileDisposition(packages); | 841 disposition = new PackagesFileDisposition(packages); |
| 808 } | 842 } |
| 809 } | 843 } |
| 810 | 844 |
| 811 // Next resort to a package uri resolver. | 845 // Next resort to a package uri resolver. |
| 812 if (disposition == null) { | 846 if (disposition == null) { |
| 813 disposition = _computeFolderDisposition(folder, info); | 847 disposition = _computeFolderDisposition(folder, info, dependencies.add); |
| 814 } | 848 } |
| 815 | 849 |
| 850 info.setDependencies(dependencies); |
| 816 info.context = callbacks.addContext(folder, disposition); | 851 info.context = callbacks.addContext(folder, disposition); |
| 817 info.context.name = folder.path; | 852 info.context.name = folder.path; |
| 818 } catch (_) { | 853 } catch (_) { |
| 819 info.changeSubscription.cancel(); | 854 info.changeSubscription.cancel(); |
| 820 rethrow; | 855 rethrow; |
| 821 } | 856 } |
| 822 return info; | 857 return info; |
| 823 } | 858 } |
| 824 | 859 |
| 825 /** | 860 /** |
| (...skipping 122 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 948 } | 983 } |
| 949 | 984 |
| 950 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { | 985 void _handleWatchEvent(Folder folder, ContextInfo info, WatchEvent event) { |
| 951 // TODO(brianwilkerson) If a file is explicitly included in one context | 986 // TODO(brianwilkerson) If a file is explicitly included in one context |
| 952 // but implicitly referenced in another context, we will only send a | 987 // but implicitly referenced in another context, we will only send a |
| 953 // changeSet to the context that explicitly includes the file (because | 988 // changeSet to the context that explicitly includes the file (because |
| 954 // that's the only context that's watching the file). | 989 // that's the only context that's watching the file). |
| 955 _instrumentationService.logWatchEvent( | 990 _instrumentationService.logWatchEvent( |
| 956 folder.path, event.path, event.type.toString()); | 991 folder.path, event.path, event.type.toString()); |
| 957 String path = event.path; | 992 String path = event.path; |
| 993 // First handle changes that affect folderDisposition (since these need to |
| 994 // be processed regardless of whether they are part of an excluded/ignored |
| 995 // path). |
| 996 if (info.hasDependency(path)) { |
| 997 _recomputeFolderDisposition(info); |
| 998 } |
| 958 // maybe excluded globally | 999 // maybe excluded globally |
| 959 if (_isExcluded(path)) { | 1000 if (_isExcluded(path)) { |
| 960 return; | 1001 return; |
| 961 } | 1002 } |
| 962 // maybe excluded from the context, so other context will handle it | 1003 // maybe excluded from the context, so other context will handle it |
| 963 if (info.excludes(path)) { | 1004 if (info.excludes(path)) { |
| 964 return; | 1005 return; |
| 965 } | 1006 } |
| 966 if (info.ignored(path)) { | 1007 if (info.ignored(path)) { |
| 967 return; | 1008 return; |
| (...skipping 111 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1079 sources.forEach((Source source) { | 1120 sources.forEach((Source source) { |
| 1080 changeSet.changedSource(source); | 1121 changeSet.changedSource(source); |
| 1081 }); | 1122 }); |
| 1082 callbacks.applyChangesToContext(folder, changeSet); | 1123 callbacks.applyChangesToContext(folder, changeSet); |
| 1083 } | 1124 } |
| 1084 break; | 1125 break; |
| 1085 } | 1126 } |
| 1086 | 1127 |
| 1087 //TODO(pquitslund): find the right place for this | 1128 //TODO(pquitslund): find the right place for this |
| 1088 _checkForPackagespecUpdate(path, info, folder); | 1129 _checkForPackagespecUpdate(path, info, folder); |
| 1089 | |
| 1090 if (info.packageMapInfo != null && | |
| 1091 info.packageMapInfo.dependencies.contains(path)) { | |
| 1092 _recomputeFolderDisposition(info); | |
| 1093 } | |
| 1094 } | 1130 } |
| 1095 | 1131 |
| 1096 /** | 1132 /** |
| 1097 * Returns `true` if the given [path] is excluded by [excludedPaths]. | 1133 * Returns `true` if the given [path] is excluded by [excludedPaths]. |
| 1098 */ | 1134 */ |
| 1099 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path); | 1135 bool _isExcluded(String path) => _isExcludedBy(excludedPaths, path); |
| 1100 | 1136 |
| 1101 /** | 1137 /** |
| 1102 * Returns `true` if the given [path] is excluded by [excludedPaths]. | 1138 * Returns `true` if the given [path] is excluded by [excludedPaths]. |
| 1103 */ | 1139 */ |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1158 | 1194 |
| 1159 /** | 1195 /** |
| 1160 * Recompute the [FolderDisposition] for the context described by [info], | 1196 * Recompute the [FolderDisposition] for the context described by [info], |
| 1161 * and update the client appropriately. | 1197 * and update the client appropriately. |
| 1162 */ | 1198 */ |
| 1163 void _recomputeFolderDisposition(ContextInfo info) { | 1199 void _recomputeFolderDisposition(ContextInfo info) { |
| 1164 // TODO(paulberry): when computePackageMap is changed into an | 1200 // TODO(paulberry): when computePackageMap is changed into an |
| 1165 // asynchronous API call, we'll want to suspend analysis for this context | 1201 // asynchronous API call, we'll want to suspend analysis for this context |
| 1166 // while we're rerunning "pub list", since any analysis we complete while | 1202 // while we're rerunning "pub list", since any analysis we complete while |
| 1167 // "pub list" is in progress is just going to get thrown away anyhow. | 1203 // "pub list" is in progress is just going to get thrown away anyhow. |
| 1204 List<String> dependencies = <String>[]; |
| 1168 FolderDisposition disposition = | 1205 FolderDisposition disposition = |
| 1169 _computeFolderDisposition(info.folder, info); | 1206 _computeFolderDisposition(info.folder, info, dependencies.add); |
| 1207 info.setDependencies(dependencies); |
| 1170 callbacks.updateContextPackageUriResolver(info.folder, disposition); | 1208 callbacks.updateContextPackageUriResolver(info.folder, disposition); |
| 1171 } | 1209 } |
| 1172 | 1210 |
| 1173 /** | 1211 /** |
| 1174 * Create and return a source representing the given [file] within the given | 1212 * Create and return a source representing the given [file] within the given |
| 1175 * [context]. | 1213 * [context]. |
| 1176 */ | 1214 */ |
| 1177 static Source createSourceInContext(AnalysisContext context, File file) { | 1215 static Source createSourceInContext(AnalysisContext context, File file) { |
| 1178 // TODO(brianwilkerson) Optimize this, by allowing support for source | 1216 // TODO(brianwilkerson) Optimize this, by allowing support for source |
| 1179 // factories to restore URI's from a file path rather than a source. | 1217 // factories to restore URI's from a file path rather than a source. |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1313 class PackagesFileDisposition extends FolderDisposition { | 1351 class PackagesFileDisposition extends FolderDisposition { |
| 1314 @override | 1352 @override |
| 1315 final Packages packages; | 1353 final Packages packages; |
| 1316 | 1354 |
| 1317 PackagesFileDisposition(this.packages) {} | 1355 PackagesFileDisposition(this.packages) {} |
| 1318 | 1356 |
| 1319 @override | 1357 @override |
| 1320 Iterable<UriResolver> createPackageUriResolvers( | 1358 Iterable<UriResolver> createPackageUriResolvers( |
| 1321 ResourceProvider resourceProvider) => const <UriResolver>[]; | 1359 ResourceProvider resourceProvider) => const <UriResolver>[]; |
| 1322 } | 1360 } |
| OLD | NEW |