mirror of
https://github.com/dart-lang/sdk
synced 2024-11-05 18:22:09 +00:00
Add line table command to debugger
New command returns token information of a script. This will enable the editor/debugger to translate token offsets to line numbers. Review URL: https://codereview.chromium.org//13533016 git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@21009 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
parent
cbe8bd9a3a
commit
ee69789e07
5 changed files with 138 additions and 1 deletions
|
@ -479,6 +479,7 @@ static JSONDebuggerCommand debugger_commands[] = {
|
|||
{ "getGlobalVariables", DbgMessage::HandleGetGlobalsCmd },
|
||||
{ "getScriptURLs", DbgMessage::HandleGetScriptURLsCmd },
|
||||
{ "getScriptSource", DbgMessage::HandleGetSourceCmd },
|
||||
{ "getLineNumberTable", DbgMessage::HandleGetLineNumbersCmd },
|
||||
{ "getStackTrace", DbgMessage::HandleGetStackTraceCmd },
|
||||
{ "setBreakpoint", DbgMessage::HandleSetBpCmd },
|
||||
{ "setPauseOnException", DbgMessage::HandlePauseOnExcCmd },
|
||||
|
@ -788,6 +789,53 @@ bool DbgMessage::HandleGetSourceCmd(DbgMessage* in_msg) {
|
|||
}
|
||||
|
||||
|
||||
bool DbgMessage::HandleGetLineNumbersCmd(DbgMessage* in_msg) {
|
||||
ASSERT(in_msg != NULL);
|
||||
MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
|
||||
int msg_id = msg_parser.MessageId();
|
||||
dart::TextBuffer msg(64);
|
||||
intptr_t lib_id = msg_parser.GetIntParam("libraryId");
|
||||
char* url_chars = msg_parser.GetStringParam("url");
|
||||
ASSERT(url_chars != NULL);
|
||||
Dart_Handle url = DartUtils::NewString(url_chars);
|
||||
ASSERT_NOT_ERROR(url);
|
||||
free(url_chars);
|
||||
url_chars = NULL;
|
||||
Dart_Handle info = Dart_ScriptGetTokenInfo(lib_id, url);
|
||||
if (Dart_IsError(info)) {
|
||||
in_msg->SendErrorReply(msg_id, Dart_GetError(info));
|
||||
return false;
|
||||
}
|
||||
ASSERT(Dart_IsList(info));
|
||||
intptr_t info_len = 0;
|
||||
Dart_Handle res = Dart_ListLength(info, &info_len);
|
||||
ASSERT_NOT_ERROR(res);
|
||||
msg.Printf("{ \"id\": %d, ", msg_id);
|
||||
msg.Printf("\"result\": { \"lines\": [");
|
||||
Dart_Handle elem;
|
||||
bool num_elems = 0;
|
||||
for (intptr_t i = 0; i < info_len; i++) {
|
||||
elem = Dart_ListGetAt(info, i);
|
||||
if (Dart_IsNull(elem)) {
|
||||
msg.Printf((i == 0) ? "[" : "], [");
|
||||
num_elems = 0;
|
||||
} else {
|
||||
ASSERT(Dart_IsInteger(elem));
|
||||
int value = GetIntValue(elem);
|
||||
if (num_elems == 0) {
|
||||
msg.Printf("%d", value);
|
||||
} else {
|
||||
msg.Printf(",%d", value);
|
||||
}
|
||||
num_elems++;
|
||||
}
|
||||
}
|
||||
msg.Printf("]]}}");
|
||||
in_msg->SendReply(&msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
bool DbgMessage::HandleGetStackTraceCmd(DbgMessage* in_msg) {
|
||||
ASSERT(in_msg != NULL);
|
||||
MessageParser msg_parser(in_msg->buffer(), in_msg->buffer_len());
|
||||
|
|
|
@ -104,6 +104,7 @@ class DbgMessage {
|
|||
static bool HandleGetListCmd(DbgMessage* msg);
|
||||
static bool HandleGetScriptURLsCmd(DbgMessage* msg);
|
||||
static bool HandleGetSourceCmd(DbgMessage* msg);
|
||||
static bool HandleGetLineNumbersCmd(DbgMessage* msg);
|
||||
static bool HandleGetStackTraceCmd(DbgMessage* msg);
|
||||
static bool HandlePauseOnExcCmd(DbgMessage* msg);
|
||||
static bool HandleSetBpCmd(DbgMessage* msg);
|
||||
|
|
|
@ -141,6 +141,28 @@ DART_EXPORT Dart_Handle Dart_ScriptGetSource(
|
|||
Dart_Handle script_url_in);
|
||||
|
||||
|
||||
/**
|
||||
* Returns an array containing line number and token offset info
|
||||
* for the given script.
|
||||
*
|
||||
* Returns an array of numbers. Null values indicate the beginning of
|
||||
* a new line. The first number after null is the line number.
|
||||
* The line number is followed by pairs of numbers, with the first value
|
||||
* being the "token offset" and the second value being the character offset
|
||||
* of the token relative to the beginning of the script.
|
||||
* The "token offset" is a value that is used to indicate a location
|
||||
* in code, similarly to a "PC" address.
|
||||
* Source lines with no tokens are omitted.
|
||||
*
|
||||
* Requires there to be a current isolate.
|
||||
*
|
||||
* \return A handle to an array or an error object.
|
||||
*/
|
||||
DART_EXPORT Dart_Handle Dart_ScriptGetTokenInfo(
|
||||
intptr_t library_id,
|
||||
Dart_Handle script_url_in);
|
||||
|
||||
|
||||
/**
|
||||
* Returns a string containing a generated source code of the given script
|
||||
* in the given library. This is essentially used to pretty print dart code
|
||||
|
|
|
@ -587,6 +587,57 @@ DART_EXPORT Dart_Handle Dart_ScriptGetSource(
|
|||
}
|
||||
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_ScriptGetTokenInfo(
|
||||
intptr_t library_id,
|
||||
Dart_Handle script_url_in) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
DARTSCOPE(isolate);
|
||||
const Library& lib = Library::Handle(Library::GetLibrary(library_id));
|
||||
if (lib.IsNull()) {
|
||||
return Api::NewError("%s: %"Pd" is not a valid library id",
|
||||
CURRENT_FUNC, library_id);
|
||||
}
|
||||
UNWRAP_AND_CHECK_PARAM(String, script_url, script_url_in);
|
||||
const Script& script = Script::Handle(lib.LookupScript(script_url));
|
||||
if (script.IsNull()) {
|
||||
return Api::NewError("%s: script '%s' not found in library '%s'",
|
||||
CURRENT_FUNC, script_url.ToCString(),
|
||||
String::Handle(lib.url()).ToCString());
|
||||
}
|
||||
|
||||
const GrowableObjectArray& info =
|
||||
GrowableObjectArray::Handle(GrowableObjectArray::New());
|
||||
const String& source = String::Handle(script.Source());
|
||||
const String& key = Symbols::Empty();
|
||||
const Object& line_separator = Object::Handle();
|
||||
const TokenStream& tkns = TokenStream::Handle(script.tokens());
|
||||
ASSERT(!tkns.IsNull());
|
||||
TokenStream::Iterator tkit(tkns, 0);
|
||||
int current_line = -1;
|
||||
Scanner s(source, key);
|
||||
s.Scan();
|
||||
while (s.current_token().kind != Token::kEOS) {
|
||||
ASSERT(tkit.IsValid());
|
||||
ASSERT(s.current_token().kind == tkit.CurrentTokenKind());
|
||||
int token_line = s.current_token().position.line;
|
||||
if (token_line != current_line) {
|
||||
// emit line
|
||||
info.Add(line_separator);
|
||||
info.Add(Smi::Handle(Smi::New(token_line)));
|
||||
current_line = token_line;
|
||||
}
|
||||
// TODO(hausner): Could optimize here by not reporting tokens
|
||||
// that will never be a location used by the debugger, e.g.
|
||||
// braces, semicolons, most keywords etc.
|
||||
info.Add(Smi::Handle(Smi::New(tkit.CurrentPosition())));
|
||||
info.Add(Smi::Handle(Smi::New(s.current_token().offset)));
|
||||
s.Scan();
|
||||
tkit.Advance();
|
||||
}
|
||||
return Api::NewHandle(isolate, Array::MakeArray(info));
|
||||
}
|
||||
|
||||
|
||||
DART_EXPORT Dart_Handle Dart_GenerateScriptSource(Dart_Handle library_url_in,
|
||||
Dart_Handle script_url_in) {
|
||||
Isolate* isolate = Isolate::Current();
|
||||
|
|
|
@ -48,6 +48,7 @@ void printHelp() {
|
|||
pg <id> Print all global variables visible within given library id
|
||||
ls <lib_id> List loaded scripts in library
|
||||
gs <lib_id> <script_url> Get source text of script in library
|
||||
tok <lib_id> <script_url> Get line and token table of script in library
|
||||
epi <none|all|unhandled> Set exception pause info
|
||||
i <id> Interrupt execution of given isolate id
|
||||
h Print help
|
||||
|
@ -181,6 +182,13 @@ void processCommand(String cmdLine) {
|
|||
"libraryId": int.parse(args[1]),
|
||||
"url": args[2] } };
|
||||
sendCmd(cmd).then((result) => handleGetSourceResponse(result));
|
||||
} else if (command == "tok" && args.length == 3) {
|
||||
var cmd = { "id": seqNum,
|
||||
"command": "getLineNumberTable",
|
||||
"params": { "isolateId" : isolate_id,
|
||||
"libraryId": int.parse(args[1]),
|
||||
"url": args[2] } };
|
||||
sendCmd(cmd).then((result) => handleGetLineTableResponse(result));
|
||||
} else if (command == "epi" && args.length == 2) {
|
||||
var cmd = { "id": seqNum,
|
||||
"command": "setPauseOnException",
|
||||
|
@ -324,6 +332,13 @@ handleGetSourceResponse(response) {
|
|||
}
|
||||
|
||||
|
||||
handleGetLineTableResponse(response) {
|
||||
Map result = response["result"];
|
||||
var info = result["lines"];
|
||||
print("Line info table:\n$info");
|
||||
}
|
||||
|
||||
|
||||
void handleGetLibraryResponse(response) {
|
||||
Map result = response["result"];
|
||||
List libs = result["libraries"];
|
||||
|
@ -391,7 +406,7 @@ void printStackTrace(List frames) {
|
|||
void handlePausedEvent(msg) {
|
||||
assert(msg["params"] != null);
|
||||
var reason = msg["params"]["reason"];
|
||||
isolate_id = msg["params"]["id"];
|
||||
isolate_id = msg["params"]["isolateId"];
|
||||
stackTrace = msg["params"]["callFrames"];
|
||||
assert(stackTrace != null);
|
||||
assert(stackTrace.length >= 1);
|
||||
|
|
Loading…
Reference in a new issue