Debugger: Use DebuggerCommand in QML engine

... instead of manually set up JSON. It's more concise, and paves the
way to use per-command callbacks as in the other engines.

Change-Id: Ib5cf9c9b882ec0ec87acd7c1ceb938d3ee60346b
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
hjk
2015-07-10 11:06:27 +02:00
parent 90985d18c0
commit 92f4ea3f79
3 changed files with 116 additions and 176 deletions

View File

@@ -782,6 +782,16 @@ void DebuggerCommand::arg(const char *name, const char *value)
args.append("\","); args.append("\",");
} }
void DebuggerCommand::arg(const char *name, const QList<int> &list)
{
beginList(name);
foreach (int item, list) {
args.append(QByteArray::number(item));
args.append(',');
}
endList();
}
void DebuggerCommand::arg(const char *value) void DebuggerCommand::arg(const char *value)
{ {
args.append("\""); args.append("\"");
@@ -823,5 +833,13 @@ void DebuggerCommand::endGroup()
args += "},"; args += "},";
} }
QByteArray DebuggerCommand::arguments() const
{
QByteArray result = args;
if (result.endsWith(','))
result.chop(1);
return result;
}
} // namespace Internal } // namespace Internal
} // namespace Debugger } // namespace Debugger

View File

@@ -32,6 +32,7 @@
#define DEBUGGER_PROTOCOL_H #define DEBUGGER_PROTOCOL_H
#include <QByteArray> #include <QByteArray>
#include <QList>
#include <QString> #include <QString>
#include <functional> #include <functional>
@@ -64,10 +65,13 @@ public:
void arg(const char *name, const QString &value); void arg(const char *name, const QString &value);
void arg(const char *name, const QByteArray &value); void arg(const char *name, const QByteArray &value);
void arg(const char *name, const char *value); void arg(const char *name, const char *value);
void arg(const char *name, const QList<int> &list);
void beginList(const char *name = 0); void beginList(const char *name = 0);
void endList(); void endList();
void beginGroup(const char *name = 0); void beginGroup(const char *name = 0);
void endGroup(); void endGroup();
QByteArray arguments() const;
QByteArray function; QByteArray function;
QByteArray args; QByteArray args;

View File

