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

Unified Diff: tools/ddbg.dart

Issue 106743008: When we hit a breakpoint in the debugger, show the source of current line. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 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 side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: tools/ddbg.dart
===================================================================
--- tools/ddbg.dart (revision 30871)
+++ tools/ddbg.dart (working copy)
@@ -12,6 +12,18 @@
import "ddbg/lib/commando.dart";
+class TargetScript {
+ // The text of a script.
+ String source = null;
+
+ // A mapping from line number to source text.
+ List<String> lineToSource = null;
+
+ // A mapping from token offset to line number.
+ Map<int,int> tokenToLine = null;
+}
+
+
class TargetIsolate {
int id;
// The location of the last paused event.
@@ -19,6 +31,8 @@
TargetIsolate(this.id);
bool get isPaused => pausedLocation != null;
+
+ Map<String, TargetScript> scripts = {};
}
Map<int, TargetIsolate> targetIsolates= new Map<int, TargetIsolate>();
@@ -33,6 +47,7 @@
int seqNum = 0;
bool isDebugging = false;
+bool stepMode = false;
Process targetProcess = null;
bool suppressNextExitCode = false;
@@ -85,9 +100,13 @@
// The current values for all settings.
var settings = new Map();
-// Generates a string of 'count' spaces.
-String _spaces(int count) {
- return new List.filled(count, ' ').join('');
+String _leftJustify(text, int width) {
+ StringBuffer buffer = new StringBuffer();
+ buffer.write(text);
+ while (buffer.length < width) {
+ buffer.write(' ');
+ }
+ return buffer.toString();
}
// TODO(turnidge): Move all commands here.
@@ -138,9 +157,7 @@
if (args.length == 1) {
print("Debugger commands:\n");
for (var command in commandList) {
- const tabStop = 12;
- var spaces = _spaces(max(1, (tabStop - command.name.length)));
- print(' ${command.name}${spaces}${command.helpShort}');
+ print(' ${_leftJustify(command.name, 11)} ${command.helpShort}');
}
// TODO(turnidge): Convert all commands to use the Command class.
@@ -512,6 +529,8 @@
{ 'r':'resume', 's':'stepOver', 'si':'stepInto', 'so':'stepOut'};
if (resume_commands[command] != null) {
if (!checkPaused()) return;
+ // TODO(turnidge): step mode isn't quite right yet.
+ stepMode = (command != 'r');
var cmd = { "id": seqNum,
"command": resume_commands[command],
"params": { "isolateId" : currentIsolate.id } };
@@ -909,7 +928,7 @@
void printStackFrame(frame_num, Map frame) {
var fname = frame["functionName"];
var loc = formatLocation(frame["location"]);
- print("$frame_num $fname ($loc)");
+ print("#${_leftJustify(frame_num,2)} $fname at $loc");
List locals = frame["locals"];
for (int i = 0; i < locals.length; i++) {
printNamedObject(locals[i]);
@@ -924,7 +943,86 @@
}
-void handlePausedEvent(msg) {
+Map<int, int> parseLineNumberTable(List<List<int>> table) {
+ Map tokenToLine = {};
+ for (var line in table) {
+ // Each entry begins with a line number...
+ var lineNumber = line[0];
+ for (var pos = 1; pos < line.length; pos += 2) {
+ // ...and is followed by (token offset, col number) pairs.
+ // We ignore the column numbers.
+ var tokenOffset = line[pos];
+ tokenToLine[tokenOffset] = lineNumber;
+ }
+ }
+ return tokenToLine;
+}
+
+
+Future<TargetScript> getTargetScript(Map location) {
+ var isolate = targetIsolates[currentIsolate.id];
+ var url = location['url'];
+ var script = isolate.scripts[url];
+ if (script != null) {
+ return new Future.value(script);
+ }
+
+ // Ask the vm for the source and line number table.
+ var sourceCmd = {
+ "id": seqNum++,
+ "command": "getScriptSource",
+ "params": { "isolateId": currentIsolate.id,
+ "libraryId": location['libraryId'],
+ "url": url } };
+
+ var lineNumberCmd = {
+ "id": seqNum++,
+ "command": "getLineNumberTable",
+ "params": { "isolateId": currentIsolate.id,
+ "libraryId": location['libraryId'],
+ "url": url } };
+
+ script = new TargetScript();
+ return Future.wait([
hausner 2013/12/05 23:57:53 Your comments helped a lot to understand the contr
Bob Nystrom 2013/12/06 00:08:09 Drive-by!
turnidge 2013/12/06 17:19:43 Done.
turnidge 2013/12/06 17:19:43 Done.
+ // Send the source command
+ sendCmd(sourceCmd).then(
+ (Map response) {
+ Map result = response["result"];
+ script.source = result['text'];
+ // Line numbers are 1-based so add a dummy for line 0.
+ script.lineToSource = [''];
+ script.lineToSource.addAll(script.source.split('\n'));
+ }),
+ // Send the line numbers command
+ sendCmd(lineNumberCmd).then(
+ (Map response) {
+ Map result = response["result"];
+ script.tokenToLine = parseLineNumberTable(result['lines']);
+ })]).then((_) {
+ // When both commands complete, cache the result.
+ isolate.scripts[url] = script;
+ return script;
+ });
+}
+
+
+Future printLocation(String label, Map location) {
+ // Figure out the line number.
+ return getTargetScript(location).then(
+ (script) {
+ var lineNumber = script.tokenToLine[location['tokenOffset']];
+ var text = script.lineToSource[lineNumber];
+ if (label != null) {
+ var fileName = location['url'].split("/").last;
+ print("$label \n"
+ " at $fileName:$lineNumber");
+ }
+ print("${_leftJustify(lineNumber, 8)}$text");
+ });
+}
+
+
+Future handlePausedEvent(msg) {
assert(msg["params"] != null);
var reason = msg["params"]["reason"];
int isolateId = msg["params"]["isolateId"];
@@ -936,16 +1034,16 @@
assert(location != null);
isolate.pausedLocation = location;
if (reason == "breakpoint") {
- print("Isolate $isolateId paused on breakpoint");
- print("location: ${formatLocation(location)}");
+ return printLocation((stepMode ? null : "Breakpoint"), location);
hausner 2013/12/05 23:57:53 A cleaner way would be to add to the wire protocol
turnidge 2013/12/06 17:19:43 That would be nice. Also, it might be helpful to
} else if (reason == "interrupted") {
- print("Isolate $isolateId paused due to an interrupt");
- print("location: ${formatLocation(location)}");
+ stepMode = false;
+ return printLocation("Interrupted", location);
} else {
assert(reason == "exception");
var excObj = msg["params"]["exception"];
print("Isolate $isolateId paused on exception");
print(remoteObject(excObj));
+ return new Future.value();
}
}
@@ -1001,8 +1099,9 @@
}
if (event == "paused") {
cmdo.hide();
- handlePausedEvent(msg);
- cmdo.show();
+ handlePausedEvent(msg).then((_) {
+ cmdo.show();
+ });
return;
}
if (event == "breakpointResolved") {
@@ -1011,7 +1110,7 @@
var isolateId = params["isolateId"];
var location = formatLocation(params["location"]);
cmdo.hide();
- print("BP ${params["breakpointId"]} resolved in isolate $isolateId"
+ print("Breakpoint ${params["breakpointId"]} resolved in isolate $isolateId"
" at $location.");
cmdo.show();
return;
@@ -1267,6 +1366,12 @@
return Future.wait(cleanupFutures);
}
+void debuggerError(error, StackTrace trace) {
+ print('\n--------\nExiting due to unexpected error:\n'
+ ' $error\n$trace\n');
+ debuggerQuit();
+}
+
Future debuggerQuit() {
// Kill target process, if any.
if (targetProcess != null) {
@@ -1299,10 +1404,21 @@
}
void main(List<String> args) {
- parseArgs(args);
+ // Setup a zone which will exit the debugger cleanly on any uncaught
+ // exception.
+ var zone =
+ Zone.ROOT.fork(
+ specification:new ZoneSpecification(
+ handleUncaughtError:
+ (self, parent, zone, error, trace) {
+ debuggerError(error, trace);
+ }));
- cmdo = new Commando(completer: debuggerCommandCompleter);
- cmdSubscription = cmdo.commands.listen(processCommand,
- onError: processError,
- onDone: processDone);
+ zone.run(() {
+ parseArgs(args);
+ cmdo = new Commando(completer: debuggerCommandCompleter);
+ cmdSubscription = cmdo.commands.listen(processCommand,
+ onError: processError,
+ onDone: processDone);
+ });
}
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698