summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAurindam Jana <aurindam.jana@nokia.com>2012-02-16 15:58:40 +0100
committerAurindam Jana <aurindam.jana@nokia.com>2012-02-21 12:51:42 +0100
commit9720c0d737a325b64e6e5227c21a27012583de4a (patch)
tree27b93678aa3aafcd669e5d2924ced5b0eb36fc2c /src
parent4667371b9a0a901602b606be120f334f0492d2e1 (diff)
downloadqt-creator-9720c0d737a325b64e6e5227c21a27012583de4a.tar.gz
QmlDebugging: Show Object Tree in Console
Show QML/Javascript objects as a tree when evaluated in the console. Change-Id: I42901bf9bda3f18fb9fb1ca309a8370ccbe37c0a Reviewed-by: Kai Koehne <kai.koehne@nokia.com>
Diffstat (limited to 'src')
-rw-r--r--src/plugins/debugger/qml/qmlengine.cpp51
-rw-r--r--src/plugins/debugger/qml/qmlengine.h3
-rw-r--r--src/plugins/debugger/qml/qmlv8debuggerclient.cpp264
-rw-r--r--src/plugins/debugger/qml/qmlv8debuggerclient.h2
4 files changed, 188 insertions, 132 deletions
diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp
index 8c24aa0313..52da3723ed 100644
--- a/src/plugins/debugger/qml/qmlengine.cpp
+++ b/src/plugins/debugger/qml/qmlengine.cpp
@@ -804,11 +804,11 @@ void QmlEngine::onDebugQueryStateChanged(
QmlJsDebugClient::QDeclarativeDebugExpressionQuery *query =
qobject_cast<QmlJsDebugClient::QDeclarativeDebugExpressionQuery *>(
sender());
- if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error)
- qtMessageLogHandler()->
- appendItem(new QtMessageLogItem(QtMessageLogHandler::UndefinedType,
- query->result().toString()));
- else
+ if (query && state != QmlJsDebugClient::QDeclarativeDebugQuery::Error) {
+ QtMessageLogItem *item = constructLogItemTree(query->result());
+ if (item)
+ qtMessageLogHandler()->appendItem(item);
+ } else
qtMessageLogHandler()->
appendItem(new QtMessageLogItem(QtMessageLogHandler::ErrorType,
_("Error evaluating expression.")));
@@ -1050,6 +1050,47 @@ bool QmlEngine::canEvaluateScript(const QString &script)
return d->m_interpreter.canEvaluate();
}
+QtMessageLogItem *QmlEngine::constructLogItemTree(
+ const QVariant &result, const QString &key)
+{
+ if (!result.isValid())
+ return 0;
+
+ QtMessageLogItem *item = new QtMessageLogItem();
+ if (result.type() == QVariant::Map) {
+ if (key.isEmpty())
+ item->setText(_("Object"));
+ else
+ item->setText(QString(_("%1: Object")).arg(key));
+
+ QMapIterator<QString, QVariant> i(result.toMap());
+ while (i.hasNext()) {
+ i.next();
+ QtMessageLogItem *child = constructLogItemTree(i.value(), i.key());
+ if (child)
+ item->insertChild(item->childCount(), child);
+ }
+ } else if (result.type() == QVariant::List) {
+ if (key.isEmpty())
+ item->setText(_("List"));
+ else
+ item->setText(QString(_("[%1] : List")).arg(key));
+ QVariantList resultList = result.toList();
+ for (int i = 0; i < resultList.count(); i++) {
+ QtMessageLogItem *child = constructLogItemTree(resultList.at(i),
+ QString::number(i));
+ if (child)
+ item->insertChild(item->childCount(), child);
+ }
+ } else if (result.canConvert(QVariant::String)) {
+ item->setText(result.toString());
+ } else {
+ item->setText(_("Unknown Value"));
+ }
+
+ return item;
+}
+
QmlAdapter *QmlEngine::adapter() const
{
return &d->m_adapter;
diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h
index e3df9e9b9c..abf80cbb1d 100644
--- a/src/plugins/debugger/qml/qmlengine.h
+++ b/src/plugins/debugger/qml/qmlengine.h
@@ -53,6 +53,7 @@ class QmlAdapter;
namespace Internal {
+class QtMessageLogItem;
class QmlEnginePrivate;
class QmlEngine : public DebuggerEngine
@@ -182,6 +183,8 @@ private:
void updateEditor(Core::IEditor *editor, const QTextDocument *document);
bool canEvaluateScript(const QString &script);
+ QtMessageLogItem *constructLogItemTree(const QVariant &result,
+ const QString &key = QString());
private:
friend class QmlCppEngine;
diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp
index 0a30be2164..9ef0989308 100644
--- a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp
+++ b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp
@@ -39,6 +39,7 @@
#include "breakhandler.h"
#include "qmlengine.h"
#include "stackhandler.h"
+#include "qtmessageloghandler.h"
#include <utils/qtcassert.h>
#include <coreplugin/editormanager/editormanager.h>
@@ -68,9 +69,11 @@ namespace Internal {
typedef QPair<QByteArray, QByteArray> WatchDataPair;
struct QmlV8ObjectData {
+ int handle;
+ QByteArray name;
QByteArray type;
QVariant value;
- QVariant properties;
+ QVariantList properties;
};
class QmlV8DebuggerClientPrivate
@@ -117,7 +120,7 @@ public:
//void profile(ProfileCommand command); //NOT SUPPORTED
void gc();
- QmlV8ObjectData extractData(const QVariant &data);
+ QmlV8ObjectData extractData(const QVariant &data, const QVariant &refsVal);
void clearCache();
void logSendMessage(const QString &msg) const;
@@ -126,10 +129,12 @@ public:
//TODO:: remove this method
void reformatRequest(QByteArray &request);
+ QtMessageLogItem *constructLogItemTree(const QmlV8ObjectData &objectData,
+ const QVariant &refsVal);
private:
QByteArray packMessage(const QByteArray &type, const QByteArray &message = QByteArray());
QScriptValue initObject();
-
+ QVariant valueFromRef(int handle, const QVariant &refsVal, bool *success);
public:
QmlV8DebuggerClient *q;
@@ -149,7 +154,6 @@ public:
//Cache
QStringList watchedExpressions;
- QVariant refsVal;
QList<int> currentFrameScopes;
//TODO: remove this flag
@@ -779,7 +783,8 @@ void QmlV8DebuggerClientPrivate::gc()
q->sendMessage(packMessage(V8REQUEST, jsonMessage.toString().toUtf8()));
}
-QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data)
+QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data,
+ const QVariant &refsVal)
{
// { "handle" : <handle>,
// "type" : <"undefined", "null", "boolean", "number", "string", "object", "function" or "frame">
@@ -834,41 +839,56 @@ QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data)
QmlV8ObjectData objectData;
const QVariantMap dataMap = data.toMap();
- QString type = dataMap.value(_(TYPE)).toString();
- if (type == _("undefined")) {
- objectData.type = QByteArray("undefined");
- objectData.value = QVariant(_("undefined"));
+ objectData.name = dataMap.value(_(NAME)).toByteArray();
+
+ if (dataMap.contains(_(REF))) {
+ objectData.handle = dataMap.value(_(REF)).toInt();
+ bool success;
+ QVariant dataFromRef = valueFromRef(objectData.handle, refsVal, &success);
+ if (success) {
+ QmlV8ObjectData data = extractData(dataFromRef, refsVal);
+ objectData.type = data.type;
+ objectData.value = data.value;
+ objectData.properties = data.properties;
+ }
+ } else {
+ QString type = dataMap.value(_(TYPE)).toString();
+
+ if (type == _("undefined")) {
+ objectData.type = QByteArray("undefined");
+ objectData.value = QVariant(_("undefined"));
- } else if (type == _("null")) {
- objectData.type = QByteArray("null");
- objectData.value= QVariant(_("null"));
+ } else if (type == _("null")) {
+ objectData.type = QByteArray("null");
+ objectData.value= QVariant(_("null"));
- } else if (type == _("boolean")) {
- objectData.type = QByteArray("boolean");
- objectData.value = dataMap.value(_(VALUE));
+ } else if (type == _("boolean")) {
+ objectData.type = QByteArray("boolean");
+ objectData.value = dataMap.value(_(VALUE));
- } else if (type == _("number")) {
- objectData.type = QByteArray("number");
- objectData.value = dataMap.value(_(VALUE));
+ } else if (type == _("number")) {
+ objectData.type = QByteArray("number");
+ objectData.value = dataMap.value(_(VALUE));
- } else if (type == _("string")) {
- objectData.type = QByteArray("string");
- objectData.value = dataMap.value(_(VALUE));
+ } else if (type == _("string")) {
+ objectData.type = QByteArray("string");
+ objectData.value = dataMap.value(_(VALUE));
- } else if (type == _("object")) {
- objectData.type = QByteArray("object");
- objectData.value = dataMap.value(_("className"));
- objectData.properties = dataMap.value(_("properties"));
+ } else if (type == _("object")) {
+ objectData.type = QByteArray("object");
+ objectData.value = dataMap.value(_("className"));
+ objectData.properties = dataMap.value(_("properties")).toList();
- } else if (type == _("function")) {
- objectData.type = QByteArray("function");
- objectData.value = dataMap.value(_(NAME));
- objectData.properties = dataMap.value(_("properties"));
+ } else if (type == _("function")) {
+ objectData.type = QByteArray("function");
+ objectData.value = dataMap.value(_(NAME));
+ objectData.properties = dataMap.value(_("properties")).toList();
- } else if (type == _("script")) {
- objectData.type = QByteArray("script");
- objectData.value = dataMap.value(_(NAME));
+ } else if (type == _("script")) {
+ objectData.type = QByteArray("script");
+ objectData.value = dataMap.value(_(NAME));
+ }
}
return objectData;
@@ -877,7 +897,6 @@ QmlV8ObjectData QmlV8DebuggerClientPrivate::extractData(const QVariant &data)
void QmlV8DebuggerClientPrivate::clearCache()
{
watchedExpressions.clear();
- refsVal.clear();
currentFrameScopes.clear();
}
@@ -903,6 +922,24 @@ QScriptValue QmlV8DebuggerClientPrivate::initObject()
return jsonVal;
}
+QVariant QmlV8DebuggerClientPrivate::valueFromRef(int handle,
+ const QVariant &refsVal,
+ bool *success)
+{
+ *success = false;
+ QVariant variant;
+ const QVariantList refs = refsVal.toList();
+ foreach (const QVariant &ref, refs) {
+ const QVariantMap refData = ref.toMap();
+ if (refData.value(_(HANDLE)).toInt() == handle) {
+ variant = refData;
+ *success = true;
+ break;
+ }
+ }
+ return variant;
+}
+
void QmlV8DebuggerClientPrivate::logSendMessage(const QString &msg) const
{
if (engine)
@@ -956,6 +993,33 @@ void QmlV8DebuggerClientPrivate::reformatRequest(QByteArray &request)
}
}
+QtMessageLogItem *QmlV8DebuggerClientPrivate::constructLogItemTree(
+ const QmlV8ObjectData &objectData,
+ const QVariant &refsVal)
+{
+ if (!objectData.value.isValid())
+ return 0;
+
+ QString text;
+ if (objectData.name.isEmpty())
+ text = objectData.value.toString();
+ else
+ text = QString(_("%1: %2")).arg(QString::fromAscii(objectData.name))
+ .arg(objectData.value.toString());
+
+ QtMessageLogItem *item = new QtMessageLogItem(
+ QtMessageLogHandler::UndefinedType, text);
+
+ foreach (const QVariant &property, objectData.properties) {
+ QtMessageLogItem *child = constructLogItemTree(
+ extractData(property, refsVal), refsVal);
+ if (child)
+ item->insertChild(item->childCount(), child);
+ }
+
+ return item;
+}
+
///////////////////////////////////////////////////////////////////////
//
// QmlV8DebuggerClient
@@ -1525,7 +1589,6 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data)
}
}
-
void QmlV8DebuggerClient::updateStack(const QVariant &bodyVal, const QVariant &refsVal)
{
// { "seq" : <number>,
@@ -1600,27 +1663,18 @@ StackFrame QmlV8DebuggerClient::insertStackFrame(const QVariant &bodyVal, const
StackFrame stackFrame;
stackFrame.level = body.value(_("index")).toInt();
- QVariantMap func = body.value(_("func")).toMap();
- if (func.contains(_(REF))) {
- func = valueFromRef(func.value(_(REF)).toInt(), refsVal).toMap();
- }
- QString functionName = d->extractData(QVariant(func)).value.toString();
+ QmlV8ObjectData objectData = d->extractData(body.value(_("func")), refsVal);
+ QString functionName = objectData.value.toString();
if (functionName.isEmpty())
functionName = tr("anonymous function");
stackFrame.function = functionName;
- QVariantMap file = body.value(_("script")).toMap();
- if (file.contains(_(REF))) {
- file = valueFromRef(file.value(_(REF)).toInt(), refsVal).toMap();
- }
- stackFrame.file = d->engine->toFileInProject(d->extractData(QVariant(file)).value.toString());
+ objectData = d->extractData(body.value(_("script")), refsVal);
+ stackFrame.file = d->engine->toFileInProject(objectData.value.toString());
stackFrame.usable = QFileInfo(stackFrame.file).isReadable();
- QVariantMap receiver = body.value(_("receiver")).toMap();
- if (receiver.contains(_(REF))) {
- receiver = valueFromRef(receiver.value(_(REF)).toInt(), refsVal).toMap();
- }
- stackFrame.to = d->extractData(QVariant(receiver)).value.toString();
+ objectData = d->extractData(body.value(_("receiver")), refsVal);
+ stackFrame.to = objectData.value.toString();
stackFrame.line = body.value(_("line")).toInt() + 1;
@@ -1665,22 +1719,18 @@ void QmlV8DebuggerClient::setCurrentFrameDetails(const QVariant &bodyVal, const
int frameIndex = currentFrame.value(QLatin1String("index")).toInt();
d->clearCache();
- d->refsVal = refsVal;
//Set "this" variable
{
WatchData data;
data.exp = QByteArray("this");
data.name = QLatin1String(data.exp);
data.iname = QByteArray("local.") + data.exp;
- QVariantMap receiver = currentFrame.value(_("receiver")).toMap();
- if (receiver.contains(_(REF))) {
- receiver = valueFromRef(receiver.value(_(REF)).toInt(), refsVal).toMap();
- }
- data.id = receiver.value(_("handle")).toInt();
- QmlV8ObjectData receiverData = d->extractData(QVariant(receiver));
- data.type = receiverData.type;
- data.value = receiverData.value.toString();
- data.setHasChildren(receiverData.properties.toList().count());
+ QmlV8ObjectData objectData = d->extractData(
+ currentFrame.value(_("receiver")), refsVal);
+ data.id = objectData.handle;
+ data.type = objectData.type;
+ data.value = objectData.value.toString();
+ data.setHasChildren(objectData.properties.count());
d->engine->watchHandler()->beginCycle();
d->engine->watchHandler()->insertData(data);
d->engine->watchHandler()->endCycle();
@@ -1730,20 +1780,14 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r
if (bodyMap.value(_("frameIndex")).toInt() != stackHandler->currentIndex())
return;
- QVariantMap object = bodyMap.value(_("object")).toMap();
- if (object.contains(_(REF))) {
- object = valueFromRef(object.value(_(REF)).toInt(),
- refsVal).toMap();
- }
-
- const QVariantList properties = object.value(_("properties")).toList();
+ QmlV8ObjectData objectData = d->extractData(bodyMap.value(_("object")), refsVal);
QList<int> handlesToLookup;
QList<WatchData> locals;
- foreach (const QVariant &property, properties) {
- QVariantMap localData = property.toMap();
+ foreach (const QVariant &property, objectData.properties) {
+ QmlV8ObjectData localData = d->extractData(property, refsVal);
WatchData data;
- data.exp = localData.value(_(NAME)).toByteArray();
+ data.exp = localData.name;
//Check for v8 specific local data
if (data.exp.startsWith('.') || data.exp.isEmpty())
continue;
@@ -1751,22 +1795,16 @@ void QmlV8DebuggerClient::updateScope(const QVariant &bodyVal, const QVariant &r
data.name = QLatin1String(data.exp);
data.iname = QByteArray("local.") + data.exp;
- int handle = localData.value(_(REF)).toInt();
- localData = valueFromRef(handle, d->refsVal).toMap();
- if (localData.isEmpty()) {
+ int handle = localData.handle;
+ if (localData.value.isValid()) {
+ data.id = handle;
+ data.type = localData.type;
+ data.value = localData.value.toString();
+ data.setHasChildren(localData.properties.count());
+ locals << data;
+ } else {
handlesToLookup << handle;
d->localsAndWatchers.insert(handle, data.exp);
-
- } else {
- data.id = localData.value(_(HANDLE)).toInt();
-
- QmlV8ObjectData objectData = d->extractData(QVariant(localData));
- data.type = objectData.type;
- data.value = objectData.value.toString();
-
- data.setHasChildren(objectData.properties.toList().count());
-
- locals << data;
}
}
@@ -1797,13 +1835,7 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
d->scope(index);
} else {
- QVariantMap bodyMap = bodyVal.toMap();
- if (bodyMap.contains(_(REF))) {
- bodyMap = valueFromRef(bodyMap.value(_(REF)).toInt(),
- refsVal).toMap();
- }
-
- QmlV8ObjectData body = d->extractData(QVariant(bodyMap));
+ QmlV8ObjectData body = d->extractData(bodyVal, refsVal);
QString exp = d->evaluatingExpression.take(sequence);
if (d->watchedExpressions.contains(exp)) {
QByteArray iname = d->engine->watchHandler()->watcherName(exp.toLatin1());
@@ -1812,11 +1844,11 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
data.exp = exp.toLatin1();
data.name = exp;
data.iname = iname;
- data.id = bodyMap.value(_(HANDLE)).toInt();
+ data.id = body.handle;
if (success) {
data.type = body.type;
data.value = body.value.toString();
- data.hasChildren = body.properties.toList().count();
+ data.hasChildren = body.properties.count();
} else {
//Do not set type since it is unknown
data.setError(body.value.toString());
@@ -1828,7 +1860,9 @@ void QmlV8DebuggerClient::updateEvaluationResult(int sequence, bool success, con
d->engine->watchHandler()->endCycle();
} else {
- d->engine->showMessage(body.value.toString(), QtMessageLogOutput);
+ QtMessageLogItem *item = d->constructLogItemTree(body, refsVal);
+ if (item)
+ d->engine->qtMessageLogHandler()->appendItem(item);
//Update the locals
foreach (int index, d->currentFrameScopes)
d->scope(index);
@@ -1886,20 +1920,6 @@ void QmlV8DebuggerClient::updateBreakpoints(const QVariant &bodyVal)
}
}
-QVariant QmlV8DebuggerClient::valueFromRef(int handle, const QVariant &refsVal)
-{
- QVariant variant;
- const QVariantList refs = refsVal.toList();
- foreach (const QVariant &ref, refs) {
- const QVariantMap refData = ref.toMap();
- if (refData.value(_(HANDLE)).toInt() == handle) {
- variant = refData;
- break;
- }
- }
- return variant;
-}
-
void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal)
{
// { "seq" : <number>,
@@ -1916,27 +1936,26 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
QStringList handlesList = body.keys();
foreach (const QString &handle, handlesList) {
QmlV8ObjectData bodyObjectData = d->extractData(
- body.value(handle));
+ body.value(handle), refsVal);
QByteArray prepend = d->localsAndWatchers.take(handle.toInt());
-
if (prepend.startsWith("local.") || prepend.startsWith("watch.")) {
//Data for expanded local/watch
- if (bodyObjectData.properties.isValid()) {
+ if (bodyObjectData.properties.count()) {
//Could be an object or function
const WatchData *parent = d->engine->watchHandler()->findItem(prepend);
- const QVariantList properties = bodyObjectData.properties.toList();
- foreach (const QVariant &property, properties) {
- QVariantMap propertyData = property.toMap();
+ foreach (const QVariant &property, bodyObjectData.properties) {
+ QmlV8ObjectData propertyData = d->extractData(property, refsVal);
WatchData data;
- data.name = propertyData.value(_(NAME)).toString();
+ data.name = propertyData.name;
//Check for v8 specific local data
if (data.name.startsWith(QLatin1Char('.')) || data.name.isEmpty())
continue;
if (parent && parent->type == "object") {
if (parent->value == _("Array"))
- data.exp = parent->exp + QByteArray("[") + data.name.toLatin1() + QByteArray("]");
+ data.exp = parent->exp + QByteArray("[") +
+ data.name.toLatin1() + QByteArray("]");
else if (parent->value == _("Object"))
data.exp = parent->exp + QByteArray(".") + data.name.toLatin1();
} else {
@@ -1944,15 +1963,10 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
}
data.iname = prepend + '.' + data.name.toLatin1();
- propertyData = valueFromRef(propertyData.value(_(REF)).toInt(),
- refsVal).toMap();
- data.id = propertyData.value(_(HANDLE)).toInt();
-
- QmlV8ObjectData objectData = d->extractData(QVariant(propertyData));
- data.type = objectData.type;
- data.value = objectData.value.toString();
-
- data.setHasChildren(objectData.properties.toList().count());
+ data.id = propertyData.handle;
+ data.type = propertyData.type;
+ data.value = propertyData.value.toString();
+ data.setHasChildren(propertyData.properties.count());
watchDataList << data;
}
}
@@ -1967,7 +1981,7 @@ void QmlV8DebuggerClient::expandLocalsAndWatchers(const QVariant &bodyVal, const
data.type = bodyObjectData.type;
data.value = bodyObjectData.value.toString();
- data.setHasChildren(bodyObjectData.properties.toList().count());
+ data.setHasChildren(bodyObjectData.properties.count());
watchDataList << data;
}
diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.h b/src/plugins/debugger/qml/qmlv8debuggerclient.h
index 04e4e46843..3f68b0e64e 100644
--- a/src/plugins/debugger/qml/qmlv8debuggerclient.h
+++ b/src/plugins/debugger/qml/qmlv8debuggerclient.h
@@ -113,8 +113,6 @@ private:
const QVariant &refsVal);
void updateBreakpoints(const QVariant &bodyVal);
- QVariant valueFromRef(int handle, const QVariant &refsVal);
-
void expandLocalsAndWatchers(const QVariant &bodyVal, const QVariant &refsVal);
void highlightExceptionCode(int lineNumber, const QString &filePath,