OLD | NEW |
1 // Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2017, 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 import 'dart:async'; | 5 import 'dart:async'; |
6 import 'dart:collection'; | 6 import 'dart:collection'; |
7 import 'dart:io' show Platform; | 7 import 'dart:io' show Platform; |
8 | 8 |
9 import 'package:analysis_server/src/plugin/notification_manager.dart'; | 9 import 'package:analysis_server/src/plugin/notification_manager.dart'; |
10 import 'package:analyzer/context/context_root.dart' as analyzer; | 10 import 'package:analyzer/context/context_root.dart' as analyzer; |
(...skipping 243 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
254 * The object used to manage the receiving and sending of notifications. | 254 * The object used to manage the receiving and sending of notifications. |
255 */ | 255 */ |
256 final NotificationManager notificationManager; | 256 final NotificationManager notificationManager; |
257 | 257 |
258 /** | 258 /** |
259 * The instrumentation service that is being used by the analysis server. | 259 * The instrumentation service that is being used by the analysis server. |
260 */ | 260 */ |
261 final InstrumentationService instrumentationService; | 261 final InstrumentationService instrumentationService; |
262 | 262 |
263 /** | 263 /** |
| 264 * The list of globs used to match plugin paths that have been whitelisted. |
| 265 */ |
| 266 List<Glob> _whitelistGlobs; |
| 267 |
| 268 /** |
264 * A table mapping the paths of plugins to information about those plugins. | 269 * A table mapping the paths of plugins to information about those plugins. |
265 */ | 270 */ |
266 Map<String, PluginInfo> _pluginMap = <String, PluginInfo>{}; | 271 Map<String, PluginInfo> _pluginMap = <String, PluginInfo>{}; |
267 | 272 |
268 /** | 273 /** |
269 * The parameters for the last 'analysis.setPriorityFiles' request that was | 274 * The parameters for the last 'analysis.setPriorityFiles' request that was |
270 * received from the client. Because plugins are lazily discovered, this needs | 275 * received from the client. Because plugins are lazily discovered, this needs |
271 * to be retained so that it can be sent after a plugin has been started. | 276 * to be retained so that it can be sent after a plugin has been started. |
272 */ | 277 */ |
273 AnalysisSetPriorityFilesParams _analysisSetPriorityFilesParams; | 278 AnalysisSetPriorityFilesParams _analysisSetPriorityFilesParams; |
(...skipping 10 matching lines...) Expand all Loading... |
284 * discovered, the state needs to be retained so that it can be sent after a | 289 * discovered, the state needs to be retained so that it can be sent after a |
285 * plugin has been started. | 290 * plugin has been started. |
286 */ | 291 */ |
287 Map<String, dynamic> _overlayState = <String, dynamic>{}; | 292 Map<String, dynamic> _overlayState = <String, dynamic>{}; |
288 | 293 |
289 /** | 294 /** |
290 * Initialize a newly created plugin manager. The notifications from the | 295 * Initialize a newly created plugin manager. The notifications from the |
291 * running plugins will be handled by the given [notificationManager]. | 296 * running plugins will be handled by the given [notificationManager]. |
292 */ | 297 */ |
293 PluginManager(this.resourceProvider, this.byteStorePath, this.sdkPath, | 298 PluginManager(this.resourceProvider, this.byteStorePath, this.sdkPath, |
294 this.notificationManager, this.instrumentationService); | 299 this.notificationManager, this.instrumentationService) { |
| 300 // TODO(brianwilkerson) Figure out the right list of plugin paths. |
| 301 _whitelistGlobs = <Glob>[ |
| 302 new Glob(resourceProvider.pathContext.separator, |
| 303 '**/analyze_angular/tools/analysis_plugin') |
| 304 ]; |
| 305 } |
295 | 306 |
296 /** | 307 /** |
297 * Add the plugin with the given [path] to the list of plugins that should be | 308 * Add the plugin with the given [path] to the list of plugins that should be |
298 * used when analyzing code for the given [contextRoot]. If the plugin had not | 309 * used when analyzing code for the given [contextRoot]. If the plugin had not |
299 * yet been started, then it will be started by this method. | 310 * yet been started, then it will be started by this method. |
300 */ | 311 */ |
301 Future<Null> addPluginToContextRoot( | 312 Future<Null> addPluginToContextRoot( |
302 analyzer.ContextRoot contextRoot, String path) async { | 313 analyzer.ContextRoot contextRoot, String path) async { |
| 314 if (!_isWhitelisted(path)) { |
| 315 return; |
| 316 } |
303 PluginInfo plugin = _pluginMap[path]; | 317 PluginInfo plugin = _pluginMap[path]; |
304 bool isNew = plugin == null; | 318 bool isNew = plugin == null; |
305 if (isNew) { | 319 if (isNew) { |
306 List<String> pluginPaths = _pathsFor(path); | 320 List<String> pluginPaths = _pathsFor(path); |
307 if (pluginPaths == null) { | 321 if (pluginPaths == null) { |
308 return; | 322 return; |
309 } | 323 } |
310 plugin = new DiscoveredPluginInfo(path, pluginPaths[0], pluginPaths[1], | 324 plugin = new DiscoveredPluginInfo(path, pluginPaths[0], pluginPaths[1], |
311 notificationManager, instrumentationService); | 325 notificationManager, instrumentationService); |
312 _pluginMap[path] = plugin; | 326 _pluginMap[path] = plugin; |
(...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
468 } | 482 } |
469 } | 483 } |
470 | 484 |
471 /** | 485 /** |
472 * Stop all of the plugins that are currently running. | 486 * Stop all of the plugins that are currently running. |
473 */ | 487 */ |
474 Future<List<Null>> stopAll() { | 488 Future<List<Null>> stopAll() { |
475 return Future.wait(_pluginMap.values.map((PluginInfo info) => info.stop())); | 489 return Future.wait(_pluginMap.values.map((PluginInfo info) => info.stop())); |
476 } | 490 } |
477 | 491 |
| 492 /** |
| 493 * Whitelist all plugins. |
| 494 */ |
| 495 @visibleForTesting |
| 496 void whitelistEverything() { |
| 497 _whitelistGlobs = <Glob>[ |
| 498 new Glob(resourceProvider.pathContext.separator, '**/*') |
| 499 ]; |
| 500 } |
| 501 |
478 WatchEventType _convertChangeType(watcher.ChangeType type) { | 502 WatchEventType _convertChangeType(watcher.ChangeType type) { |
479 switch (type) { | 503 switch (type) { |
480 case watcher.ChangeType.ADD: | 504 case watcher.ChangeType.ADD: |
481 return WatchEventType.ADD; | 505 return WatchEventType.ADD; |
482 case watcher.ChangeType.MODIFY: | 506 case watcher.ChangeType.MODIFY: |
483 return WatchEventType.MODIFY; | 507 return WatchEventType.MODIFY; |
484 case watcher.ChangeType.REMOVE: | 508 case watcher.ChangeType.REMOVE: |
485 return WatchEventType.REMOVE; | 509 return WatchEventType.REMOVE; |
486 default: | 510 default: |
487 throw new StateError('Unknown change type: $type'); | 511 throw new StateError('Unknown change type: $type'); |
488 } | 512 } |
489 } | 513 } |
490 | 514 |
491 WatchEvent _convertWatchEvent(watcher.WatchEvent watchEvent) { | 515 WatchEvent _convertWatchEvent(watcher.WatchEvent watchEvent) { |
492 return new WatchEvent(_convertChangeType(watchEvent.type), watchEvent.path); | 516 return new WatchEvent(_convertChangeType(watchEvent.type), watchEvent.path); |
493 } | 517 } |
494 | 518 |
495 /** | 519 /** |
| 520 * Return `true` if the plugin with the given [path] has been whitelisted. |
| 521 */ |
| 522 bool _isWhitelisted(String path) { |
| 523 for (Glob glob in _whitelistGlobs) { |
| 524 if (glob.matches(path)) { |
| 525 return true; |
| 526 } |
| 527 } |
| 528 return false; |
| 529 } |
| 530 |
| 531 /** |
496 * Return the execution path and .packages path associated with the plugin at | 532 * Return the execution path and .packages path associated with the plugin at |
497 * the given [path], or `null` if there is a problem that prevents us from | 533 * the given [path], or `null` if there is a problem that prevents us from |
498 * executing the plugin. | 534 * executing the plugin. |
499 */ | 535 */ |
500 List<String> _pathsFor(String pluginPath) { | 536 List<String> _pathsFor(String pluginPath) { |
501 /** | 537 /** |
502 * Return `true` if the plugin in the give [folder] needs to be copied to a | 538 * Return `true` if the plugin in the give [folder] needs to be copied to a |
503 * temporary location so that 'pub' can be run to resolve dependencies. We | 539 * temporary location so that 'pub' can be run to resolve dependencies. We |
504 * need to run `pub` if the plugin contains a `pubspec.yaml` file and is not | 540 * need to run `pub` if the plugin contains a `pubspec.yaml` file and is not |
505 * in a workspace. | 541 * in a workspace. |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
756 Future<Null> stop() { | 792 Future<Null> stop() { |
757 if (channel == null) { | 793 if (channel == null) { |
758 throw new StateError('Cannot stop a plugin that is not running.'); | 794 throw new StateError('Cannot stop a plugin that is not running.'); |
759 } | 795 } |
760 // TODO(brianwilkerson) Ensure that the isolate is killed if it does not | 796 // TODO(brianwilkerson) Ensure that the isolate is killed if it does not |
761 // terminate normally. | 797 // terminate normally. |
762 sendRequest(new PluginShutdownParams()); | 798 sendRequest(new PluginShutdownParams()); |
763 return pluginStoppedCompleter.future; | 799 return pluginStoppedCompleter.future; |
764 } | 800 } |
765 } | 801 } |
OLD | NEW |