| OLD | NEW |
| 1 // Copyright (c) 2016, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2016, 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 analysis_server.src.single_context_manager; | 5 library analysis_server.src.single_context_manager; |
| 6 | 6 |
| 7 import 'dart:async'; | 7 import 'dart:async'; |
| 8 import 'dart:core' hide Resource; | 8 import 'dart:core' hide Resource; |
| 9 import 'dart:math' as math; | 9 import 'dart:math' as math; |
| 10 | 10 |
| (...skipping 77 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 88 * The context in which everything is being analyzed. | 88 * The context in which everything is being analyzed. |
| 89 */ | 89 */ |
| 90 AnalysisContext context; | 90 AnalysisContext context; |
| 91 | 91 |
| 92 /** | 92 /** |
| 93 * The folder associated with the context. | 93 * The folder associated with the context. |
| 94 */ | 94 */ |
| 95 Folder contextFolder; | 95 Folder contextFolder; |
| 96 | 96 |
| 97 /** | 97 /** |
| 98 * The current [contextFolder] watch subscription. | 98 * The current watch subscriptions. |
| 99 */ | 99 */ |
| 100 StreamSubscription<WatchEvent> watchSubscription; | 100 Map<String, StreamSubscription<WatchEvent>> watchSubscriptions = |
| 101 new Map<String, StreamSubscription<WatchEvent>>(); |
| 101 | 102 |
| 102 /** | 103 /** |
| 103 * The [packageResolverProvider] must not be `null`. | 104 * The [packageResolverProvider] must not be `null`. |
| 104 */ | 105 */ |
| 105 SingleContextManager(this.resourceProvider, this.sdkManager, | 106 SingleContextManager(this.resourceProvider, this.sdkManager, |
| 106 this.packageResolverProvider, this.analyzedFilesGlobs) { | 107 this.packageResolverProvider, this.analyzedFilesGlobs) { |
| 107 pathContext = resourceProvider.pathContext; | 108 pathContext = resourceProvider.pathContext; |
| 108 } | 109 } |
| 109 | 110 |
| 110 @override | 111 @override |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 143 !_isContainedIn(excludedPaths, path); | 144 !_isContainedIn(excludedPaths, path); |
| 144 } | 145 } |
| 145 | 146 |
| 146 @override | 147 @override |
| 147 void refresh(List<Resource> roots) { | 148 void refresh(List<Resource> roots) { |
| 148 if (context != null) { | 149 if (context != null) { |
| 149 callbacks.removeContext(contextFolder, null); | 150 callbacks.removeContext(contextFolder, null); |
| 150 context.dispose(); | 151 context.dispose(); |
| 151 context = null; | 152 context = null; |
| 152 contextFolder = null; | 153 contextFolder = null; |
| 153 if (watchSubscription != null) { | 154 _cancelCurrentWatchSubscriptions(); |
| 154 watchSubscription.cancel(); | |
| 155 watchSubscription = null; | |
| 156 } | |
| 157 setRoots(includedPaths, excludedPaths, packageRoots); | 155 setRoots(includedPaths, excludedPaths, packageRoots); |
| 158 } | 156 } |
| 159 } | 157 } |
| 160 | 158 |
| 161 @override | 159 @override |
| 162 void setRoots(List<String> includedPaths, List<String> excludedPaths, | 160 void setRoots(List<String> includedPaths, List<String> excludedPaths, |
| 163 Map<String, String> packageRoots) { | 161 Map<String, String> packageRoots) { |
| 164 includedPaths = _nonOverlappingPaths(includedPaths); | 162 includedPaths = _nonOverlappingPaths(includedPaths); |
| 165 excludedPaths = _nonOverlappingPaths(excludedPaths); | 163 excludedPaths = _nonOverlappingPaths(excludedPaths); |
| 166 this.packageRoots = packageRoots; | 164 this.packageRoots = packageRoots; |
| 167 _updateNormalizedPackageRoots(); | 165 _updateNormalizedPackageRoots(); |
| 168 // Update context path. | 166 // Update context path. |
| 169 { | 167 { |
| 170 String contextPath = _commonPrefix(includedPaths); | 168 String contextPath = _commonPrefix(includedPaths); |
| 171 Folder contextFolder = resourceProvider.getFolder(contextPath); | 169 Folder contextFolder = resourceProvider.getFolder(contextPath); |
| 172 if (contextFolder != this.contextFolder) { | 170 if (contextFolder != this.contextFolder) { |
| 173 if (context != null) { | 171 if (context != null) { |
| 174 callbacks.moveContext(this.contextFolder, contextFolder); | 172 callbacks.moveContext(this.contextFolder, contextFolder); |
| 175 } | 173 } |
| 176 this.contextFolder = contextFolder; | 174 this.contextFolder = contextFolder; |
| 177 // Start new watcher and cancel the old one. | |
| 178 StreamSubscription<WatchEvent> watchSubscription = | |
| 179 this.contextFolder.changes.listen(_handleWatchEvent); | |
| 180 this.watchSubscription?.cancel(); | |
| 181 this.watchSubscription = watchSubscription; | |
| 182 } | 175 } |
| 183 } | 176 } |
| 177 // Start new watchers and cancel old ones. |
| 178 { |
| 179 Map<String, StreamSubscription<WatchEvent>> newSubscriptions = |
| 180 new Map<String, StreamSubscription<WatchEvent>>(); |
| 181 for (String includedPath in includedPaths) { |
| 182 Resource resource = resourceProvider.getResource(includedPath); |
| 183 if (resource is Folder) { |
| 184 // Extract the existing subscription or create a new one. |
| 185 StreamSubscription<WatchEvent> subscription = |
| 186 watchSubscriptions.remove(includedPath); |
| 187 if (subscription == null) { |
| 188 subscription = resource.changes.listen(_handleWatchEvent); |
| 189 } |
| 190 // Remember the subscription. |
| 191 newSubscriptions[includedPath] = subscription; |
| 192 } |
| 193 _cancelCurrentWatchSubscriptions(); |
| 194 this.watchSubscriptions = newSubscriptions; |
| 195 } |
| 196 } |
| 197 // Create or update the analysis context. |
| 184 if (context == null) { | 198 if (context == null) { |
| 185 UriResolver packageResolver = packageResolverProvider(); | 199 UriResolver packageResolver = packageResolverProvider(); |
| 186 context = callbacks.addContext(contextFolder, new AnalysisOptionsImpl(), | 200 context = callbacks.addContext(contextFolder, new AnalysisOptionsImpl(), |
| 187 new CustomPackageResolverDisposition(packageResolver)); | 201 new CustomPackageResolverDisposition(packageResolver)); |
| 188 ChangeSet changeSet = | 202 ChangeSet changeSet = |
| 189 _buildChangeSet(added: _includedFiles(includedPaths, excludedPaths)); | 203 _buildChangeSet(added: _includedFiles(includedPaths, excludedPaths)); |
| 190 callbacks.applyChangesToContext(contextFolder, changeSet); | 204 callbacks.applyChangesToContext(contextFolder, changeSet); |
| 191 } else { | 205 } else { |
| 192 // TODO(brianwilkerson) Optimize this. | 206 // TODO(brianwilkerson) Optimize this. |
| 193 List<File> oldFiles = | 207 List<File> oldFiles = |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 235 } | 249 } |
| 236 if (removed != null) { | 250 if (removed != null) { |
| 237 for (File file in removed) { | 251 for (File file in removed) { |
| 238 Source source = createSourceInContext(context, file); | 252 Source source = createSourceInContext(context, file); |
| 239 changeSet.removedSource(source); | 253 changeSet.removedSource(source); |
| 240 } | 254 } |
| 241 } | 255 } |
| 242 return changeSet; | 256 return changeSet; |
| 243 } | 257 } |
| 244 | 258 |
| 259 void _cancelCurrentWatchSubscriptions() { |
| 260 for (StreamSubscription<WatchEvent> subscription |
| 261 in watchSubscriptions.values) { |
| 262 subscription.cancel(); |
| 263 } |
| 264 watchSubscriptions.clear(); |
| 265 } |
| 266 |
| 245 String _commonPrefix(List<String> paths) { | 267 String _commonPrefix(List<String> paths) { |
| 246 if (paths.isEmpty) { | 268 if (paths.isEmpty) { |
| 247 return ''; | 269 return ''; |
| 248 } | 270 } |
| 249 List<String> left = pathContext.split(paths[0]); | 271 List<String> left = pathContext.split(paths[0]); |
| 250 int count = left.length; | 272 int count = left.length; |
| 251 for (int i = 1; i < paths.length; i++) { | 273 for (int i = 1; i < paths.length; i++) { |
| 252 List<String> right = pathContext.split(paths[i]); | 274 List<String> right = pathContext.split(paths[i]); |
| 253 count = _commonComponents(left, count, right); | 275 count = _commonComponents(left, count, right); |
| 254 } | 276 } |
| (...skipping 218 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 473 static List<Resource> _getChildrenSafe(Folder folder) { | 495 static List<Resource> _getChildrenSafe(Folder folder) { |
| 474 try { | 496 try { |
| 475 return folder.getChildren(); | 497 return folder.getChildren(); |
| 476 } on FileSystemException { | 498 } on FileSystemException { |
| 477 // The folder either doesn't exist or cannot be read. | 499 // The folder either doesn't exist or cannot be read. |
| 478 // Either way, there are no children. | 500 // Either way, there are no children. |
| 479 return const <Resource>[]; | 501 return const <Resource>[]; |
| 480 } | 502 } |
| 481 } | 503 } |
| 482 } | 504 } |
| OLD | NEW |