Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(198)

Side by Side Diff: pkg/analyzer_plugin/lib/src/channel/isolate_channel.dart

Issue 2676633003: Add server-side communications channel (Closed)
Patch Set: Created 3 years, 10 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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:isolate'; 6 import 'dart:isolate';
7 7
8 import 'package:analyzer_plugin/channel/channel.dart'; 8 import 'package:analyzer_plugin/channel/channel.dart';
9 import 'package:analyzer_plugin/protocol/protocol.dart'; 9 import 'package:analyzer_plugin/protocol/protocol.dart';
10 10
11 /** 11 /**
12 * The object that allows a [ServerPlugin] to receive [Request]s and to return 12 * The object that allows a [ServerPlugin] to receive [Request]s and to return
13 * both [Response]s and [Notification]s. It communicates with the analysis 13 * both [Response]s and [Notification]s. It communicates with the analysis
14 * server by passing data to the server's main isolate. 14 * server by passing data to the server's main isolate.
15 */ 15 */
16 class IsolateChannel implements PluginCommunicationChannel { 16 class PluginIsolateChannel implements PluginCommunicationChannel {
17 /** 17 /**
18 * The port used to send notifications and responses to the server. 18 * The port used to send notifications and responses to the server.
19 */ 19 */
20 SendPort _sendPort; 20 SendPort _sendPort;
21 21
22 /** 22 /**
23 * The port used to receive requests from the server. 23 * The port used to receive requests from the server.
24 */ 24 */
25 ReceivePort _receivePort; 25 ReceivePort _receivePort;
26 26
27 /** 27 /**
28 * The subscription that needs to be cancelled when the channel is closed. 28 * The subscription that needs to be cancelled when the channel is closed.
29 */ 29 */
30 StreamSubscription _subscription; 30 StreamSubscription _subscription;
31 31
32 /** 32 /**
33 * Initialize a newly created channel to communicate with the server. 33 * Initialize a newly created channel to communicate with the server.
34 */ 34 */
35 IsolateChannel(this._sendPort) { 35 PluginIsolateChannel(this._sendPort) {
36 _receivePort = new ReceivePort(); 36 _receivePort = new ReceivePort();
37 _sendPort.send(_receivePort.sendPort); 37 _sendPort.send(_receivePort.sendPort);
38 } 38 }
39 39
40 @override 40 @override
41 void close() { 41 void close() {
42 if (_subscription != null) { 42 if (_subscription != null) {
43 _subscription.cancel(); 43 _subscription.cancel();
44 _subscription = null; 44 _subscription = null;
45 } 45 }
(...skipping 20 matching lines...) Expand all
66 @override 66 @override
67 void sendNotification(Notification notification) { 67 void sendNotification(Notification notification) {
68 _sendPort.send(notification.toJson()); 68 _sendPort.send(notification.toJson());
69 } 69 }
70 70
71 @override 71 @override
72 void sendResponse(Response response) { 72 void sendResponse(Response response) {
73 _sendPort.send(response.toJson()); 73 _sendPort.send(response.toJson());
74 } 74 }
75 } 75 }
76
77 /**
78 * The communication channel that allows an analysis server to send [Request]s
79 * to, and to receive both [Response]s and [Notification]s from, a plugin.
80 */
81 class ServerIsolateChannel implements ServerCommunicationChannel {
82 /**
83 * The URI for the plugin that will be run in the isolate that this channel
84 * communicates with.
85 */
86 final Uri uri;
87
88 /**
89 * The isolate in which the plugin is running, or `null` if the plugin has
90 * not yet been started by invoking [listen].
91 */
92 Isolate _isolate;
93
94 /**
95 * The port used to send requests to the plugin, or `null` if the plugin has
96 * not yet been started by invoking [listen].
97 */
98 SendPort _sendPort;
99
100 /**
101 * Initialize a newly created channel to communicate with an isolate running
102 * the code at the given [uri].
103 */
104 ServerIsolateChannel(this.uri);
105
106 @override
107 void close() {
108 // TODO(brianwilkerson) Is there anything useful to do here?
109 _isolate = null;
110 _sendPort = null;
111 }
112
113 @override
114 Future<Null> listen(void onResponse(Response response),
115 void onNotification(Notification notification),
116 {Function onError, void onDone()}) async {
117 if (_isolate != null) {
118 throw new StateError('Cannot listen to the same channel more than once.');
119 }
120 ReceivePort receivePort = new ReceivePort();
121 ReceivePort errorPort;
122 if (onError != null) {
123 errorPort = new ReceivePort();
124 errorPort.listen((error) {
125 onError(error);
126 });
127 }
128 ReceivePort exitPort;
129 if (onDone != null) {
130 exitPort = new ReceivePort();
131 exitPort.listen((_) {
132 onDone();
133 });
134 }
135 _isolate = await Isolate.spawnUri(uri, <String>[], receivePort.sendPort,
136 automaticPackageResolution: true,
137 onError: errorPort?.sendPort,
138 onExit: exitPort?.sendPort);
139 _sendPort = await receivePort.first as SendPort;
140 receivePort.listen((dynamic input) {
141 if (input is Map) {
142 if (input.containsKey('id') != null) {
143 onResponse(new Response.fromJson(input));
144 } else if (input.containsKey('event')) {
145 onNotification(new Notification.fromJson(input));
146 }
147 }
148 });
149 }
150
151 @override
152 void sendRequest(Request request) {
153 _sendPort.send(request.toJson());
154 }
155 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698