OLD | NEW |
---|---|
(Empty) | |
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 | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 import 'dart:async'; | |
6 import 'dart:convert'; | |
7 import 'dart:io'; | |
8 | |
9 /// Type of callbacks used to process notification. | |
10 typedef void NotificationProcessor(String event, Map<String, Object> params); | |
11 | |
12 /// Instances of the class [AnalysisServerClient] manage a connection to an | |
13 /// [AnalysisServer] process, and facilitate communication to and from the | |
14 /// client/user. | |
15 class AnalysisServerClient { | |
16 /// AnalysisServer process object, or null if the server has been shut down. | |
17 Process _process; | |
scheglov
2017/08/08 21:18:56
final?
| |
18 | |
19 /// Commands that have been sent to the server but not yet acknowledged, | |
20 /// and the [Completer] objects which should be completed when | |
21 /// acknowledgement is received. | |
22 final Map<String, Completer> _pendingCommands = <String, Completer>{}; | |
23 | |
24 /// Number which should be used to compute the 'id' to send to the next | |
25 /// command sent to the server. | |
26 int _nextId = 0; | |
27 | |
28 AnalysisServerClient(this._process); | |
29 | |
30 /// Return a future that will complete when all commands that have been | |
31 /// sent to the server so far have been flushed to the OS buffer. | |
32 Future flushCommands() { | |
scheglov
2017/08/08 21:18:56
Future<Null>, I presume?
| |
33 return _process.stdin.flush(); | |
34 } | |
35 | |
36 void listenToOutput({NotificationProcessor notificationProcessor}) { | |
37 _process.stdout | |
38 .transform((new Utf8Codec()).decoder) | |
39 .transform(new LineSplitter()) | |
40 .listen((String line) { | |
41 String trimmedLine = line.trim(); | |
42 if (trimmedLine.startsWith('Observatory listening on ')) { | |
43 return; | |
44 } | |
45 final result = JSON.decoder.convert(trimmedLine) as Map; | |
46 if (result.containsKey('id')) { | |
47 final id = result['id'] as String; | |
48 final completer = _pendingCommands[id]; | |
49 _pendingCommands.remove(id); | |
scheglov
2017/08/08 21:18:56
Map.remove() already return the value.
| |
50 | |
51 if (result.containsKey('error')) { | |
52 completer.completeError(new ServerErrorMessage(result['error'])); | |
53 } else { | |
54 completer.complete(result['result']); | |
55 } | |
56 } else if (notificationProcessor != null && result.containsKey('event')) { | |
57 // Message is a notification. It should have an event and possibly | |
58 // params. | |
59 notificationProcessor(result['event'], result['params']); | |
60 } | |
61 }); | |
62 } | |
63 | |
64 /// Sends a command to the server. An 'id' will be automatically assigned. | |
65 /// The returned [Future] will be completed when the server acknowledges | |
66 /// the command with a response. If the server acknowledges the command | |
67 /// with a normal (non-error) response, the future will be completed | |
68 /// with the 'result' field from the response. If the server acknowledges | |
69 /// the command with an error response, the future will be completed with an | |
70 /// error. | |
71 Future send(String method, Map<String, dynamic> params) { | |
72 String id = '${_nextId++}'; | |
73 Map<String, dynamic> command = <String, dynamic>{ | |
74 'id': id, | |
75 'method': method | |
76 }; | |
77 if (params != null) { | |
78 command['params'] = params; | |
79 } | |
80 Completer completer = new Completer(); | |
81 _pendingCommands[id] = completer; | |
82 String commandAsJson = JSON.encode(command); | |
83 _process.stdin.add(UTF8.encoder.convert('$commandAsJson\n')); | |
84 return completer.future; | |
85 } | |
86 | |
87 /// Force kill the server. Returns exit code future. | |
88 Future<int> kill() { | |
89 _process.kill(); | |
90 return _process.exitCode; | |
91 } | |
92 } | |
93 | |
94 class ServerErrorMessage { | |
95 final Map errorJson; | |
96 | |
97 ServerErrorMessage(this.errorJson); | |
98 | |
99 String get code => errorJson['code'].toString(); | |
100 String get message => errorJson['message']; | |
101 String get stackTrace => errorJson['stackTrace']; | |
102 } | |
OLD | NEW |