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

Side by Side Diff: runtime/observatory/lib/src/elements/debugger.dart

Issue 921893004: Implement 'help' command for Observatory debugger. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Created 5 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 | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file 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 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 library debugger_page_element; 5 library debugger_page_element;
6 6
7 import 'dart:async'; 7 import 'dart:async';
8 import 'dart:html'; 8 import 'dart:html';
9 import 'observatory_element.dart'; 9 import 'observatory_element.dart';
10 import 'package:observatory/cli.dart'; 10 import 'package:observatory/cli.dart';
11 import 'package:observatory/debugger.dart'; 11 import 'package:observatory/debugger.dart';
12 import 'package:observatory/service.dart'; 12 import 'package:observatory/service.dart';
13 import 'package:polymer/polymer.dart'; 13 import 'package:polymer/polymer.dart';
14 14
15 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library. 15 // TODO(turnidge): Move Debugger, DebuggerCommand to debugger library.
16 abstract class DebuggerCommand extends Command { 16 abstract class DebuggerCommand extends Command {
17 ObservatoryDebugger debugger; 17 ObservatoryDebugger debugger;
18 18
19 DebuggerCommand(this.debugger, name, children) 19 DebuggerCommand(this.debugger, name, children)
20 : super(name, children); 20 : super(name, children);
21
22 String get helpShort;
23 String get helpLong;
21 } 24 }
22 25
26 // TODO(turnidge): Rewrite HelpCommand so that it is a general utility
27 // provided by the cli library.
23 class HelpCommand extends DebuggerCommand { 28 class HelpCommand extends DebuggerCommand {
24 HelpCommand(Debugger debugger) : super(debugger, 'help', []); 29 HelpCommand(Debugger debugger) : super(debugger, 'help', []);
25 30
26 Future run(List<String> args) { 31 Future run(List<String> args) {
27 var con = debugger.console; 32 var con = debugger.console;
28 con.printLine('List of commands:'); 33 if (args.length == 0) {
29 con.newline(); 34 // Print list of all top-level commands.
35 var commands = debugger.cmd.matchCommand([], false);
36 commands.sort((a, b) => a.name.compareTo(b.name));
37 con.print('List of commands:\n');
38 for (var command in commands) {
39 con.print('${command.name.padRight(12)} - ${command.helpShort}');
40 }
41 con.print(
42 "\nFor more information on a specific command type 'help <command>'\n"
43 "\n"
44 "Command prefixes are accepted (e.g. 'h' for 'help')\n"
45 "Hit [TAB] to complete a command (try 'i[TAB][TAB]')\n"
46 "Hit [ENTER] to repeat the last command\n");
47 return new Future.value(null);
48 } else {
49 // Print any matching commands.
50 var commands = debugger.cmd.matchCommand(args, true);
51 commands.sort((a, b) => a.name.compareTo(b.name));
52 if (commands.isEmpty) {
53 var line = args.join(' ');
54 con.print("No command matches '${line}'");
55 return new Future.value(null);
56 }
57 con.print('');
58 for (var command in commands) {
59 con.printBold(command.fullName);
60 con.print(command.helpLong);
30 61
31 // TODO(turnidge): Build a real help system. 62 var newArgs = [];
32 return debugger.cmd.completeCommand('').then((completions) { 63 newArgs.addAll(args.take(args.length - 1));
33 completions = completions.map((s) => s.trimRight()).toList(); 64 newArgs.add(command.name);
34 completions.sort(); 65 newArgs.add('');
35 con.printLine(completions.toString()); 66 var subCommands = debugger.cmd.matchCommand(newArgs, false);
36 con.newline(); 67 subCommands.remove(command);
37 con.printLine("Command prefixes are accepted (e.g. 'h' for 'help')"); 68 if (subCommands.isNotEmpty) {
38 con.printLine("Hit [TAB] to complete a command (try 'i[TAB][TAB]')"); 69 subCommands.sort((a, b) => a.name.compareTo(b.name));
39 con.printLine("Hit [ENTER] to repeat the last command"); 70 con.print('Subcommands:\n');
40 }); 71 for (var subCommand in subCommands) {
72 con.print(' ${subCommand.fullName.padRight(16)} '
73 '- ${subCommand.helpShort}');
74 }
75 con.print('');
76 }
77 }
78 return new Future.value(null);
79 }
41 } 80 }
81
82 Future<List<String>> complete(List<String> args) {
83 var commands = debugger.cmd.matchCommand(args, false);
84 var result = commands.map((command) => '${command.fullName} ');
85 return new Future.value(result);
86 }
87
88 String helpShort = 'List commands or provide details about a specific command' ;
89
90 String helpLong =
91 'List commands or provide details about a specific command.\n'
92 '\n'
93 'Syntax: help - Show a list of all commands\n'
94 ' help <command> - Help for a specific command\n';
42 } 95 }
43 96
44 class PauseCommand extends DebuggerCommand { 97 class PauseCommand extends DebuggerCommand {
45 PauseCommand(Debugger debugger) : super(debugger, 'pause', []); 98 PauseCommand(Debugger debugger) : super(debugger, 'pause', []);
46 99
47 Future run(List<String> args) { 100 Future run(List<String> args) {
48 if (!debugger.isolatePaused()) { 101 if (!debugger.isolatePaused()) {
49 return debugger.isolate.pause(); 102 return debugger.isolate.pause();
50 } else { 103 } else {
51 debugger.console.printLine('The program is already paused'); 104 debugger.console.print('The program is already paused');
52 return new Future.value(null); 105 return new Future.value(null);
53 } 106 }
54 } 107 }
108
109 String helpShort = 'Pause the isolate';
110
111 String helpLong =
112 'Pause the isolate.\n'
113 '\n'
114 'Syntax: pause\n';
55 } 115 }
56 116
57 class ContinueCommand extends DebuggerCommand { 117 class ContinueCommand extends DebuggerCommand {
58 ContinueCommand(Debugger debugger) : super(debugger, 'continue', []); 118 ContinueCommand(Debugger debugger) : super(debugger, 'continue', []);
59 119
60 Future run(List<String> args) { 120 Future run(List<String> args) {
61 if (debugger.isolatePaused()) { 121 if (debugger.isolatePaused()) {
62 return debugger.isolate.resume().then((_) { 122 return debugger.isolate.resume().then((_) {
63 debugger.warnOutOfDate(); 123 debugger.warnOutOfDate();
64 }); 124 });
65 } else { 125 } else {
66 debugger.console.printLine('The program must be paused'); 126 debugger.console.print('The program must be paused');
67 return new Future.value(null); 127 return new Future.value(null);
68 } 128 }
69 } 129 }
130
131 String helpShort = 'Resume execution of the isolate';
132
133 String helpLong =
134 'Continue running the isolate.\n'
135 '\n'
136 'Syntax: continue\n';
70 } 137 }
71 138
72 class NextCommand extends DebuggerCommand { 139 class NextCommand extends DebuggerCommand {
73 NextCommand(Debugger debugger) : super(debugger, 'next', []); 140 NextCommand(Debugger debugger) : super(debugger, 'next', []);
74 141
75 Future run(List<String> args) { 142 Future run(List<String> args) {
76 if (debugger.isolatePaused()) { 143 if (debugger.isolatePaused()) {
77 var event = debugger.isolate.pauseEvent; 144 var event = debugger.isolate.pauseEvent;
78 if (event.eventType == 'IsolateCreated') { 145 if (event.eventType == 'IsolateCreated') {
79 debugger.console.printLine("Type 'continue' to start the isolate"); 146 debugger.console.print("Type 'continue' to start the isolate");
80 return new Future.value(null); 147 return new Future.value(null);
81 } 148 }
82 if (event.eventType == 'IsolateShutdown') { 149 if (event.eventType == 'IsolateShutdown') {
83 debugger.console.printLine("Type 'continue' to exit the isolate"); 150 debugger.console.print("Type 'continue' to exit the isolate");
84 return new Future.value(null); 151 return new Future.value(null);
85 } 152 }
86 return debugger.isolate.stepOver(); 153 return debugger.isolate.stepOver();
87 } else { 154 } else {
88 debugger.console.printLine('The program is already running'); 155 debugger.console.print('The program is already running');
89 return new Future.value(null); 156 return new Future.value(null);
90 } 157 }
91 } 158 }
159
160 String helpShort =
161 'Continue running the isolate until it reaches the next source location '
162 'in the current function';
163
164 String helpLong =
165 'Continue running the isolate until it reaches the next source location '
166 'in the current function.\n'
167 '\n'
168 'Syntax: next\n';
92 } 169 }
93 170
94 class StepCommand extends DebuggerCommand { 171 class StepCommand extends DebuggerCommand {
95 StepCommand(Debugger debugger) : super(debugger, 'step', []); 172 StepCommand(Debugger debugger) : super(debugger, 'step', []);
96 173
97 Future run(List<String> args) { 174 Future run(List<String> args) {
98 if (debugger.isolatePaused()) { 175 if (debugger.isolatePaused()) {
99 var event = debugger.isolate.pauseEvent; 176 var event = debugger.isolate.pauseEvent;
100 if (event.eventType == 'IsolateCreated') { 177 if (event.eventType == 'IsolateCreated') {
101 debugger.console.printLine("Type 'continue' to start the isolate"); 178 debugger.console.print("Type 'continue' to start the isolate");
102 return new Future.value(null); 179 return new Future.value(null);
103 } 180 }
104 if (event.eventType == 'IsolateShutdown') { 181 if (event.eventType == 'IsolateShutdown') {
105 debugger.console.printLine("Type 'continue' to exit the isolate"); 182 debugger.console.print("Type 'continue' to exit the isolate");
106 return new Future.value(null); 183 return new Future.value(null);
107 } 184 }
108 return debugger.isolate.stepInto(); 185 return debugger.isolate.stepInto();
109 } else { 186 } else {
110 debugger.console.printLine('The program is already running'); 187 debugger.console.print('The program is already running');
111 return new Future.value(null); 188 return new Future.value(null);
112 } 189 }
113 } 190 }
191
192 String helpShort =
193 'Continue running the isolate until it reaches the next source location';
194
195 String helpLong =
196 'Continue running the isolate until it reaches the next source '
197 'location.\n'
198 '\n'
199 'Syntax: step\n';
114 } 200 }
115 201
116 class FinishCommand extends DebuggerCommand { 202 class FinishCommand extends DebuggerCommand {
117 FinishCommand(Debugger debugger) : super(debugger, 'finish', []); 203 FinishCommand(Debugger debugger) : super(debugger, 'finish', []);
118 204
119 Future run(List<String> args) { 205 Future run(List<String> args) {
120 if (debugger.isolatePaused()) { 206 if (debugger.isolatePaused()) {
121 return debugger.isolate.stepOut(); 207 return debugger.isolate.stepOut();
122 } else { 208 } else {
123 debugger.console.printLine('The program is already running'); 209 debugger.console.print('The program is already running');
124 return new Future.value(null); 210 return new Future.value(null);
125 } 211 }
126 } 212 }
213
214 String helpShort =
215 'Continue running the isolate until the current function exits';
216
217 String helpLong =
218 'Continue running the isolate until the current function exits.\n'
219 '\n'
220 'Syntax: finish\n';
127 } 221 }
128 222
129 class BreakCommand extends DebuggerCommand { 223 class BreakCommand extends DebuggerCommand {
130 BreakCommand(Debugger debugger) : super(debugger, 'break', []); 224 BreakCommand(Debugger debugger) : super(debugger, 'break', []);
131 225
132 Future run(List<String> args) { 226 Future run(List<String> args) {
133 if (args.length > 1) { 227 if (args.length > 1) {
134 debugger.console.printLine('not implemented'); 228 debugger.console.print('not implemented');
135 return new Future.value(null); 229 return new Future.value(null);
136 } 230 }
137 var arg = (args.length == 0 ? '' : args[0]); 231 var arg = (args.length == 0 ? '' : args[0]);
138 return SourceLocation.parse(debugger, arg).then((loc) { 232 return SourceLocation.parse(debugger, arg).then((loc) {
139 if (loc.valid) { 233 if (loc.valid) {
140 if (loc.function != null) { 234 if (loc.function != null) {
141 debugger.console.printLine( 235 debugger.console.print(
142 'Ignoring breakpoint at $loc: ' 236 'Ignoring breakpoint at $loc: '
143 'Function entry breakpoints not yet implemented'); 237 'Function entry breakpoints not yet implemented');
144 return null; 238 return null;
145 } 239 }
146 if (loc.col != null) { 240 if (loc.col != null) {
147 // TODO(turnidge): Add tokenPos breakpoint support. 241 // TODO(turnidge): Add tokenPos breakpoint support.
148 debugger.console.printLine( 242 debugger.console.print(
149 'Ignoring column: ' 243 'Ignoring column: '
150 'adding breakpoint at a specific column not yet implemented'); 244 'adding breakpoint at a specific column not yet implemented');
151 } 245 }
152 return debugger.isolate.addBreakpoint(loc.script, loc.line).then((result ) { 246 return debugger.isolate.addBreakpoint(loc.script, loc.line).then((result ) {
153 if (result is DartError) { 247 if (result is DartError) {
154 debugger.console.printLine('Unable to set breakpoint at ${loc}'); 248 debugger.console.print('Unable to set breakpoint at ${loc}');
155 } else { 249 } else {
156 // TODO(turnidge): Adding a duplicate breakpoint is 250 // TODO(turnidge): Adding a duplicate breakpoint is
157 // currently ignored. May want to change the protocol to 251 // currently ignored. May want to change the protocol to
158 // inform us when this happens. 252 // inform us when this happens.
159 253
160 // The BreakpointResolved event prints resolved 254 // The BreakpointResolved event prints resolved
161 // breakpoints already. Just print the unresolved ones here. 255 // breakpoints already. Just print the unresolved ones here.
162 ServiceMap bpt = result; 256 ServiceMap bpt = result;
163 if (!bpt['resolved']) { 257 if (!bpt['resolved']) {
164 var script = bpt['location']['script']; 258 var script = bpt['location']['script'];
165 var bpId = bpt['breakpointNumber']; 259 var bpId = bpt['breakpointNumber'];
166 var tokenPos = bpt['location']['tokenPos']; 260 var tokenPos = bpt['location']['tokenPos'];
167 return script.load().then((_) { 261 return script.load().then((_) {
168 var line = script.tokenToLine(tokenPos); 262 var line = script.tokenToLine(tokenPos);
169 var col = script.tokenToCol(tokenPos); 263 var col = script.tokenToCol(tokenPos);
170 debugger.console.printLine( 264 debugger.console.print(
171 'Future breakpoint ${bpId} added at ' 265 'Future breakpoint ${bpId} added at '
172 '${script.name}:${line}:${col}'); 266 '${script.name}:${line}:${col}');
173 }); 267 });
174 } 268 }
175 } 269 }
176 }); 270 });
177 } else { 271 } else {
178 debugger.console.printLine(loc.errorMessage); 272 debugger.console.print(loc.errorMessage);
179 } 273 }
180 }); 274 });
181 } 275 }
182 276
183 Future<List<String>> complete(List<String> args) { 277 Future<List<String>> complete(List<String> args) {
184 if (args.length != 1) { 278 if (args.length != 1) {
185 return new Future.value([]); 279 return new Future.value([]);
186 } 280 }
187 // TODO - fix SourceLocation complete 281 // TODO - fix SourceLocation complete
188 return new Future.value(SourceLocation.complete(debugger, args[0])); 282 return new Future.value(SourceLocation.complete(debugger, args[0]));
189 } 283 }
284
285 String helpShort = 'Add a breakpoint by source location or function name';
286
287 String helpLong =
288 'Add a breakpoint by source location or function name.\n'
289 '\n'
290 'Syntax: break '
291 '- Break at the current position\n'
292 ' break <line> '
293 '- Break at a line in the current script\n'
294 ' '
295 ' (e.g \'break 11\')\n'
296 ' break <line>:<col> '
297 '- Break at a line:col in the current script\n'
298 ' '
299 ' (e.g \'break 11:8\')\n'
300 ' break <script>:<line> '
301 '- Break at a line:col in a specific script\n'
302 ' '
303 ' (e.g \'break test.dart:11\')\n'
304 ' break <script>:<line>:<col> '
305 '- Break at a line:col in a specific script\n'
306 ' '
307 ' (e.g \'break test.dart:11:8\')\n'
308 ' break <function> '
309 '- Break at the named function\n'
310 ' '
311 ' (e.g \'break main\' or \'break Class.someFunction\')\n';
190 } 312 }
191 313
192 class ClearCommand extends DebuggerCommand { 314 class ClearCommand extends DebuggerCommand {
193 ClearCommand(Debugger debugger) : super(debugger, 'clear', []); 315 ClearCommand(Debugger debugger) : super(debugger, 'clear', []);
194 316
195 Future run(List<String> args) { 317 Future run(List<String> args) {
196 if (args.length > 1) { 318 if (args.length > 1) {
197 debugger.console.printLine('not implemented'); 319 debugger.console.print('not implemented');
198 return new Future.value(null); 320 return new Future.value(null);
199 } 321 }
200 var arg = (args.length == 0 ? '' : args[0]); 322 var arg = (args.length == 0 ? '' : args[0]);
201 return SourceLocation.parse(debugger, arg).then((loc) { 323 return SourceLocation.parse(debugger, arg).then((loc) {
202 if (loc.valid) { 324 if (loc.valid) {
203 if (loc.function != null) { 325 if (loc.function != null) {
204 debugger.console.printLine( 326 debugger.console.print(
205 'Ignoring breakpoint at $loc: ' 327 'Ignoring breakpoint at $loc: '
206 'Function entry breakpoints not yet implemented'); 328 'Function entry breakpoints not yet implemented');
207 return null; 329 return null;
208 } 330 }
209 if (loc.col != null) { 331 if (loc.col != null) {
210 // TODO(turnidge): Add tokenPos clear support. 332 // TODO(turnidge): Add tokenPos clear support.
211 debugger.console.printLine( 333 debugger.console.print(
212 'Ignoring column: ' 334 'Ignoring column: '
213 'clearing breakpoint at a specific column not yet implemented'); 335 'clearing breakpoint at a specific column not yet implemented');
214 } 336 }
215 337
216 for (var bpt in debugger.isolate.breakpoints) { 338 for (var bpt in debugger.isolate.breakpoints) {
217 var script = bpt['location']['script']; 339 var script = bpt['location']['script'];
218 if (script.id == loc.script.id) { 340 if (script.id == loc.script.id) {
219 assert(script.loaded); 341 assert(script.loaded);
220 var line = script.tokenToLine(bpt['location']['tokenPos']); 342 var line = script.tokenToLine(bpt['location']['tokenPos']);
221 if (line == loc.line) { 343 if (line == loc.line) {
222 return debugger.isolate.removeBreakpoint(bpt).then((result) { 344 return debugger.isolate.removeBreakpoint(bpt).then((result) {
223 if (result is DartError) { 345 if (result is DartError) {
224 debugger.console.printLine( 346 debugger.console.print(
225 'Unable to clear breakpoint at ${loc}: ${result.message}') ; 347 'Unable to clear breakpoint at ${loc}: ${result.message}') ;
226 return; 348 return;
227 } else { 349 } else {
228 // TODO(turnidge): Add a BreakpointRemoved event to 350 // TODO(turnidge): Add a BreakpointRemoved event to
229 // the service instead of printing here. 351 // the service instead of printing here.
230 var bpId = bpt['breakpointNumber']; 352 var bpId = bpt['breakpointNumber'];
231 debugger.console.printLine( 353 debugger.console.print(
232 'Breakpoint ${bpId} removed at ${loc}'); 354 'Breakpoint ${bpId} removed at ${loc}');
233 return; 355 return;
234 } 356 }
235 }); 357 });
236 } 358 }
237 } 359 }
238 } 360 }
239 debugger.console.printLine('No breakpoint found at ${loc}'); 361 debugger.console.print('No breakpoint found at ${loc}');
240 } else { 362 } else {
241 debugger.console.printLine(loc.errorMessage); 363 debugger.console.print(loc.errorMessage);
242 } 364 }
243 }); 365 });
244 } 366 }
245 367
246 Future<List<String>> complete(List<String> args) { 368 Future<List<String>> complete(List<String> args) {
247 if (args.length != 1) { 369 if (args.length != 1) {
248 return new Future.value([]); 370 return new Future.value([]);
249 } 371 }
250 return new Future.value(SourceLocation.complete(debugger, args[0])); 372 return new Future.value(SourceLocation.complete(debugger, args[0]));
251 } 373 }
374
375 String helpShort = 'Remove a breakpoint by source location or function name';
376
377 String helpLong =
378 'Remove a breakpoint by source location or function name.\n'
379 '\n'
380 'Syntax: clear '
381 '- Clear at the current position\n'
382 ' clear <line> '
383 '- Clear at a line in the current script\n'
384 ' '
385 ' (e.g \'clear 11\')\n'
386 ' clear <line>:<col> '
387 '- Clear at a line:col in the current script\n'
388 ' '
389 ' (e.g \'clear 11:8\')\n'
390 ' clear <script>:<line> '
391 '- Clear at a line:col in a specific script\n'
392 ' '
393 ' (e.g \'clear test.dart:11\')\n'
394 ' clear <script>:<line>:<col> '
395 '- Clear at a line:col in a specific script\n'
396 ' '
397 ' (e.g \'clear test.dart:11:8\')\n'
398 ' clear <function> '
399 '- Clear at the named function\n'
400 ' '
401 ' (e.g \'clear main\' or \'clear Class.someFunction\')\n';
252 } 402 }
253 403
254 // TODO(turnidge): Add argument completion. 404 // TODO(turnidge): Add argument completion.
255 class DeleteCommand extends DebuggerCommand { 405 class DeleteCommand extends DebuggerCommand {
256 DeleteCommand(Debugger debugger) : super(debugger, 'delete', []); 406 DeleteCommand(Debugger debugger) : super(debugger, 'delete', []);
257 407
258 Future run(List<String> args) { 408 Future run(List<String> args) {
259 if (args.length < 1) { 409 if (args.length < 1) {
260 debugger.console.printLine('delete expects one or more arguments'); 410 debugger.console.print('delete expects one or more arguments');
261 return new Future.value(null); 411 return new Future.value(null);
262 } 412 }
263 List toDelete = []; 413 List toDelete = [];
264 for (var arg in args) { 414 for (var arg in args) {
265 int id = int.parse(arg); 415 int id = int.parse(arg);
266 var bpt = null; 416 var bpt = null;
267 for (var candidate in debugger.isolate.breakpoints) { 417 for (var candidate in debugger.isolate.breakpoints) {
268 if (candidate['breakpointNumber'] == id) { 418 if (candidate['breakpointNumber'] == id) {
269 bpt = candidate; 419 bpt = candidate;
270 break; 420 break;
271 } 421 }
272 } 422 }
273 if (bpt == null) { 423 if (bpt == null) {
274 debugger.console.printLine("Invalid breakpoint id '${id}'"); 424 debugger.console.print("Invalid breakpoint id '${id}'");
275 return new Future.value(null); 425 return new Future.value(null);
276 } 426 }
277 toDelete.add(bpt); 427 toDelete.add(bpt);
278 } 428 }
279 List pending = []; 429 List pending = [];
280 for (var bpt in toDelete) { 430 for (var bpt in toDelete) {
281 pending.add(debugger.isolate.removeBreakpoint(bpt).then((_) { 431 pending.add(debugger.isolate.removeBreakpoint(bpt).then((_) {
282 var id = bpt['breakpointNumber']; 432 var id = bpt['breakpointNumber'];
283 debugger.console.printLine("Removed breakpoint $id"); 433 debugger.console.print("Removed breakpoint $id");
284 })); 434 }));
285 } 435 }
286 return Future.wait(pending); 436 return Future.wait(pending);
287 } 437 }
438
439 String helpShort = 'Remove a breakpoint by breakpoint id';
440
441 String helpLong =
442 'Remove a breakpoint by breakpoint id.\n'
443 '\n'
444 'Syntax: delete <bp-id>\n'
445 ' delete <bp-id> <bp-id> ...\n';
288 } 446 }
289 447
290 class InfoBreakpointsCommand extends DebuggerCommand { 448 class InfoBreakpointsCommand extends DebuggerCommand {
291 InfoBreakpointsCommand(Debugger debugger) 449 InfoBreakpointsCommand(Debugger debugger)
292 : super(debugger, 'breakpoints', []); 450 : super(debugger, 'breakpoints', []);
293 451
294 Future run(List<String> args) { 452 Future run(List<String> args) {
295 return debugger.isolate.reloadBreakpoints().then((_) { 453 return debugger.isolate.reloadBreakpoints().then((_) {
296 if (debugger.isolate.breakpoints.isEmpty) { 454 if (debugger.isolate.breakpoints.isEmpty) {
297 debugger.console.printLine('No breakpoints'); 455 debugger.console.print('No breakpoints');
298 } 456 }
299 for (var bpt in debugger.isolate.breakpoints) { 457 for (var bpt in debugger.isolate.breakpoints) {
300 var bpId = bpt['breakpointNumber']; 458 var bpId = bpt['breakpointNumber'];
301 var script = bpt['location']['script']; 459 var script = bpt['location']['script'];
302 var tokenPos = bpt['location']['tokenPos']; 460 var tokenPos = bpt['location']['tokenPos'];
303 var line = script.tokenToLine(tokenPos); 461 var line = script.tokenToLine(tokenPos);
304 var col = script.tokenToCol(tokenPos); 462 var col = script.tokenToCol(tokenPos);
305 var extras = new StringBuffer(); 463 var extras = new StringBuffer();
306 if (!bpt['resolved']) { 464 if (!bpt['resolved']) {
307 extras.write(' unresolved'); 465 extras.write(' unresolved');
308 } 466 }
309 if (!bpt['enabled']) { 467 if (!bpt['enabled']) {
310 extras.write(' disabled'); 468 extras.write(' disabled');
311 } 469 }
312 debugger.console.printLine( 470 debugger.console.print(
313 'Breakpoint ${bpId} at ${script.name}:${line}:${col}${extras}'); 471 'Breakpoint ${bpId} at ${script.name}:${line}:${col}${extras}');
314 } 472 }
315 }); 473 });
316 } 474 }
475
476 String helpShort = 'List all breakpoints';
477
478 String helpLong =
479 'List all breakpoints.\n'
480 '\n'
481 'Syntax: info breakpoints\n';
317 } 482 }
318 483
319 class InfoIsolatesCommand extends DebuggerCommand { 484 class InfoIsolatesCommand extends DebuggerCommand {
320 InfoIsolatesCommand(Debugger debugger) : super(debugger, 'isolates', []); 485 InfoIsolatesCommand(Debugger debugger) : super(debugger, 'isolates', []);
321 486
322 Future run(List<String> args) { 487 Future run(List<String> args) {
323 for (var isolate in debugger.isolate.vm.isolates) { 488 for (var isolate in debugger.isolate.vm.isolates) {
324 debugger.console.printLine( 489 String current = (isolate == debugger.isolate ? ' *' : '');
325 "Isolate ${isolate.id} '${isolate.name}'"); 490 debugger.console.print(
491 "Isolate ${isolate.id} '${isolate.name}'${current}");
326 } 492 }
327 return new Future.value(null); 493 return new Future.value(null);
328 } 494 }
495
496 String helpShort = 'List all isolates';
497
498 String helpLong =
499 'List all isolates.\n'
500 '\n'
501 'Syntax: info isolates\n';
329 } 502 }
330 503
331 class InfoCommand extends DebuggerCommand { 504 class InfoCommand extends DebuggerCommand {
332 InfoCommand(Debugger debugger) : super(debugger, 'info', [ 505 InfoCommand(Debugger debugger) : super(debugger, 'info', [
333 new InfoBreakpointsCommand(debugger), 506 new InfoBreakpointsCommand(debugger),
334 new InfoIsolatesCommand(debugger), 507 new InfoIsolatesCommand(debugger),
335 ]); 508 ]);
336 509
337 Future run(List<String> args) { 510 Future run(List<String> args) {
338 debugger.console.printLine("Invalid info command"); 511 debugger.console.print("'info' expects a subcommand (see 'help info')");
339 return new Future.value(null); 512 return new Future.value(null);
340 } 513 }
514
515 String helpShort = 'Show information on a variety of topics';
516
517 String helpLong =
518 'Show information on a variety of topics.\n'
519 '\n'
520 'Syntax: info <subcommand>\n';
341 } 521 }
342 522
343 class RefreshCoverageCommand extends DebuggerCommand { 523 class RefreshCoverageCommand extends DebuggerCommand {
344 RefreshCoverageCommand(Debugger debugger) : super(debugger, 'coverage', []); 524 RefreshCoverageCommand(Debugger debugger) : super(debugger, 'coverage', []);
345 525
346 Future run(List<String> args) { 526 Future run(List<String> args) {
347 Set<Script> scripts = debugger.stackElement.activeScripts(); 527 Set<Script> scripts = debugger.stackElement.activeScripts();
348 List pending = []; 528 List pending = [];
349 for (var script in scripts) { 529 for (var script in scripts) {
350 pending.add(script.refreshCoverage().then((_) { 530 pending.add(script.refreshCoverage().then((_) {
351 debugger.console.printLine('Refreshed coverage for ${script.name}'); 531 debugger.console.print('Refreshed coverage for ${script.name}');
352 })); 532 }));
353 } 533 }
354 return Future.wait(pending); 534 return Future.wait(pending);
355 } 535 }
536
537 String helpShort = 'Refresh code coverage information for current frames';
538
539 String helpLong =
540 'Refresh code coverage information for current frames.\n'
541 '\n'
542 'Syntax: refresh coverage\n\n';
543 }
544
545 class RefreshStackCommand extends DebuggerCommand {
546 RefreshStackCommand(Debugger debugger) : super(debugger, 'stack', []);
547
548 Future run(List<String> args) {
549 Set<Script> scripts = debugger.stackElement.activeScripts();
550 List pending = [];
551 return debugger.refreshStack();
552 }
553
554 String helpShort = 'Refresh isolate stack';
555
556 String helpLong =
557 'Refresh isolate stack.\n'
558 '\n'
559 'Syntax: refresh stack\n';
356 } 560 }
357 561
358 class RefreshCommand extends DebuggerCommand { 562 class RefreshCommand extends DebuggerCommand {
359 RefreshCommand(Debugger debugger) : super(debugger, 'refresh', [ 563 RefreshCommand(Debugger debugger) : super(debugger, 'refresh', [
360 new RefreshCoverageCommand(debugger), 564 new RefreshCoverageCommand(debugger),
565 new RefreshStackCommand(debugger),
361 ]); 566 ]);
362 567
363 Future run(List<String> args) { 568 Future run(List<String> args) {
364 return debugger.refreshStack(); 569 debugger.console.print("'refresh' expects a subcommand (see 'help refresh')" );
570 return new Future.value(null);
365 } 571 }
572
573 String helpShort = 'Refresh debugging information of various sorts';
574
575 String helpLong =
576 'Refresh debugging information of various sorts.\n'
577 '\n'
578 'Syntax: refresh <subcommand>\n';
366 } 579 }
367 580
368 // Tracks the state for an isolate debugging session. 581 // Tracks the state for an isolate debugging session.
369 class ObservatoryDebugger extends Debugger { 582 class ObservatoryDebugger extends Debugger {
370 RootCommand cmd; 583 RootCommand cmd;
371 DebuggerConsoleElement console; 584 DebuggerConsoleElement console;
372 DebuggerStackElement stackElement; 585 DebuggerStackElement stackElement;
373 ServiceMap stack; 586 ServiceMap stack;
374 int currentFrame = 0; 587 int currentFrame = 0;
375 588
(...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after
444 return isolate.getStack().then((result) { 657 return isolate.getStack().then((result) {
445 stack = result; 658 stack = result;
446 // TODO(turnidge): Replace only the changed part of the stack to 659 // TODO(turnidge): Replace only the changed part of the stack to
447 // reduce flicker. 660 // reduce flicker.
448 stackElement.updateStack(stack, pauseEvent); 661 stackElement.updateStack(stack, pauseEvent);
449 }); 662 });
450 } 663 }
451 664
452 void reportStatus() { 665 void reportStatus() {
453 if (_isolate.idle) { 666 if (_isolate.idle) {
454 console.printLine('Isolate is idle'); 667 console.print('Isolate is idle');
455 } else if (_isolate.running) { 668 } else if (_isolate.running) {
456 console.printLine("Isolate is running (type 'pause' to interrupt)"); 669 console.print("Isolate is running (type 'pause' to interrupt)");
457 } else if (_isolate.pauseEvent != null) { 670 } else if (_isolate.pauseEvent != null) {
458 _reportPause(_isolate.pauseEvent); 671 _reportPause(_isolate.pauseEvent);
459 } else { 672 } else {
460 console.printLine('Isolate is in unknown state'); 673 console.print('Isolate is in unknown state');
461 } 674 }
462 } 675 }
463 676
464 void _reportPause(ServiceEvent event) { 677 void _reportPause(ServiceEvent event) {
465 if (event.eventType == 'IsolateCreated') { 678 if (event.eventType == 'IsolateCreated') {
466 console.printLine( 679 console.print(
467 "Paused at isolate start (type 'continue' to start the isolate')"); 680 "Paused at isolate start (type 'continue' to start the isolate')");
468 } else if (event.eventType == 'IsolateShutdown') { 681 } else if (event.eventType == 'IsolateShutdown') {
469 console.printLine( 682 console.print(
470 "Paused at isolate exit (type 'continue' to exit the isolate')"); 683 "Paused at isolate exit (type 'continue' to exit the isolate')");
471 } 684 }
472 if (stack['frames'].length > 0) { 685 if (stack['frames'].length > 0) {
473 var frame = stack['frames'][0]; 686 var frame = stack['frames'][0];
474 var script = frame['script']; 687 var script = frame['script'];
475 script.load().then((_) { 688 script.load().then((_) {
476 var line = script.tokenToLine(frame['tokenPos']); 689 var line = script.tokenToLine(frame['tokenPos']);
477 var col = script.tokenToCol(frame['tokenPos']); 690 var col = script.tokenToCol(frame['tokenPos']);
478 if (event.breakpoint != null) { 691 if (event.breakpoint != null) {
479 var bpId = event.breakpoint['breakpointNumber']; 692 var bpId = event.breakpoint['breakpointNumber'];
480 console.printLine('Breakpoint ${bpId} at ${script.name}:${line}:${col} '); 693 console.print('Breakpoint ${bpId} at ${script.name}:${line}:${col}');
481 } else if (event.exception != null) { 694 } else if (event.exception != null) {
482 // TODO(turnidge): Test this. 695 // TODO(turnidge): Test this.
483 console.printLine( 696 console.print(
484 'Exception ${event.exception} at ${script.name}:${line}:${col}'); 697 'Exception ${event.exception} at ${script.name}:${line}:${col}');
485 } else { 698 } else {
486 console.printLine('Paused at ${script.name}:${line}:${col}'); 699 console.print('Paused at ${script.name}:${line}:${col}');
487 } 700 }
488 }); 701 });
489 } 702 }
490 } 703 }
491 704
492 void _onEvent(ServiceEvent event) { 705 void _onEvent(ServiceEvent event) {
493 if (event.owner != isolate) { 706 if (event.owner != isolate) {
494 return; 707 return;
495 } 708 }
496 switch(event.eventType) { 709 switch(event.eventType) {
497 case 'IsolateShutdown': 710 case 'IsolateShutdown':
498 console.printLine('Isolate shutdown'); 711 console.print('Isolate shutdown');
499 isolate = null; 712 isolate = null;
500 break; 713 break;
501 714
502 case 'BreakpointReached': 715 case 'BreakpointReached':
503 case 'IsolateInterrupted': 716 case 'IsolateInterrupted':
504 case 'ExceptionThrown': 717 case 'ExceptionThrown':
505 _refreshStack(event).then((_) { 718 _refreshStack(event).then((_) {
506 _reportPause(event); 719 _reportPause(event);
507 }); 720 });
508 break; 721 break;
509 722
510 case 'IsolateResumed': 723 case 'IsolateResumed':
511 console.printLine('Continuing...'); 724 console.print('Continuing...');
512 break; 725 break;
513 726
514 case 'BreakpointResolved': 727 case 'BreakpointResolved':
515 var bpId = event.breakpoint['breakpointNumber']; 728 var bpId = event.breakpoint['breakpointNumber'];
516 var script = event.breakpoint['location']['script']; 729 var script = event.breakpoint['location']['script'];
517 var tokenPos = event.breakpoint['location']['tokenPos']; 730 var tokenPos = event.breakpoint['location']['tokenPos'];
518 var line = script.tokenToLine(tokenPos); 731 var line = script.tokenToLine(tokenPos);
519 var col = script.tokenToCol(tokenPos); 732 var col = script.tokenToCol(tokenPos);
520 console.printLine( 733 console.print(
521 'Breakpoint ${bpId} added at ${script.name}:${line}:${col}'); 734 'Breakpoint ${bpId} added at ${script.name}:${line}:${col}');
522 break; 735 break;
523 736
524 case '_Graph': 737 case '_Graph':
525 case 'IsolateCreated': 738 case 'IsolateCreated':
526 case 'GC': 739 case 'GC':
527 // Ignore these events for now. 740 // Ignore these events for now.
528 break; 741 break;
529 742
530 default: 743 default:
531 console.printLine('Unrecognized event: $event'); 744 console.print('Unrecognized event: $event');
532 break; 745 break;
533 } 746 }
534 } 747 }
535 748
536 static String _commonPrefix(String a, String b) { 749 static String _commonPrefix(String a, String b) {
537 int pos = 0; 750 int pos = 0;
538 while (pos < a.length && pos < b.length) { 751 while (pos < a.length && pos < b.length) {
539 if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) { 752 if (a.codeUnitAt(pos) != b.codeUnitAt(pos)) {
540 break; 753 break;
541 } 754 }
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after
576 String lastCommand; 789 String lastCommand;
577 790
578 Future run(String command) { 791 Future run(String command) {
579 if (command == '' && lastCommand != null) { 792 if (command == '' && lastCommand != null) {
580 command = lastCommand; 793 command = lastCommand;
581 } 794 }
582 console.printBold('\$ $command'); 795 console.printBold('\$ $command');
583 return cmd.runCommand(command).then((_) { 796 return cmd.runCommand(command).then((_) {
584 lastCommand = command; 797 lastCommand = command;
585 }).catchError((e) { 798 }).catchError((e) {
586 console.printLine('ERROR $e'); 799 console.print('ERROR $e');
587 }); 800 });
588 } 801 }
589 } 802 }
590 803
591 @CustomTag('debugger-page') 804 @CustomTag('debugger-page')
592 class DebuggerPageElement extends ObservatoryElement { 805 class DebuggerPageElement extends ObservatoryElement {
593 @published Isolate isolate; 806 @published Isolate isolate;
594 807
595 isolateChanged(oldValue) { 808 isolateChanged(oldValue) {
596 if (isolate != null) { 809 if (isolate != null) {
(...skipping 190 matching lines...) Expand 10 before | Expand all | Expand 10 after
787 }); 1000 });
788 } 1001 }
789 } 1002 }
790 1003
791 @CustomTag('debugger-console') 1004 @CustomTag('debugger-console')
792 class DebuggerConsoleElement extends ObservatoryElement { 1005 class DebuggerConsoleElement extends ObservatoryElement {
793 @published Isolate isolate; 1006 @published Isolate isolate;
794 1007
795 DebuggerConsoleElement.created() : super.created(); 1008 DebuggerConsoleElement.created() : super.created();
796 1009
797 void printLine(String line) { 1010 void print(String line, { bool newline:true }) {
798 var div = new DivElement(); 1011 var span = new SpanElement();
799 div.classes.add('normal'); 1012 span.classes.add('normal');
800 div.appendText(line); 1013 span.appendText(line);
801 $['consoleText'].children.add(div); 1014 if (newline) {
802 div.scrollIntoView(); 1015 span.appendText('\n');
1016 }
1017 $['consoleText'].children.add(span);
1018 span.scrollIntoView();
803 } 1019 }
804 1020
805 void printBold(String line) { 1021 void printBold(String line, { bool newline:true }) {
806 var div = new DivElement(); 1022 var span = new SpanElement();
807 div.classes.add('bold'); 1023 span.classes.add('bold');
808 div.appendText(line); 1024 span.appendText(line);
809 $['consoleText'].children.add(div); 1025 span.appendText('\n');
810 div.scrollIntoView(); 1026 $['consoleText'].children.add(span);
1027 span.scrollIntoView();
811 } 1028 }
812 1029
813 void newline() { 1030 void newline() {
814 var br = new BRElement(); 1031 var br = new BRElement();
815 $['consoleText'].children.add(br); 1032 $['consoleText'].children.add(br);
816 br.scrollIntoView(); 1033 br.scrollIntoView();
817 } 1034 }
818 } 1035 }
819 1036
820 @CustomTag('debugger-input') 1037 @CustomTag('debugger-input')
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
856 debugger.run(command).whenComplete(_notBusy); 1073 debugger.run(command).whenComplete(_notBusy);
857 } 1074 }
858 break; 1075 break;
859 } 1076 }
860 }); 1077 });
861 } 1078 }
862 1079
863 DebuggerInputElement.created() : super.created(); 1080 DebuggerInputElement.created() : super.created();
864 } 1081 }
865 1082
OLDNEW
« no previous file with comments | « runtime/observatory/lib/src/cli/command.dart ('k') | runtime/observatory/lib/src/elements/debugger.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698