Index: pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
diff --git a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
index a7ccafc82ea823b79288bdc92ce7d67ccff7953f..c3048d4201d639a4d1565cfd3bc1b8c02848f851 100644 |
--- a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
+++ b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
@@ -13,7 +13,7 @@ import 'package:analyzer_plugin/protocol/protocol.dart'; |
* both [Response]s and [Notification]s. It communicates with the analysis |
* server by passing data to the server's main isolate. |
*/ |
-class IsolateChannel implements PluginCommunicationChannel { |
+class PluginIsolateChannel implements PluginCommunicationChannel { |
/** |
* The port used to send notifications and responses to the server. |
*/ |
@@ -32,7 +32,7 @@ class IsolateChannel implements PluginCommunicationChannel { |
/** |
* Initialize a newly created channel to communicate with the server. |
*/ |
- IsolateChannel(this._sendPort) { |
+ PluginIsolateChannel(this._sendPort) { |
_receivePort = new ReceivePort(); |
_sendPort.send(_receivePort.sendPort); |
} |
@@ -73,3 +73,83 @@ class IsolateChannel implements PluginCommunicationChannel { |
_sendPort.send(response.toJson()); |
} |
} |
+ |
+/** |
+ * The communication channel that allows an analysis server to send [Request]s |
+ * to, and to receive both [Response]s and [Notification]s from, a plugin. |
+ */ |
+class ServerIsolateChannel implements ServerCommunicationChannel { |
+ /** |
+ * The URI for the plugin that will be run in the isolate that this channel |
+ * communicates with. |
+ */ |
+ final Uri uri; |
+ |
+ /** |
+ * The isolate in which the plugin is running, or `null` if the plugin has |
+ * not yet been started by invoking [listen]. |
+ */ |
+ Isolate _isolate; |
+ |
+ /** |
+ * The port used to send requests to the plugin, or `null` if the plugin has |
+ * not yet been started by invoking [listen]. |
+ */ |
+ SendPort _sendPort; |
+ |
+ /** |
+ * Initialize a newly created channel to communicate with an isolate running |
+ * the code at the given [uri]. |
+ */ |
+ ServerIsolateChannel(this.uri); |
+ |
+ @override |
+ void close() { |
+ // TODO(brianwilkerson) Is there anything useful to do here? |
+ _isolate = null; |
+ _sendPort = null; |
+ } |
+ |
+ @override |
+ Future<Null> listen(void onResponse(Response response), |
+ void onNotification(Notification notification), |
+ {Function onError, void onDone()}) async { |
+ if (_isolate != null) { |
+ throw new StateError('Cannot listen to the same channel more than once.'); |
+ } |
+ ReceivePort receivePort = new ReceivePort(); |
+ ReceivePort errorPort; |
+ if (onError != null) { |
+ errorPort = new ReceivePort(); |
+ errorPort.listen((error) { |
+ onError(error); |
+ }); |
+ } |
+ ReceivePort exitPort; |
+ if (onDone != null) { |
+ exitPort = new ReceivePort(); |
+ exitPort.listen((_) { |
+ onDone(); |
+ }); |
+ } |
+ _isolate = await Isolate.spawnUri(uri, <String>[], receivePort.sendPort, |
+ automaticPackageResolution: true, |
+ onError: errorPort?.sendPort, |
+ onExit: exitPort?.sendPort); |
+ _sendPort = await receivePort.first as SendPort; |
+ receivePort.listen((dynamic input) { |
+ if (input is Map) { |
+ if (input.containsKey('id') != null) { |
+ onResponse(new Response.fromJson(input)); |
+ } else if (input.containsKey('event')) { |
+ onNotification(new Notification.fromJson(input)); |
+ } |
+ } |
+ }); |
+ } |
+ |
+ @override |
+ void sendRequest(Request request) { |
+ _sendPort.send(request.toJson()); |
+ } |
+} |