summaryrefslogtreecommitdiffstats
path: root/src/declarative/debugger
diff options
context:
space:
mode:
authorKai Koehne <kai.koehne@nokia.com>2011-06-21 14:38:44 (GMT)
committerKai Koehne <kai.koehne@nokia.com>2011-06-22 08:05:33 (GMT)
commitd349c879e1d55e4cd2b7d31c08e2796c0fec4020 (patch)
treef1e5ba4f3d71f3ef607e1b81ba53c506963eb41e /src/declarative/debugger
parent6cb43a9b72c67b71409a59fdeb419f390441f0c7 (diff)
downloadQt-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.cpp42
-rw-r--r--src/declarative/debugger/qjsdebuggeragent_p.h12
-rw-r--r--src/declarative/debugger/qjsdebugservice.cpp53
-rw-r--r--src/declarative/debugger/qjsdebugservice_p.h24
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