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

Side by Side Diff: tools/ddbg_service/lib/debugger.dart

Issue 1497033003: - Remove the legacy debug protocol. (Closed) Base URL: git@github.com:dart-lang/sdk.git@master
Patch Set: Address review comments. Created 5 years 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
« no previous file with comments | « tools/ddbg_service/lib/commando.dart ('k') | tools/ddbg_service/lib/terminfo.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2014, 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 library debugger;
6
7 import "dart:async";
8 import "dart:io";
9
10 import "package:ddbg/commando.dart";
11 import "package:observatory/service_io.dart";
12
13 class Debugger {
14 Commando cmdo;
15 var _cmdoSubscription;
16
17 CommandList _commands;
18
19 VM _vm;
20 VM get vm => _vm;
21 set vm(VM vm) {
22 if (_vm == vm) {
23 // Do nothing.
24 return;
25 }
26 if (_vm != null) {
27 _vm.disconnect();
28 }
29 if (vm != null) {
30 vm.onConnect.then(_vmConnected);
31 vm.onDisconnect.then(_vmDisconnected);
32 vm.errors.stream.listen(_onServiceError);
33 vm.exceptions.stream.listen(_onServiceException);
34 vm.events.stream.listen(_onServiceEvent);
35 }
36 _vm = vm;
37 }
38
39 _vmConnected(VM vm) {
40 cmdo.print('Connected to vm');
41 }
42
43 _vmDisconnected(VM vm) {
44 cmdo.print('Disconnected from vm');
45 }
46
47 _onServiceError(ServiceError error) {
48 cmdo.print('error $error');
49 }
50
51 _onServiceException(ServiceException exception) {
52 cmdo.print('${exception.message}');
53 }
54
55 _onServiceEvent(ServiceEvent event) {
56 switch (event.eventType) {
57 case 'GC':
58 // Ignore GC events for now.
59 break;
60 default:
61 cmdo.print('event $event');
62 break;
63 }
64 }
65
66 VM _isolate;
67 VM get isolate => _isolate;
68 set isolate(Isolate isolate) {
69 _isolate = isolate;
70 cmdo.print('Current isolate is now isolate ${getIsolateIndex(_isolate)}');
71 }
72
73 Map _isolateIndexMap = new Map();
74 int _nextIsolateIndex = 0;
75 int getIsolateIndex(Isolate isolate) {
76 var index = _isolateIndexMap[isolate.id];
77 if (index == null) {
78 index = _nextIsolateIndex++;
79 _isolateIndexMap[isolate.id] = index;
80 }
81 return index;
82 }
83
84 void onUncaughtError(error, StackTrace trace) {
85 if (error is ServiceException ||
86 error is ServiceError) {
87 // These are handled elsewhere. Ignore.
88 return;
89 }
90 cmdo.print('\n--------\nExiting due to unexpected error:\n'
91 ' $error\n$trace\n');
92 quit();
93 }
94
95 Debugger() {
96 cmdo = new Commando(completer: _completeCommand);
97 _cmdoSubscription = cmdo.commands.listen(_processCommand,
98 onError: _cmdoError,
99 onDone: _cmdoDone);
100 _commands = new CommandList();
101 _commands.register(new AttachCommand());
102 _commands.register(new DetachCommand());
103 _commands.register(new HelpCommand(_commands));
104 _commands.register(new IsolateCommand());
105 _commands.register(new QuitCommand());
106 }
107
108 Future _closeCmdo() {
109 var sub = _cmdoSubscription;
110 _cmdoSubscription = null;
111 cmdo = null;
112
113 var future = sub.cancel();
114 if (future != null) {
115 return future;
116 } else {
117 return new Future.value();
118 }
119 }
120
121 Future quit() {
122 return Future.wait([_closeCmdo()]).then((_) {
123 exit(0);
124 });
125 }
126
127 void _cmdoError(error, StackTrace trace) {
128 cmdo.print('\n--------\nExiting due to unexpected error:\n'
129 ' $error\n$trace\n');
130 quit();
131 }
132
133 void _cmdoDone() {
134 quit();
135 }
136
137 List<String> _completeCommand(List<String> commandParts) {
138 return _commands.complete(commandParts);
139 }
140
141 void _processCommand(String cmdLine) {
142 void huh() {
143 cmdo.print("'$cmdLine' not understood, try 'help' for help.");
144 }
145
146 cmdo.hide();
147 cmdLine = cmdLine.trim();
148 var args = cmdLine.split(' ');
149 if (args.length == 0) {
150 return;
151 }
152 var command = args[0];
153 var matches = _commands.match(command, true);
154 if (matches.length == 0) {
155 huh();
156 cmdo.show();
157 } else if (matches.length == 1) {
158 matches[0].run(this, args).then((_) {
159 cmdo.show();
160 });
161 } else {
162 var matchNames = matches.map((handler) => handler.name);
163 cmdo.print("Ambiguous command '$command' : ${matchNames.toList()}");
164 cmdo.show();
165 }
166 }
167
168 }
169
170 // Every debugger command extends this base class.
171 abstract class Command {
172 String get name;
173 String get helpShort;
174 void printHelp(Debugger debugger, List<String> args);
175 Future run(Debugger debugger, List<String> args);
176 List<String> complete(List<String> commandParts) {
177 return ["$name ${commandParts.join(' ')}"];
178
179 }
180 }
181
182 class AttachCommand extends Command {
183 final name = 'attach';
184 final helpShort = 'Attach to a running Dart VM';
185 void printHelp(Debugger debugger, List<String> args) {
186 debugger.cmdo.print('''
187 ----- attach -----
188
189 Attach to the Dart VM running at the indicated host:port. If no
190 host:port is provided, attach to the VM running on the default port.
191
192 Usage:
193 attach
194 attach <host:port>
195 ''');
196 }
197
198 Future run(Debugger debugger, List<String> args) {
199 var cmdo = debugger.cmdo;
200 if (args.length > 2) {
201 cmdo.print('$name expects 0 or 1 arguments');
202 return new Future.value();
203 }
204 String hostPort = 'localhost:8181';
205 if (args.length > 1) {
206 hostPort = args[1];
207 }
208
209 debugger.vm = new WebSocketVM(new WebSocketVMTarget('ws://${hostPort}/ws'));
210 return debugger.vm.load().then((vm) {
211 if (debugger.isolate == null) {
212 for (var isolate in vm.isolates) {
213 if (isolate.name == 'root') {
214 debugger.isolate = isolate;
215 }
216 }
217 }
218 });
219 }
220 }
221
222 class CommandList {
223 List _commands = new List<Command>();
224
225 void register(Command cmd) {
226 _commands.add(cmd);
227 }
228
229 List<Command> match(String commandName, bool exactMatchWins) {
230 var matches = [];
231 for (var command in _commands) {
232 if (command.name.startsWith(commandName)) {
233 if (exactMatchWins && command.name == commandName) {
234 // Exact match
235 return [command];
236 } else {
237 matches.add(command);
238 }
239 }
240 }
241 return matches;
242 }
243
244 List<String> complete(List<String> commandParts) {
245 var completions = new List<String>();
246 String prefix = commandParts[0];
247 for (var command in _commands) {
248 if (command.name.startsWith(prefix)) {
249 completions.addAll(command.complete(commandParts.sublist(1)));
250 }
251 }
252 return completions;
253 }
254
255 void printHelp(Debugger debugger, List<String> args) {
256 var cmdo = debugger.cmdo;
257 if (args.length <= 1) {
258 cmdo.print("\nDebugger commands:\n");
259 for (var command in _commands) {
260 cmdo.print(' ${command.name.padRight(11)} ${command.helpShort}');
261 }
262 cmdo.print("For more information about a particular command, type:\n\n"
263 " help <command>\n");
264
265 cmdo.print("Commands may be abbreviated: e.g. type 'h' for 'help.\n");
266 } else {
267 var commandName = args[1];
268 var matches =match(commandName, true);
269 if (matches.length == 0) {
270 cmdo.print("Command '$commandName' not recognized. "
271 "Try 'help' for a list of commands.");
272 } else {
273 for (var command in matches) {
274 command.printHelp(debugger, args);
275 }
276 }
277 }
278 }
279 }
280
281 class DetachCommand extends Command {
282 final name = 'detach';
283 final helpShort = 'Detach from a running Dart VM';
284 void printHelp(Debugger debugger, List<String> args) {
285 debugger.cmdo.print('''
286 ----- detach -----
287
288 Detach from the Dart VM.
289
290 Usage:
291 detach
292 ''');
293 }
294
295 Future run(Debugger debugger, List<String> args) {
296 var cmdo = debugger.cmdo;
297 if (args.length > 1) {
298 cmdo.print('$name expects no arguments');
299 return new Future.value();
300 }
301 if (debugger.vm == null) {
302 cmdo.print('No VM is attached');
303 } else {
304 debugger.vm = null;
305 }
306 return new Future.value();
307 }
308 }
309
310 class HelpCommand extends Command {
311 HelpCommand(this._commands);
312 final CommandList _commands;
313
314 final name = 'help';
315 final helpShort = 'Show a list of debugger commands';
316 void printHelp(Debugger debugger, List<String> args) {
317 debugger.cmdo.print('''
318 ----- help -----
319
320 Show a list of debugger commands or get more information about a
321 particular command.
322
323 Usage:
324 help
325 help <command>
326 ''');
327 }
328
329 Future run(Debugger debugger, List<String> args) {
330 _commands.printHelp(debugger, args);
331 return new Future.value();
332 }
333
334 List<String> complete(List<String> commandParts) {
335 if (commandParts.isEmpty) {
336 return ['$name '];
337 }
338 return _commands.complete(commandParts).map((value) {
339 return '$name $value';
340 });
341 }
342 }
343
344 class IsolateCommand extends Command {
345 final name = 'isolate';
346 final helpShort = 'Isolate control';
347 void printHelp(Debugger debugger, List<String> args) {
348 debugger.cmdo.print('''
349 ----- isolate -----
350
351 List all isolates.
352
353 Usage:
354 isolate
355 isolate list
356
357 Set current isolate.
358
359 Usage:
360 isolate <id>
361 ''');
362 }
363
364 Future run(Debugger debugger, List<String> args) {
365 var cmdo = debugger.cmdo;
366 if (args.length == 1 ||
367 (args.length == 2 && args[1] == 'list')) {
368 return _listIsolates(debugger);
369 } else if (args.length == 2) {
370 cmdo.print('UNIMPLEMENTED');
371 return new Future.value();
372 } else {
373 if (args.length > 1) {
374 cmdo.print('Unrecognized isolate command');
375 printHelp(debugger, []);
376 return new Future.value();
377 }
378 }
379 }
380
381 Future _listIsolates(Debugger debugger) {
382 var cmdo = debugger.cmdo;
383 if (debugger.vm == null) {
384 cmdo.print('No VM is attached');
385 return new Future.value();
386 }
387 return debugger.vm.reload().then((vm) {
388 // Sort the isolates by their indices.
389 var isolates = vm.isolates.toList();
390 isolates.sort((iso1, iso2) {
391 return (debugger.getIsolateIndex(iso1) -
392 debugger.getIsolateIndex(iso2));
393 });
394
395 StringBuffer sb = new StringBuffer();
396 cmdo.print(' ID NAME STATE');
397 cmdo.print('-----------------------------------------------');
398 for (var isolate in isolates) {
399 if (isolate == debugger.isolate) {
400 sb.write('* ');
401 } else {
402 sb.write(' ');
403 }
404 sb.write(debugger.getIsolateIndex(isolate).toString().padRight(8));
405 sb.write(' ');
406 sb.write(isolate.name.padRight(12));
407 sb.write(' ');
408 if (isolate.pauseEvent != null) {
409 switch (isolate.pauseEvent.eventType) {
410 case 'IsolateCreated':
411 sb.write('paused at isolate start');
412 break;
413 case 'IsolateShutdown':
414 sb.write('paused at isolate exit');
415 break;
416 case 'IsolateInterrupted':
417 sb.write('paused');
418 break;
419 case 'BreakpointReached':
420 sb.write('paused by breakpoint');
421 break;
422 case 'ExceptionThrown':
423 sb.write('paused by exception');
424 break;
425 default:
426 sb.write('paused by unknown cause');
427 break;
428 }
429 } else if (isolate.running) {
430 sb.write('running');
431 } else if (isolate.idle) {
432 sb.write('idle');
433 } else if (isolate.loading) {
434 // TODO(turnidge): This is weird in a command line debugger.
435 sb.write('(not available)');
436 }
437 sb.write('\n');
438 }
439 cmdo.print(sb);
440 });
441 return new Future.value();
442 }
443
444 List<String> complete(List<String> commandParts) {
445 if (commandParts.isEmpty) {
446 return ['$name ${commandParts.join(" ")}'];
447 } else {
448 var completions = _commands.complete(commandParts);
449 return completions.map((completion) {
450 return '$name $completion';
451 });
452 }
453 }
454 }
455
456 class QuitCommand extends Command {
457 final name = 'quit';
458 final helpShort = 'Quit the debugger.';
459 void printHelp(Debugger debugger, List<String> args) {
460 debugger.cmdo.print('''
461 ----- quit -----
462
463 Quit the debugger.
464
465 Usage:
466 quit
467 ''');
468 }
469
470 Future run(Debugger debugger, List<String> args) {
471 var cmdo = debugger.cmdo;
472 if (args.length > 1) {
473 cmdo.print("Unexpected arguments to $name command.");
474 return new Future.value();
475 }
476 return debugger.quit();
477 }
478 }
OLDNEW
« no previous file with comments | « tools/ddbg_service/lib/commando.dart ('k') | tools/ddbg_service/lib/terminfo.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698