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 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
104 * If the plugin is currently running, send a request based on the given | 104 * If the plugin is currently running, send a request based on the given |
105 * [params] to the plugin. If the plugin is not running, the request will | 105 * [params] to the plugin. If the plugin is not running, the request will |
106 * silently be dropped. | 106 * silently be dropped. |
107 */ | 107 */ |
108 void sendRequest(RequestParams params) { | 108 void sendRequest(RequestParams params) { |
109 currentSession?.sendRequest(params); | 109 currentSession?.sendRequest(params); |
110 } | 110 } |
111 | 111 |
112 /** | 112 /** |
113 * Start a new isolate that is running the plugin. Return the state object | 113 * Start a new isolate that is running the plugin. Return the state object |
114 * used to interact with the plugin. | 114 * used to interact with the plugin, or `null` if the plugin could not be run. |
115 */ | 115 */ |
116 Future<PluginSession> start(String byteStorePath) async { | 116 Future<PluginSession> start(String byteStorePath) async { |
117 if (currentSession != null) { | 117 if (currentSession != null) { |
118 throw new StateError('Cannot start a plugin that is already running.'); | 118 throw new StateError('Cannot start a plugin that is already running.'); |
119 } | 119 } |
120 currentSession = new PluginSession(this); | 120 currentSession = new PluginSession(this); |
121 await currentSession.start(byteStorePath); | 121 bool isRunning = await currentSession.start(byteStorePath); |
| 122 if (!isRunning) { |
| 123 currentSession = null; |
| 124 } |
122 return currentSession; | 125 return currentSession; |
123 } | 126 } |
124 | 127 |
125 /** | 128 /** |
126 * Request that the plugin shutdown. | 129 * Request that the plugin shutdown. |
127 */ | 130 */ |
128 Future<Null> stop() { | 131 Future<Null> stop() { |
129 if (currentSession == null) { | 132 if (currentSession == null) { |
130 throw new StateError('Cannot stop a plugin that is not running.'); | 133 throw new StateError('Cannot stop a plugin that is not running.'); |
131 } | 134 } |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
219 if (isNew) { | 222 if (isNew) { |
220 List<String> pluginPaths = _pathsFor(path); | 223 List<String> pluginPaths = _pathsFor(path); |
221 if (pluginPaths == null) { | 224 if (pluginPaths == null) { |
222 return; | 225 return; |
223 } | 226 } |
224 plugin = new PluginInfo(path, pluginPaths[0], pluginPaths[1], | 227 plugin = new PluginInfo(path, pluginPaths[0], pluginPaths[1], |
225 notificationManager, instrumentationService); | 228 notificationManager, instrumentationService); |
226 _pluginMap[path] = plugin; | 229 _pluginMap[path] = plugin; |
227 if (pluginPaths[0] != null) { | 230 if (pluginPaths[0] != null) { |
228 PluginSession session = await plugin.start(byteStorePath); | 231 PluginSession session = await plugin.start(byteStorePath); |
229 session.onDone.then((_) { | 232 session?.onDone?.then((_) { |
230 _pluginMap.remove(path); | 233 _pluginMap.remove(path); |
231 }); | 234 }); |
232 } | 235 } |
233 } | 236 } |
234 plugin.addContextRoot(contextRoot); | 237 plugin.addContextRoot(contextRoot); |
235 if (isNew) { | 238 if (isNew) { |
236 if (_analysisSetSubscriptionsParams != null) { | 239 if (_analysisSetSubscriptionsParams != null) { |
237 plugin.sendRequest(_analysisSetSubscriptionsParams); | 240 plugin.sendRequest(_analysisSetSubscriptionsParams); |
238 } | 241 } |
239 if (_overlayState.isNotEmpty) { | 242 if (_overlayState.isNotEmpty) { |
(...skipping 397 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
637 } | 640 } |
638 if (!isCompatible) { | 641 if (!isCompatible) { |
639 return false; | 642 return false; |
640 } | 643 } |
641 channel = new ServerIsolateChannel( | 644 channel = new ServerIsolateChannel( |
642 new Uri.file(info.executionPath, windows: Platform.isWindows), | 645 new Uri.file(info.executionPath, windows: Platform.isWindows), |
643 new Uri.file(info.packagesPath, windows: Platform.isWindows), | 646 new Uri.file(info.packagesPath, windows: Platform.isWindows), |
644 info.instrumentationService); | 647 info.instrumentationService); |
645 await channel.listen(handleResponse, handleNotification, | 648 await channel.listen(handleResponse, handleNotification, |
646 onDone: handleOnDone, onError: handleOnError); | 649 onDone: handleOnDone, onError: handleOnError); |
| 650 if (channel == null) { |
| 651 // If there is an error when starting the isolate, the channel will invoke |
| 652 // handleOnDone, which will cause `channel` to be set to `null`. |
| 653 return false; |
| 654 } |
647 Response response = await sendRequest( | 655 Response response = await sendRequest( |
648 new PluginVersionCheckParams(byteStorePath ?? '', '1.0.0-alpha.0')); | 656 new PluginVersionCheckParams(byteStorePath ?? '', '1.0.0-alpha.0')); |
649 PluginVersionCheckResult result = | 657 PluginVersionCheckResult result = |
650 new PluginVersionCheckResult.fromResponse(response); | 658 new PluginVersionCheckResult.fromResponse(response); |
651 isCompatible = result.isCompatible; | 659 isCompatible = result.isCompatible; |
652 contactInfo = result.contactInfo; | 660 contactInfo = result.contactInfo; |
653 interestingFiles = result.interestingFiles; | 661 interestingFiles = result.interestingFiles; |
654 name = result.name; | 662 name = result.name; |
655 version = result.version; | 663 version = result.version; |
656 if (!isCompatible) { | 664 if (!isCompatible) { |
657 sendRequest(new PluginShutdownParams()); | 665 sendRequest(new PluginShutdownParams()); |
658 return false; | 666 return false; |
659 } | 667 } |
660 return true; | 668 return true; |
661 } | 669 } |
662 | 670 |
663 /** | 671 /** |
664 * Request that the plugin shutdown. | 672 * Request that the plugin shutdown. |
665 */ | 673 */ |
666 Future<Null> stop() { | 674 Future<Null> stop() { |
667 if (channel == null) { | 675 if (channel == null) { |
668 throw new StateError('Cannot stop a plugin that is not running.'); | 676 throw new StateError('Cannot stop a plugin that is not running.'); |
669 } | 677 } |
670 // TODO(brianwilkerson) Ensure that the isolate is killed if it does not | 678 // TODO(brianwilkerson) Ensure that the isolate is killed if it does not |
671 // terminate normally. | 679 // terminate normally. |
672 sendRequest(new PluginShutdownParams()); | 680 sendRequest(new PluginShutdownParams()); |
673 return pluginStoppedCompleter.future; | 681 return pluginStoppedCompleter.future; |
674 } | 682 } |
675 } | 683 } |
OLD | NEW |