@@ -139,8 +139,8 @@ public:
int frame = -1, bool addContext = false); int frame = -1, bool addContext = false);
void lookup(const QList<int> handles, bool includeSource = false); void lookup(const QList<int> handles, bool includeSource = false);
void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false); void backtrace(int fromFrame = -1, int toFrame = -1, bool bottom = false);
void frame(int number = -1); void frame(int number);
void scope(int number = -1, int frameNumber = -1); void scope(int number, int frameNumber = -1);
void scripts(int types = 4, const QList<int> ids = QList<int>(), void scripts(int types = 4, const QList<int> ids = QList<int>(),
bool includeSource = false, const QVariant filter = QVariant()); bool includeSource = false, const QVariant filter = QVariant());
@@ -150,13 +150,9 @@ public:
void clearBreakpoint(int breakpoint); void clearBreakpoint(int breakpoint);
void setExceptionBreak(Exceptions type, bool enabled = false); void setExceptionBreak(Exceptions type, bool enabled = false);
void version();
void clearCache(); void clearCache();
void sendAndLogV8Request(const QJsonObject &request);
QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray()); QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
QJsonObject initObject();
void expandObject(const QByteArray &iname, quint64 objectId); void expandObject(const QByteArray &iname, quint64 objectId);
void flushSendBuffer(); void flushSendBuffer();
@@ -170,6 +166,7 @@ public:
bool canEvaluateScript(const QString &script); bool canEvaluateScript(const QString &script);
void updateScriptSource(const QString &fileName, int lineOffset, int columnOffset, const QString &source); void updateScriptSource(const QString &fileName, int lineOffset, int columnOffset, const QString &source);
void runCommand(const DebuggerCommand &command);
public: public:
int sequence = -1; int sequence = -1;
@@ -1322,7 +1319,11 @@ void QmlEnginePrivate::disconnect()
// "type" : "request", // "type" : "request",
// "command" : "disconnect", // "command" : "disconnect",
// } // }
QJsonObject jsonVal = initObject(); QJsonObject jsonVal = {
{_(SEQ), ++sequence},
{_(TYPE), _(REQUEST)}
};
jsonVal.insert(_(COMMAND), _(DISCONNECT)); jsonVal.insert(_(COMMAND), _(DISCONNECT));
const QByteArray msg = QJsonDocument(jsonVal).toJson(QJsonDocument::Compact); const QByteArray msg = QJsonDocument(jsonVal).toJson(QJsonDocument::Compact);
@@ -1339,27 +1340,18 @@ void QmlEnginePrivate::continueDebugging(StepAction action)
// "stepcount" : <number of steps (default 1)> // "stepcount" : <number of steps (default 1)>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(CONTINEDEBUGGING));
if (action != Continue) { DebuggerCommand cmd(CONTINEDEBUGGING);
QJsonObject args;
switch (action) { if (action == StepIn)
case StepIn: cmd.arg(STEPACTION, IN);
args.insert(_(STEPACTION), _(IN)); else if (action == StepOut)
break; cmd.arg(STEPACTION, OUT);
case StepOut: else if (action == Next)
args.insert(_(STEPACTION), _(OUT)); cmd.arg(STEPACTION, NEXT);
break;
case Next: runCommand(cmd);
args.insert(_(STEPACTION), _(NEXT));
break;
default:break;
}
jsonVal.insert(_(ARGUMENTS), args);
}
sendAndLogV8Request(jsonVal);
previousStepAction = action; previousStepAction = action;
} }
@@ -1380,45 +1372,37 @@ void QmlEnginePrivate::evaluate(const QString expr, bool global,
// ] // ]
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(EVALUATE));
QJsonObject args { DebuggerCommand cmd(EVALUATE);
{ _(EXPRESSION), expr }
}; cmd.arg(EXPRESSION, expr);
if (frame != -1) if (frame != -1)
args.insert(_(FRAME), frame); cmd.arg(FRAME, frame);
if (global) if (global)
args.insert(_(GLOBAL), global); cmd.arg(GLOBAL, global);
if (disableBreak) if (disableBreak)
args.insert(_(DISABLE_BREAK), disableBreak); cmd.arg(DISABLE_BREAK, disableBreak);
if (addContext) { if (addContext) {
WatchHandler *watchHandler = engine->watchHandler(); WatchHandler *watchHandler = engine->watchHandler();
QAbstractItemModel *watchModel = watchHandler->model(); QAbstractItemModel *watchModel = watchHandler->model();
int rowCount = watchModel->rowCount(); int rowCount = watchModel->rowCount();
QJsonArray ctxtList; cmd.beginList(ADDITIONAL_CONTEXT);
while (rowCount) { for (int row = 0; row < rowCount; ++row) {
QModelIndex index = watchModel->index(--rowCount, 0); QModelIndex index = watchModel->index(row, 0); // FIXME: This looks wrong.
const WatchData *data = watchHandler->watchItem(index); const WatchData *data = watchHandler->watchItem(index);
const QJsonObject ctxt { cmd.beginGroup();
{ _(NAME), data->name }, cmd.arg(NAME, data->name);
{ _(HANDLE), int(data->id) } cmd.arg(HANDLE, int(data->id));
}; cmd.endGroup();
ctxtList.push_front(ctxt);
} }
args.insert(_(ADDITIONAL_CONTEXT), ctxtList);
} }
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::lookup(QList<int> handles, bool includeSource) void QmlEnginePrivate::lookup(QList<int> handles, bool includeSource)
@@ -1432,22 +1416,15 @@ void QmlEnginePrivate::lookup(QList<int> handles, bool includeSource)
// script objects are returned>, // script objects are returned>,
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(LOOKUP));
QJsonObject args; DebuggerCommand cmd(LOOKUP);
QJsonArray array; cmd.arg(HANDLES, handles);
foreach (int handle, handles)
array.push_back(handle);
args.insert(_(HANDLES), array);
if (includeSource) if (includeSource)
args.insert(_(INCLUDESOURCE), includeSource); cmd.arg(INCLUDESOURCE, includeSource);
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::backtrace(int fromFrame, int toFrame, bool bottom) void QmlEnginePrivate::backtrace(int fromFrame, int toFrame, bool bottom)
@@ -1461,23 +1438,19 @@ void QmlEnginePrivate::backtrace(int fromFrame, int toFrame, bool bottom)
// stack is requested> // stack is requested>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(BACKTRACE));
QJsonObject args; DebuggerCommand cmd(BACKTRACE);
if (fromFrame != -1) if (fromFrame != -1)
args.insert(_(FROMFRAME), fromFrame); cmd.arg(FROMFRAME, fromFrame);
if (toFrame != -1) if (toFrame != -1)
args.insert(_(TOFRAME), toFrame); cmd.arg(TOFRAME, toFrame);
if (bottom) if (bottom)
args.insert(_(BOTTOM), bottom); cmd.arg(BOTTOM, bottom);
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::frame(int number) void QmlEnginePrivate::frame(int number)
@@ -1488,18 +1461,12 @@ void QmlEnginePrivate::frame(int number)
// "arguments" : { "number" : <frame number> // "arguments" : { "number" : <frame number>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(FRAME));
if (number != -1) { DebuggerCommand cmd(FRAME);
const QJsonObject args { if (number != -1)
{ _(NUMBER), number } cmd.arg(NUMBER, number);
};
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
}
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::scope(int number, int frameNumber) void QmlEnginePrivate::scope(int number, int frameNumber)
@@ -1512,21 +1479,13 @@ void QmlEnginePrivate::scope(int number, int frameNumber)
// frame if missing> // frame if missing>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(SCOPE));
if (number != -1) { DebuggerCommand cmd(SCOPE);
QJsonObject args { cmd.arg(NUMBER, number);
{ _(NUMBER), number } if (frameNumber != -1)
}; cmd.arg(FRAMENUMBER, frameNumber);
if (frameNumber != -1) runCommand(cmd);
args.insert(_(FRAMENUMBER), frameNumber);
jsonVal.insert(_(ARGUMENTS), args);
}
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::scripts(int types, const QList<int> ids, bool includeSource, void QmlEnginePrivate::scripts(int types, const QList<int> ids, bool includeSource,
@@ -1547,37 +1506,24 @@ void QmlEnginePrivate::scripts(int types, const QList<int> ids, bool includeSour
// If a string is specified, then only scripts whose names contain the filter string will be retrieved.> // If a string is specified, then only scripts whose names contain the filter string will be retrieved.>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(SCRIPTS));
QJsonObject args { DebuggerCommand cmd(SCRIPTS);
{ _(TYPES), types } cmd.arg(TYPES, types);
};
if (ids.count()) { if (ids.count())
QJsonArray array; cmd.arg(IDS, ids);
foreach (int id, ids) {
array.push_back(id);
}
args.insert(_(IDS), array);
}
if (includeSource) if (includeSource)
args.insert(_(INCLUDESOURCE), includeSource); cmd.arg(INCLUDESOURCE, includeSource);
QJsonValue filterValue;
if (filter.type() == QVariant::String) if (filter.type() == QVariant::String)
filterValue = filter.toString(); cmd.arg(FILTER, filter.toString());
else if (filter.type() == QVariant::Int) else if (filter.type() == QVariant::Int)
filterValue = filter.toInt(); cmd.arg(FILTER, filter.toInt());
else else
QTC_CHECK(!filter.isValid()); QTC_CHECK(!filter.isValid());
args.insert(_(FILTER), filterValue); runCommand(cmd);
jsonVal.insert(_(ARGUMENTS), args);
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::setBreakpoint(const QString type, const QString target, void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
@@ -1604,33 +1550,25 @@ void QmlEnginePrivate::setBreakpoint(const QString type, const QString target,
sendMessage(packMessage(BREAKONSIGNAL, params)); sendMessage(packMessage(BREAKONSIGNAL, params));
} else { } else {
QJsonObject jsonVal = initObject(); DebuggerCommand cmd(SETBREAKPOINT);
jsonVal.insert(_(COMMAND), _(SETBREAKPOINT)); cmd.arg(TYPE, type);
cmd.arg(ENABLED, enabled);
QJsonObject args {
{ _(TYPE), type },
{ _(ENABLED), enabled }
};
if (type == _(SCRIPTREGEXP)) if (type == _(SCRIPTREGEXP))
args.insert(_(TARGET), Utils::FileName::fromString(target).fileName()); cmd.arg(TARGET, Utils::FileName::fromString(target).fileName());
else else
args.insert(_(TARGET), target); cmd.arg(TARGET, target);
if (line) if (line)
args.insert(_(LINE), line - 1); cmd.arg(LINE, line - 1);
if (column) if (column)
args.insert(_(COLUMN), column - 1); cmd.arg(COLUMN, column - 1);
if (!condition.isEmpty()) if (!condition.isEmpty())
args.insert(_(CONDITION), condition); cmd.arg(CONDITION, condition);
if (ignoreCount != -1) if (ignoreCount != -1)
args.insert(_(IGNORECOUNT), ignoreCount); cmd.arg(IGNORECOUNT, ignoreCount);
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
sendAndLogV8Request(jsonVal);
} }
} }
@@ -1642,16 +1580,10 @@ void QmlEnginePrivate::clearBreakpoint(int breakpoint)
// "arguments" : { "breakpoint" : <number of the break point to clear> // "arguments" : { "breakpoint" : <number of the break point to clear>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(CLEARBREAKPOINT));
QJsonObject args { DebuggerCommand cmd(CLEARBREAKPOINT);
{ _(BREAKPOINT), breakpoint } cmd.arg(BREAKPOINT, breakpoint);
}; runCommand(cmd);
jsonVal.insert(_(ARGUMENTS), args);
sendAndLogV8Request(jsonVal);
} }
void QmlEnginePrivate::setExceptionBreak(Exceptions type, bool enabled) void QmlEnginePrivate::setExceptionBreak(Exceptions type, bool enabled)
@@ -1663,35 +1595,19 @@ void QmlEnginePrivate::setExceptionBreak(Exceptions type, bool enabled)
// "enabled" : <optional bool: enables the break type if true> // "enabled" : <optional bool: enables the break type if true>
// } // }
// } // }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(SETEXCEPTIONBREAK));
QJsonObject args;
DebuggerCommand cmd(SETEXCEPTIONBREAK);
if (type == AllExceptions) if (type == AllExceptions)
args.insert(_(TYPE), _(ALL)); cmd.arg(TYPE, ALL);
//Not Supported
// else if (type == UncaughtExceptions) //Not Supported:
// args.setProperty(_(TYPE),QScriptValue(_(UNCAUGHT))); // else if (type == UncaughtExceptions)
// cmd.args(TYPE, UNCAUGHT);
if (enabled) if (enabled)
args.insert(_(ENABLED), enabled); cmd.arg(ENABLED, enabled);
jsonVal.insert(_(ARGUMENTS), args); runCommand(cmd);
sendAndLogV8Request(jsonVal);
}
void QmlEnginePrivate::version()
{
// { "seq" : <number>,
// "type" : "request",
// "command" : "version",
// }
QJsonObject jsonVal = initObject();
jsonVal.insert(_(COMMAND), _(VERSION));
sendAndLogV8Request(jsonVal);
} }
QVariant valueFromRef(int handle, const QVariant &refsVal, bool *success) QVariant valueFromRef(int handle, const QVariant &refsVal, bool *success)
@@ -1837,19 +1753,22 @@ QByteArray QmlEnginePrivate::packMessage(const QByteArray &type, const QByteArra
return request; return request;
} }
QJsonObject QmlEnginePrivate::initObject() void QmlEnginePrivate::runCommand(const DebuggerCommand &command)
{ {
return QJsonObject { // Leave items as variables, serialization depends on it.
{_(SEQ), ++sequence}, QByteArray cmd = V8DEBUG;
{_(TYPE), _(REQUEST)} QByteArray type = V8REQUEST;
}; QByteArray msg = "{\"seq\":" + QByteArray::number(++sequence) + ","
} + "\"type\":\"request\","
+ "\"command\":\"" + command.function + "\","
+ "\"arguments\":{" + command.arguments() + "}}";
void QmlEnginePrivate::sendAndLogV8Request(const QJsonObject &request)
{
const QByteArray msg = QJsonDocument(request).toJson(QJsonDocument::Compact);
engine->showMessage(QString::fromLatin1("%1 %2").arg(_(V8REQUEST), QString::fromUtf8(msg)), LogInput); engine->showMessage(QString::fromLatin1("%1 %2").arg(_(V8REQUEST), QString::fromUtf8(msg)), LogInput);
sendMessage(packMessage(V8REQUEST, msg));
QByteArray request;
QmlDebugStream rs(&request, QIODevice::WriteOnly);
rs << cmd << type << msg;
sendMessage(request);
} }
void QmlEnginePrivate::expandObject(const QByteArray &iname, quint64 objectId) void QmlEnginePrivate::expandObject(const QByteArray &iname, quint64 objectId)
@@ -2643,9 +2562,8 @@ void QmlEnginePrivate::stateChanged(State state)
/// Start session. /// Start session.
flushSendBuffer(); flushSendBuffer();
connect(); connect();
//Query for the V8 version. This is // Query for the V8 version. This is only for logging to the log.
//only for logging to the debuggerlog runCommand(VERSION);
version();
} }
} }