diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 7d598454b52..898d70c4852 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -122,6 +122,8 @@ static QString typeToString(BreakpointType type) return BreakHandler::tr("Watchpoint at Address"); case WatchpointAtExpression: return BreakHandler::tr("Watchpoint at Expression"); + case BreakpointOnSignalHandler: + return BreakHandler::tr("Breakpoint on Signal Handler"); case UnknownType: break; } diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 4d1f9c5be70..c313dd307c9 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -260,6 +260,7 @@ QString BreakpointParameters::toString() const << " PathUsage: " << pathUsage; break; case BreakpointByFunction: + case BreakpointOnSignalHandler: ts << " FunctionName: " << functionName; break; case BreakpointByAddress: diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index 7e1fbe5856f..2e025e32626 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -139,7 +139,8 @@ enum BreakpointType //BreakpointAtVFork, BreakpointAtSysCall, WatchpointAtAddress, - WatchpointAtExpression + WatchpointAtExpression, + BreakpointOnSignalHandler }; //! \enum Debugger::Internal::BreakpointState diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 221aaad8a03..cb2b10cb1db 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -119,8 +119,10 @@ BreakpointDialog::BreakpointDialog(unsigned engineCapabilities, QWidget *parent) << tr("Break when a new process is executed") << tr("Break when a system call is executed") << tr("Break on data access at fixed address") - << tr("Break on data access at address given by expression"); - QTC_ASSERT(types.size() == WatchpointAtExpression, return; ) + << tr("Break on data access at address given by expression") + << tr("Break on QML signal handler"); + + QTC_ASSERT(types.size() == BreakpointOnSignalHandler, return; ) m_ui.comboBoxType->addItems(types); m_ui.pathChooserFileName->setExpectedKind(Utils::PathChooser::File); connect(m_ui.comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int))); @@ -358,6 +360,8 @@ void BreakpointDialog::typeChanged(int) case WatchpointAtExpression: getParts(ExpressionPart|AllConditionParts|TracePointPart, &m_savedParameters); break; + case BreakpointOnSignalHandler: + getParts(FunctionPart, &m_savedParameters); } // Enable and set up new state from saved values. @@ -399,6 +403,10 @@ void BreakpointDialog::typeChanged(int) setPartsEnabled(ExpressionPart|AllConditionParts|TracePointPart|TracePointPart); clearOtherParts(ExpressionPart|AllConditionParts|TracePointPart); break; + case BreakpointOnSignalHandler: + setParts(FunctionPart, m_savedParameters); + setPartsEnabled(FunctionPart); + clearOtherParts(FunctionPart); } } diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 0177aa79969..bdc0ed018c8 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -2552,6 +2552,7 @@ bool CdbEngine::acceptsBreakpoint(BreakpointModelId id) const case BreakpointAtFork: case WatchpointAtExpression: case BreakpointAtSysCall: + case BreakpointOnSignalHandler: return false; case WatchpointAtAddress: case BreakpointByFileAndLine: diff --git a/src/plugins/debugger/cdb/cdbparsehelpers.cpp b/src/plugins/debugger/cdb/cdbparsehelpers.cpp index 2cdf22f8c78..7691774590c 100644 --- a/src/plugins/debugger/cdb/cdbparsehelpers.cpp +++ b/src/plugins/debugger/cdb/cdbparsehelpers.cpp @@ -107,6 +107,7 @@ static BreakpointParameters fixWinMSVCBreakpoint(const BreakpointParameters &p) case WatchpointAtExpression: case BreakpointAtSysCall: case WatchpointAtAddress: + case BreakpointOnSignalHandler: break; case BreakpointAtExec: { // Emulate by breaking on CreateProcessW(). BreakpointParameters rc(BreakpointByFunction); @@ -163,6 +164,7 @@ QByteArray cdbAddBreakpointCommand(const BreakpointParameters &bpIn, case BreakpointAtCatch: case BreakpointAtThrow: case BreakpointAtMain: + case BreakpointOnSignalHandler: QTC_ASSERT(false, return QByteArray(); ) break; case BreakpointByAddress: diff --git a/src/plugins/debugger/qml/qmldebuggerclient.cpp b/src/plugins/debugger/qml/qmldebuggerclient.cpp index 68b1cc1f0a8..c22c0bfe250 100644 --- a/src/plugins/debugger/qml/qmldebuggerclient.cpp +++ b/src/plugins/debugger/qml/qmldebuggerclient.cpp @@ -30,6 +30,7 @@ ** **************************************************************************/ #include "qmldebuggerclient.h" +#include "breakpoint.h" #include #include @@ -54,6 +55,11 @@ QmlDebuggerClient::~QmlDebuggerClient() delete d; } +bool QmlDebuggerClient::acceptsBreakpoint(const BreakpointModelId &/*id*/) +{ + return false; +} + void QmlDebuggerClient::statusChanged(Status status) { emit newStatus(status); diff --git a/src/plugins/debugger/qml/qmldebuggerclient.h b/src/plugins/debugger/qml/qmldebuggerclient.h index a9a8682c82d..26fd33c53aa 100644 --- a/src/plugins/debugger/qml/qmldebuggerclient.h +++ b/src/plugins/debugger/qml/qmldebuggerclient.h @@ -65,13 +65,14 @@ public: virtual void activateFrame(int index) = 0; - virtual void insertBreakpoint(BreakpointModelId id) = 0; - virtual void removeBreakpoint(BreakpointModelId id) = 0; - virtual void changeBreakpoint(BreakpointModelId id) = 0; + virtual bool acceptsBreakpoint(const BreakpointModelId &id); + virtual void insertBreakpoint(const BreakpointModelId &id) = 0; + virtual void removeBreakpoint(const BreakpointModelId &id) = 0; + virtual void changeBreakpoint(const BreakpointModelId &id) = 0; virtual void updateBreakpoints() = 0; virtual void assignValueInDebugger(const QByteArray expr, const quint64 &id, - const QString &property, const QString value) = 0; + const QString &property, const QString &value) = 0; virtual void updateWatchData(const WatchData *data) = 0; virtual void executeDebuggerCommand(const QString &command) = 0; diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index e3118f01fd6..a0d52354e28 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -603,7 +603,18 @@ void QmlEngine::attemptBreakpointSynchronization() bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const { - return !DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id)); + if (!DebuggerEngine::isCppBreakpoint(breakHandler()->breakpointData(id))) + return true; + + //If it is a Cpp Breakpoint query if the type can be also handled by the debugger client + //TODO: enable setting of breakpoints before start of debug session + //For now, the event breakpoint can be set after the activeDebuggerClient is known + //This is because the older client does not support BreakpointOnSignalHandler + bool acceptBreakpoint = false; + if (d->m_adapter.activeDebuggerClient()) { + acceptBreakpoint = d->m_adapter.activeDebuggerClient()->acceptsBreakpoint(id); + } + return acceptBreakpoint; } void QmlEngine::loadSymbols(const QString &moduleName) diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp index 5f7b11f45ef..24fd4e15231 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp @@ -312,7 +312,13 @@ void QmlV8DebuggerClient::activateFrame(int index) setLocals(index); } -void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id) +bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id) +{ + BreakpointType type = d->engine->breakHandler()->breakpointData(id).type; + return ((type == BreakpointOnSignalHandler) || (type == BreakpointByFunction)); +} + +void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id) { BreakHandler *handler = d->engine->breakHandler(); QByteArray request; @@ -327,6 +333,9 @@ void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id) } else if (handler->breakpointData(id).type == BreakpointByFunction) { JsonInputStream(request) << "type" << ':' << "function"; JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(id).toUtf8(); + } else if (handler->breakpointData(id).type == BreakpointOnSignalHandler) { + JsonInputStream(request) << "type" << ':' << "event"; + JsonInputStream(request) << ',' << "target" << ':' << handler->functionName(id).toUtf8(); } JsonInputStream(request) << '}'; JsonInputStream(request) << '}'; @@ -335,7 +344,7 @@ void QmlV8DebuggerClient::insertBreakpoint(BreakpointModelId id) sendMessage(packMessage(request)); } -void QmlV8DebuggerClient::removeBreakpoint(BreakpointModelId id) +void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id) { int breakpoint = d->breakpoints.value(id); d->breakpoints.remove(id); @@ -354,7 +363,7 @@ void QmlV8DebuggerClient::removeBreakpoint(BreakpointModelId id) sendMessage(packMessage(request)); } -void QmlV8DebuggerClient::changeBreakpoint(BreakpointModelId /*id*/) +void QmlV8DebuggerClient::changeBreakpoint(const BreakpointModelId &/*id*/) { } @@ -363,7 +372,7 @@ void QmlV8DebuggerClient::updateBreakpoints() } void QmlV8DebuggerClient::assignValueInDebugger(const QByteArray /*expr*/, const quint64 &/*id*/, - const QString &/*property*/, const QString /*value*/) + const QString &/*property*/, const QString &/*value*/) { //TODO:: } @@ -468,7 +477,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) ds >> response; JsonValue value(response); - QString type = value.findChild("type").toVariant().toString(); + const QString type = value.findChild("type").toVariant().toString(); if (type == "response") { @@ -478,7 +487,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) return; } - QString debugCommand(value.findChild("command").toVariant().toString()); + const QString debugCommand(value.findChild("command").toVariant().toString()); if (debugCommand == "backtrace") { setStackFrames(response); @@ -491,6 +500,12 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) BreakpointModelId id = d->breakpointsSync.take(sequence); d->breakpoints.insert(id,breakpoint); + //If this is an event breakpoint then set state = BreakpointInsertOk + const QString breakpointType = value.findChild("body").findChild("type").toVariant().toString(); + if (breakpointType == "event") { + d->engine->breakHandler()->notifyBreakpointInsertOk(id); + } + } else if (debugCommand == "evaluate") { setExpression(response); @@ -504,7 +519,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) } } else if (type == "event") { - QString event(value.findChild("event").toVariant().toString()); + const QString event(value.findChild("event").toVariant().toString()); if (event == "break") { d->engine->inferiorSpontaneousStop(); diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.h b/src/plugins/debugger/qml/qmlv8debuggerclient.h index 17165d879a1..8c0c5cc13a5 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.h +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.h @@ -80,13 +80,14 @@ public: void activateFrame(int index); - void insertBreakpoint(BreakpointModelId id); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id); + bool acceptsBreakpoint(const BreakpointModelId &id); + void insertBreakpoint(const BreakpointModelId &id); + void removeBreakpoint(const BreakpointModelId &id); + void changeBreakpoint(const BreakpointModelId &id); void updateBreakpoints(); void assignValueInDebugger(const QByteArray expr, const quint64 &id, - const QString &property, const QString value); + const QString &property, const QString &value); void updateWatchData(const WatchData *data); void executeDebuggerCommand(const QString &command); diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp index 03bc3bd9ce0..6c3a5f913b2 100644 --- a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp +++ b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp @@ -216,7 +216,7 @@ void QScriptDebuggerClient::activateFrame(int index) sendMessage(reply); } -void QScriptDebuggerClient::insertBreakpoint(BreakpointModelId id) +void QScriptDebuggerClient::insertBreakpoint(const BreakpointModelId &id) { BreakHandler *handler = d->engine->breakHandler(); JSAgentBreakpointData bp; @@ -226,7 +226,7 @@ void QScriptDebuggerClient::insertBreakpoint(BreakpointModelId id) d->breakpoints.insert(bp); } -void QScriptDebuggerClient::removeBreakpoint(BreakpointModelId id) +void QScriptDebuggerClient::removeBreakpoint(const BreakpointModelId &id) { BreakHandler *handler = d->engine->breakHandler(); JSAgentBreakpointData bp; @@ -236,7 +236,7 @@ void QScriptDebuggerClient::removeBreakpoint(BreakpointModelId id) d->breakpoints.remove(bp); } -void QScriptDebuggerClient::changeBreakpoint(BreakpointModelId /*id*/) +void QScriptDebuggerClient::changeBreakpoint(const BreakpointModelId &/*id*/) { } @@ -251,7 +251,7 @@ void QScriptDebuggerClient::updateBreakpoints() } void QScriptDebuggerClient::assignValueInDebugger(const QByteArray expr, const quint64 &id, - const QString &property, const QString value) + const QString &property, const QString &value) { QByteArray reply; QDataStream rs(&reply, QIODevice::WriteOnly); diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.h b/src/plugins/debugger/qml/qscriptdebuggerclient.h index daafb90ef0f..bd57ef60470 100644 --- a/src/plugins/debugger/qml/qscriptdebuggerclient.h +++ b/src/plugins/debugger/qml/qscriptdebuggerclient.h @@ -64,13 +64,13 @@ public: void activateFrame(int index); - void insertBreakpoint(BreakpointModelId id); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id); + void insertBreakpoint(const BreakpointModelId &id); + void removeBreakpoint(const BreakpointModelId &id); + void changeBreakpoint(const BreakpointModelId &id); void updateBreakpoints(); void assignValueInDebugger(const QByteArray expr, const quint64 &id, - const QString &property, const QString value); + const QString &property, const QString &value); void updateWatchData(const WatchData *data); void executeDebuggerCommand(const QString &command);