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 8aa8f72b25d2fc119bb9da4640337788f1448cb1..65c33cd445686076c75834359a46c507df3d7f23 100644 |
--- a/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
+++ b/pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart |
@@ -12,6 +12,74 @@ import 'package:analyzer_plugin/protocol/protocol.dart'; |
import 'package:analyzer_plugin/protocol/protocol_generated.dart'; |
/** |
+ * The type of the function used to run a built-in plugin in an isolate. |
+ */ |
+typedef void EntryPoint(SendPort sendPort); |
+ |
+/** |
+ * A communication channel appropriate for built-in plugins. |
+ */ |
+class BuiltInServerIsolateChannel extends ServerIsolateChannel { |
+ /** |
+ * The entry point |
+ */ |
+ final EntryPoint entryPoint; |
+ |
+ @override |
+ final String pluginId; |
+ |
+ /** |
+ * Initialize a newly created channel to communicate with an isolate running |
+ * the given [entryPoint]. |
+ */ |
+ BuiltInServerIsolateChannel(this.entryPoint, this.pluginId, |
+ InstrumentationService instrumentationService) |
+ : super._(instrumentationService); |
+ |
+ @override |
+ Future<Isolate> _spawnIsolate() { |
+ return Isolate.spawn(entryPoint, _receivePort.sendPort, |
+ onError: _errorPort?.sendPort, onExit: _exitPort?.sendPort); |
+ } |
+} |
+ |
+/** |
+ * A communication channel appropriate for discovered plugins. |
+ */ |
+class DiscoveredServerIsolateChannel extends ServerIsolateChannel { |
+ /** |
+ * The URI for the Dart file that will be run in the isolate that this channel |
+ * communicates with. |
+ */ |
+ final Uri pluginUri; |
+ |
+ /** |
+ * The URI for the '.packages' file that will control how 'package:' URIs are |
+ * resolved. |
+ */ |
+ final Uri packagesUri; |
+ |
+ /** |
+ * Initialize a newly created channel to communicate with an isolate running |
+ * the code at the given [uri]. |
+ */ |
+ DiscoveredServerIsolateChannel(this.pluginUri, this.packagesUri, |
+ InstrumentationService instrumentationService) |
+ : super._(instrumentationService); |
+ |
+ @override |
+ String get pluginId => pluginUri.toString(); |
+ |
+ @override |
+ Future<Isolate> _spawnIsolate() { |
+ return Isolate.spawnUri(pluginUri, <String>[], _receivePort.sendPort, |
+ onError: _errorPort?.sendPort, |
+ onExit: _exitPort?.sendPort, |
+ packageConfig: packagesUri); |
+ } |
+} |
+ |
+/** |
* The object that allows a [ServerPlugin] to receive [Request]s and to return |
* both [Response]s and [Notification]s. It communicates with the analysis |
* server by passing data to the server's main isolate. |
@@ -83,22 +151,10 @@ class PluginIsolateChannel implements PluginCommunicationChannel { |
} |
/** |
- * The communication channel that allows an analysis server to send [Request]s |
+ * A 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 Dart file that will be run in the isolate that this channel |
- * communicates with. |
- */ |
- final Uri pluginUri; |
- |
- /** |
- * The URI for the '.packages' file that will control how 'package:' URIs are |
- * resolved. |
- */ |
- final Uri packagesUri; |
- |
+abstract class ServerIsolateChannel implements ServerCommunicationChannel { |
/** |
* The instrumentation service that is being used by the analysis server. |
*/ |
@@ -132,11 +188,32 @@ class ServerIsolateChannel implements ServerCommunicationChannel { |
ReceivePort _exitPort; |
/** |
- * Initialize a newly created channel to communicate with an isolate running |
- * the code at the given [uri]. |
+ * Return a communication channel appropriate for communicating with a |
+ * built-in plugin. |
*/ |
- ServerIsolateChannel( |
- this.pluginUri, this.packagesUri, this.instrumentationService); |
+ factory ServerIsolateChannel.builtIn(EntryPoint entryPoint, String pluginId, |
+ InstrumentationService instrumentationService) = |
+ BuiltInServerIsolateChannel; |
+ |
+ /** |
+ * Return a communication channel appropriate for communicating with a |
+ * discovered plugin. |
+ */ |
+ factory ServerIsolateChannel.discovered(Uri pluginUri, Uri packagesUri, |
+ InstrumentationService instrumentationService) = |
+ DiscoveredServerIsolateChannel; |
+ |
+ /** |
+ * Initialize a newly created channel. |
+ */ |
+ ServerIsolateChannel._(this.instrumentationService); |
+ |
+ /** |
+ * Return the id of the plugin running in the isolate, used to identify the |
+ * plugin to the instrumentation service. |
+ */ |
+ String get pluginId; |
+ |
@override |
void close() { |
_receivePort?.close(); |
@@ -166,14 +243,10 @@ class ServerIsolateChannel implements ServerCommunicationChannel { |
}); |
} |
try { |
- _isolate = await Isolate.spawnUri( |
- pluginUri, <String>[], _receivePort.sendPort, |
- onError: _errorPort?.sendPort, |
- onExit: _exitPort?.sendPort, |
- packageConfig: packagesUri); |
+ _isolate = await _spawnIsolate(); |
} catch (exception, stackTrace) { |
instrumentationService.logPluginError( |
- new PluginData(pluginUri.toString(), null, null), |
+ new PluginData(pluginId, null, null), |
RequestErrorCode.PLUGIN_ERROR.toString(), |
exception.toString(), |
stackTrace.toString()); |
@@ -191,11 +264,11 @@ class ServerIsolateChannel implements ServerCommunicationChannel { |
} else if (input is Map) { |
if (input.containsKey('id')) { |
String encodedInput = JSON.encode(input); |
- instrumentationService.logPluginResponse(pluginUri, encodedInput); |
+ instrumentationService.logPluginResponse(pluginId, encodedInput); |
onResponse(new Response.fromJson(input)); |
} else if (input.containsKey('event')) { |
String encodedInput = JSON.encode(input); |
- instrumentationService.logPluginNotification(pluginUri, encodedInput); |
+ instrumentationService.logPluginNotification(pluginId, encodedInput); |
onNotification(new Notification.fromJson(input)); |
} |
} |
@@ -207,8 +280,12 @@ class ServerIsolateChannel implements ServerCommunicationChannel { |
void sendRequest(Request request) { |
Map<String, Object> json = request.toJson(); |
String encodedRequest = JSON.encode(json); |
-// print('[server] Send request: $encodedRequest'); |
- instrumentationService.logPluginRequest(pluginUri, encodedRequest); |
+ instrumentationService.logPluginRequest(pluginId, encodedRequest); |
_sendPort.send(json); |
} |
+ |
+ /** |
+ * Spawn the isolate in which the plugin is running. |
+ */ |
+ Future<Isolate> _spawnIsolate(); |
} |