diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2011-06-21 14:38:44 (GMT) |
---|---|---|
committer | Kai Koehne <kai.koehne@nokia.com> | 2011-06-22 08:05:33 (GMT) |
commit | d349c879e1d55e4cd2b7d31c08e2796c0fec4020 (patch) | |
tree | f1e5ba4f3d71f3ef607e1b81ba53c506963eb41e /src/declarative/debugger | |
parent | 6cb43a9b72c67b71409a59fdeb419f390441f0c7 (diff) | |
download | Qt-d349c879e1d55e4cd2b7d31c08e2796c0fec4020.zip Qt-d349c879e1d55e4cd2b7d31c08e2796c0fec4020.tar.gz Qt-d349c879e1d55e4cd2b7d31c08e2796c0fec4020.tar.bz2 |
QDeclarativeDebug: Add code coverage information
Add messages to track the lines of JavaScript that are executed.
Patch done by Janne Virranmaki <ext-janne.1.virranmaki@nokia.com>
Reviewed-by: kkoehne
Diffstat (limited to 'src/declarative/debugger')
-rw-r--r-- | src/declarative/debugger/qjsdebuggeragent.cpp | 42 | ||||
-rw-r--r-- | src/declarative/debugger/qjsdebuggeragent_p.h | 12 | ||||
-rw-r--r-- | src/declarative/debugger/qjsdebugservice.cpp | 53 | ||||
-rw-r--r-- | src/declarative/debugger/qjsdebugservice_p.h | 24 |
4 files changed, 124 insertions, 7 deletions
diff --git a/src/declarative/debugger/qjsdebuggeragent.cpp b/src/declarative/debugger/qjsdebuggeragent.cpp index dff637b..683032b 100644 --- a/src/declarative/debugger/qjsdebuggeragent.cpp +++ b/src/declarative/debugger/qjsdebuggeragent.cpp @@ -41,6 +41,7 @@ #include "private/qjsdebuggeragent_p.h" #include "private/qdeclarativedebughelper_p.h" +#include "private/qjsdebugservice_p.h" #include <QtCore/qdatetime.h> #include <QtCore/qcoreapplication.h> @@ -56,7 +57,7 @@ class QJSDebuggerAgentPrivate { public: QJSDebuggerAgentPrivate(QJSDebuggerAgent *q) - : q(q), state(NoState), isInitialized(false) + : q(q), state(NoState), isInitialized(false), coverageEnabled(false) {} void continueExec(); @@ -80,6 +81,7 @@ public: QStringList watchExpressions; QSet<qint64> knownObjectIds; bool isInitialized; + bool coverageEnabled; }; namespace { @@ -261,6 +263,12 @@ bool QJSDebuggerAgent::isInitialized() const return d->isInitialized; } +void QJSDebuggerAgent::setCoverageEnabled(bool enabled) +{ + d->isInitialized = true; + d->coverageEnabled = enabled; +} + void QJSDebuggerAgent::setBreakpoints(const JSAgentBreakpoints &breakpoints) { d->breakpoints = breakpoints; @@ -417,10 +425,16 @@ void QJSDebuggerAgent::setProperty(qint64 objectId, \reimp */ void QJSDebuggerAgent::scriptLoad(qint64 id, const QString &program, - const QString &fileName, int) + const QString &fileName, int baseLineNumber) { - Q_UNUSED(program); d->filenames.insert(id, fileName); + + if (d->coverageEnabled) { + JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageScriptLoad, + id, program, fileName, baseLineNumber, + 0, 0, QString()}; + QJSDebugService::instance()->processMessage(rd); + } } /*! @@ -450,8 +464,14 @@ void QJSDebuggerAgent::contextPop() */ void QJSDebuggerAgent::functionEntry(qint64 scriptId) { - Q_UNUSED(scriptId); d->stepDepth++; + + if (d->coverageEnabled) { + JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncEntry, + scriptId, QString(), QString(), 0, 0, 0, QString()}; + QJSDebugService::instance()->processMessage(rd); + QJSDebugService::instance()->m_timer.restart(); + } } /*! @@ -459,9 +479,13 @@ void QJSDebuggerAgent::functionEntry(qint64 scriptId) */ void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnValue) { - Q_UNUSED(scriptId); - Q_UNUSED(returnValue); d->stepDepth--; + + if (d->coverageEnabled) { + JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoverageFuncExit, + scriptId, QString(), QString(), 0, 0, 0, returnValue.toString()}; + QJSDebugService::instance()->processMessage(rd); + } } /*! @@ -470,6 +494,12 @@ void QJSDebuggerAgent::functionExit(qint64 scriptId, const QScriptValue &returnV void QJSDebuggerAgent::positionChange(qint64 scriptId, int lineNumber, int columnNumber) { d->positionChange(scriptId, lineNumber, columnNumber); + + if (d->coverageEnabled) { + JSAgentCoverageData rd = {"COVERAGE", QJSDebugService::instance()->m_timer.elapsed(), (int)CoveragePosChange, + scriptId, QString(), QString(), 0, lineNumber, columnNumber, QString()}; + QJSDebugService::instance()->processMessage(rd); + } } void QJSDebuggerAgentPrivate::positionChange(qint64 scriptId, int lineNumber, int columnNumber) diff --git a/src/declarative/debugger/qjsdebuggeragent_p.h b/src/declarative/debugger/qjsdebuggeragent_p.h index 4b27fc8..e999080 100644 --- a/src/declarative/debugger/qjsdebuggeragent_p.h +++ b/src/declarative/debugger/qjsdebuggeragent_p.h @@ -78,6 +78,17 @@ enum JSDebuggerState StoppedState }; +enum JSCoverageMessage { + CoverageLocation, + CoverageScriptLoad, + CoveragePosChange, + CoverageFuncEntry, + CoverageFuncExit, + CoverageComplete, + + CoverageMaximumMessage +}; + struct JSAgentWatchData { QByteArray exp; @@ -165,6 +176,7 @@ public: void stepInto(); void stepOut(); void continueExecution(); + void setCoverageEnabled(bool enabled); JSAgentWatchData executeExpression(const QString &expr); QList<JSAgentWatchData> expandObjectById(quint64 objectId); diff --git a/src/declarative/debugger/qjsdebugservice.cpp b/src/declarative/debugger/qjsdebugservice.cpp index ad84f65..03d1f76 100644 --- a/src/declarative/debugger/qjsdebugservice.cpp +++ b/src/declarative/debugger/qjsdebugservice.cpp @@ -49,10 +49,22 @@ Q_GLOBAL_STATIC(QJSDebugService, serviceInstance) +// convert to a QByteArray that can be sent to the debug client +QByteArray JSAgentCoverageData::toByteArray() const +{ + QByteArray data; + //### using QDataStream is relatively expensive + QDataStream ds(&data, QIODevice::WriteOnly); + ds << prefix << time << messageType << scriptId << program << fileName << baseLineNumber + << lineNumber << columnNumber << returnValue; + return data; +} + QJSDebugService::QJSDebugService(QObject *parent) : QDeclarativeDebugService(QLatin1String("JSDebugger"), parent) - , m_agent(0) + , m_agent(0), m_deferredSend(true) { + m_timer.start(); } QJSDebugService::~QJSDebugService() @@ -186,6 +198,13 @@ void QJSDebugService::messageReceived(const QByteArray &message) QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("PONG") << ping; sendMessage(reply); + } else if (command == "COVERAGE") { + bool enabled; + ds >> enabled; + m_agent->setCoverageEnabled(enabled); + if (!enabled) { + sendMessages(); + } } else { qDebug() << Q_FUNC_INFO << "Unknown command" << command; } @@ -206,3 +225,35 @@ void QJSDebugService::executionStopped(bool becauseOfException, << becauseOfException << exception; sendMessage(reply); } + +/* + Either send the message directly, or queue up + a list of messages to send later (via sendMessages) +*/ +void QJSDebugService::processMessage(const JSAgentCoverageData &message) +{ + if (m_deferredSend) + m_data.append(message); + else + sendMessage(message.toByteArray()); +} + +/* + Send the messages queued up by processMessage +*/ +void QJSDebugService::sendMessages() +{ + if (m_deferredSend) { + //### this is a suboptimal way to send batched messages + for (int i = 0; i < m_data.count(); ++i) + sendMessage(m_data.at(i).toByteArray()); + m_data.clear(); + + //indicate completion + QByteArray data; + QDataStream ds(&data, QIODevice::WriteOnly); + ds << QByteArray("COVERAGE") << (qint64)-1 << (int)CoverageComplete; + sendMessage(data); + } +} + diff --git a/src/declarative/debugger/qjsdebugservice_p.h b/src/declarative/debugger/qjsdebugservice_p.h index 7e7642e..4f99043 100644 --- a/src/declarative/debugger/qjsdebugservice_p.h +++ b/src/declarative/debugger/qjsdebugservice_p.h @@ -54,6 +54,7 @@ // #include <QtCore/QPointer> +#include <QElapsedTimer> #include "private/qdeclarativedebugservice_p.h" @@ -66,6 +67,23 @@ QT_MODULE(Declarative) class QDeclarativeEngine; class QJSDebuggerAgent; +struct JSAgentCoverageData +{ + QByteArray prefix; + qint64 time; + int messageType; + + qint64 scriptId; + QString program; + QString fileName; + int baseLineNumber; + int lineNumber; + int columnNumber; + QString returnValue; + + QByteArray toByteArray() const; +}; + class QJSDebugService : public QDeclarativeDebugService { Q_OBJECT @@ -78,6 +96,9 @@ public: void addEngine(QDeclarativeEngine *); void removeEngine(QDeclarativeEngine *); + void processMessage(const JSAgentCoverageData &message); + + QElapsedTimer m_timer; protected: void statusChanged(Status status); @@ -88,8 +109,11 @@ private Q_SLOTS: const QString &exception); private: + void sendMessages(); QList<QDeclarativeEngine *> m_engines; QPointer<QJSDebuggerAgent> m_agent; + bool m_deferredSend; + QList<JSAgentCoverageData> m_data; }; QT_END_NAMESPACE |