diff options
author | hjk <hjk@theqtcompany.com> | 2015-01-10 01:07:01 +0100 |
---|---|---|
committer | hjk <hjk@theqtcompany.com> | 2015-01-15 12:19:33 +0100 |
commit | 3b2d2eae17fdbab5ba65937909a7e92bc20c8224 (patch) | |
tree | 16141aae32ed4ff6abe57580f19a54ffaa1373f2 | |
parent | b88cdef0a3b170ae020f3f89ed91fd1a14daf6a2 (diff) | |
download | qt-creator-3b2d2eae17fdbab5ba65937909a7e92bc20c8224.tar.gz |
Debugger: Re-work breakpoint storage handling
The actual data is now in a TreeModel. As interface to
individual breakpoints there's a new Breakpoint class
essentially providing a checked handle.
On the user code side breakHandler()->foo(bpId) is
replaced by bp.foo().
Change-Id: I82f435bad6301fce85a1d82bf6bf39e9ddba511e
Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
28 files changed, 1311 insertions, 1382 deletions
diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index dab66afa3e..c1f63a4ec1 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -49,14 +49,88 @@ #include <QDir> #include <QDebug> -#define BREAK_ASSERT(cond, action) if (cond) {} else { action; } -//#define BREAK_ASSERT(cond, action) QTC_ASSERT(cond, action) - using namespace Utils; namespace Debugger { namespace Internal { +struct LocationItem : public TreeItem +{ + int columnCount() const { return 8; } + + QVariant data(int column, int role) const + { + if (role == Qt::DisplayRole) { + switch (column) { + case 0: + return params.id.toString(); + case 1: + return params.functionName; + case 4: + if (params.address) + return QString::fromLatin1("0x%1").arg(params.address, 0, 16); + } + } + return QVariant(); + } + + BreakpointResponse params; +}; + +class BreakpointMarker; + +class BreakpointItem : public QObject, public TreeItem +{ + Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::BreakHandler) + +public: + ~BreakpointItem(); + + int columnCount() const { return 8; } + QVariant data(int column, int role) const; + + QIcon icon() const; + + void removeBreakpoint(); + void updateLineNumberFromMarker(int lineNumber); + void updateFileNameFromMarker(const QString &fileName); + void changeLineNumberFromMarker(int lineNumber); + bool isLocatedAt(const QString &fileName, int lineNumber, bool useMarkerPosition) const; + + bool needsChildren() const; + void update(); + + void setMarkerFileAndLine(const QString &fileName, int lineNumber); + + void insertSubBreakpoint(const BreakpointResponse ¶ms); + QString markerFileName() const; + int markerLineNumber() const; + + bool needsChange() const; +private: + friend class BreakHandler; + friend class Breakpoint; + BreakpointItem(BreakHandler *handler); + + void destroyMarker(); + void updateMarker(); + void updateMarkerIcon(); + void scheduleSynchronization(); + + QString toToolTip() const; + void setState(BreakpointState state); + void deleteThis(); + bool isEngineRunning() const; + + BreakHandler * const m_handler; + const BreakpointModelId m_id; + BreakpointParameters m_params; + BreakpointState m_state; // Current state of breakpoint. + DebuggerEngine *m_engine; // Engine currently handling the breakpoint. + BreakpointResponse m_response; + BreakpointMarker *m_marker; +}; + // // BreakpointMarker // @@ -65,38 +139,38 @@ namespace Internal { class BreakpointMarker : public TextEditor::TextMark { public: - BreakpointMarker(BreakpointModelId id, const QString &fileName, int lineNumber) - : TextMark(fileName, lineNumber), m_id(id) + BreakpointMarker(BreakpointItem *b, const QString &fileName, int lineNumber) + : TextMark(fileName, lineNumber), m_bp(b) { - setIcon(breakHandler()->icon(m_id)); + setIcon(b->icon()); setPriority(TextEditor::TextMark::NormalPriority); - //qDebug() << "CREATE MARKER " << fileName << lineNumber; } void removedFromEditor() { - breakHandler()->removeBreakpoint(m_id); + if (m_bp) + m_bp->removeBreakpoint(); } void updateLineNumber(int lineNumber) { TextMark::updateLineNumber(lineNumber); - breakHandler()->updateLineNumberFromMarker(m_id, lineNumber); + m_bp->updateLineNumberFromMarker(lineNumber); } void updateFileName(const QString &fileName) { TextMark::updateFileName(fileName); - breakHandler()->updateFileNameFromMarker(m_id, fileName); + m_bp->updateFileNameFromMarker(fileName); } bool isDraggable() const { return true; } - void dragToLine(int line) { breakHandler()->changeLineNumberFromMarker(m_id, line); } + void dragToLine(int line) { m_bp->changeLineNumberFromMarker(line); } bool isClickable() const { return true; } - void clicked() { breakHandler()->removeBreakpoint(m_id); } + void clicked() { m_bp->removeBreakpoint(); } public: - BreakpointModelId m_id; + BreakpointItem *m_bp; }; static QString stateToString(BreakpointState state) @@ -173,6 +247,8 @@ static QString typeToString(BreakpointType type) BreakHandler::BreakHandler() : m_syncTimerId(-1) { + qRegisterMetaType<BreakpointModelId>(); + #if USE_BREAK_MODEL_TEST new ModelTest(this, 0); #endif @@ -259,94 +335,92 @@ static bool isSimilarTo(const BreakpointParameters ¶ms, const BreakpointResp return false; } -BreakpointModelId BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const +Breakpoint BreakHandler::findSimilarBreakpoint(const BreakpointResponse &needle) const { // Search a breakpoint we might refer to. foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); //qDebug() << "COMPARING " << params.toString() << " WITH " << needle.toString(); - if (b->response.id.isValid() && b->response.id.majorPart() == needle.id.majorPart()) - return b->id; + if (b->m_response.id.isValid() && b->m_response.id.majorPart() == needle.id.majorPart()) + return Breakpoint(b); - if (isSimilarTo(b->params, needle)) - return b->id; + if (isSimilarTo(b->m_params, needle)) + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } -BreakpointModelId BreakHandler::findBreakpointByResponseId(const BreakpointResponseId &id) const +Breakpoint BreakHandler::findBreakpointByResponseId(const BreakpointResponseId &id) const { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->response.id.majorPart() == id.majorPart()) - return b->id; + if (b->m_response.id.majorPart() == id.majorPart()) + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } -BreakpointModelId BreakHandler::findBreakpointByFunction(const QString &functionName) const +Breakpoint BreakHandler::findBreakpointByFunction(const QString &functionName) const { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->params.functionName == functionName) - return b->id; + if (b->m_params.functionName == functionName) + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } -BreakpointModelId BreakHandler::findBreakpointByAddress(quint64 address) const +Breakpoint BreakHandler::findBreakpointByAddress(quint64 address) const { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->params.address == address || b->params.address == address) - return b->id; + if (b->m_params.address == address || b->m_params.address == address) + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } -BreakpointModelId BreakHandler::findBreakpointByFileAndLine(const QString &fileName, +Breakpoint BreakHandler::findBreakpointByFileAndLine(const QString &fileName, int lineNumber, bool useMarkerPosition) { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); if (b->isLocatedAt(fileName, lineNumber, useMarkerPosition)) - return b->id; + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } -BreakHandler::BreakpointItem *BreakHandler::breakpointById(BreakpointModelId id) const +Breakpoint BreakHandler::breakpointById(BreakpointModelId id) const { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->id == id) - return b; + if (b->m_id == id) + return Breakpoint(b); } - return 0; + return Breakpoint(); } -const BreakpointParameters &BreakHandler::breakpointData(BreakpointModelId id) const +void BreakHandler::deletionHelper(BreakpointModelId id) { - static BreakpointParameters dummy; - if (BreakpointItem *b = breakpointById(id)) - return b->params; - - BREAK_ASSERT(false, /**/); - return dummy; + Breakpoint b = breakpointById(id); + QTC_ASSERT(b, return); + removeItem(b.b); + delete b.b; } -BreakpointModelId BreakHandler::findWatchpoint(const BreakpointParameters ¶ms) const +Breakpoint BreakHandler::findWatchpoint(const BreakpointParameters ¶ms) const { foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->params.isWatchpoint() - && b->params.address == params.address - && b->params.size == params.size - && b->params.expression == params.expression - && b->params.bitpos == params.bitpos) - return b->id; + if (b->m_params.isWatchpoint() + && b->m_params.address == params.address + && b->m_params.size == params.size + && b->m_params.expression == params.expression + && b->m_params.bitpos == params.bitpos) + return Breakpoint(b); } - return BreakpointModelId(); + return Breakpoint(); } void BreakHandler::saveBreakpoints() @@ -355,7 +429,7 @@ void BreakHandler::saveBreakpoints() QList<QVariant> list; foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - const BreakpointParameters ¶ms = b->params; + const BreakpointParameters ¶ms = b->m_params; QMap<QString, QVariant> map; if (params.type != BreakpointByFileAndLine) map.insert(_("type"), params.type); @@ -462,19 +536,19 @@ void BreakHandler::updateMarkers() static_cast<BreakpointItem *>(n)->updateMarker(); } -BreakpointModelId BreakHandler::findBreakpointByIndex(const QModelIndex &index) const +Breakpoint BreakHandler::findBreakpointByIndex(const QModelIndex &index) const { TreeItem *item = itemFromIndex(index); - if (item && item->parent() == rootItem()) - return static_cast<BreakpointItem *>(item)->id; - return BreakpointModelId(); + return Breakpoint(item && item->parent() == rootItem() ? static_cast<BreakpointItem *>(item) : 0); } -BreakpointModelIds BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const +Breakpoints BreakHandler::findBreakpointsByIndex(const QList<QModelIndex> &list) const { - QSet<BreakpointModelId> ids; - foreach (const QModelIndex &index, list) - ids.insert(findBreakpointByIndex(index)); + QSet<Breakpoint> ids; + foreach (const QModelIndex &index, list) { + if (Breakpoint b = findBreakpointByIndex(index)) + ids.insert(Breakpoint(b)); + } return ids.toList(); } @@ -492,10 +566,10 @@ int BreakHandler::threadSpecFromDisplay(const QString &str) const QString empty(QLatin1Char('-')); -QVariant BreakHandler::BreakpointItem::data(int column, int role) const +QVariant BreakpointItem::data(int column, int role) const { bool orig = false; - switch (state) { + switch (m_state) { case BreakpointInsertRequested: case BreakpointInsertProceeding: case BreakpointChangeRequested: @@ -513,32 +587,32 @@ QVariant BreakHandler::BreakpointItem::data(int column, int role) const switch (column) { case 0: if (role == Qt::DisplayRole) - return id.toString(); + return m_id.toString(); if (role == Qt::DecorationRole) return icon(); break; case 1: if (role == Qt::DisplayRole) { - if (!response.functionName.isEmpty()) - return simplifyType(response.functionName); - if (!params.functionName.isEmpty()) - return params.functionName; - if (params.type == BreakpointAtMain - || params.type == BreakpointAtThrow - || params.type == BreakpointAtCatch - || params.type == BreakpointAtFork - || params.type == BreakpointAtExec - //|| params.type == BreakpointAtVFork - || params.type == BreakpointAtSysCall) - return typeToString(params.type); - if (params.type == WatchpointAtAddress) { - quint64 address = response.address ? response.address : params.address; - return tr("Data at 0x%1").arg(address, 0, 16); + if (!m_response.functionName.isEmpty()) + return simplifyType(m_response.functionName); + if (!m_params.functionName.isEmpty()) + return m_params.functionName; + if (m_params.type == BreakpointAtMain + || m_params.type == BreakpointAtThrow + || m_params.type == BreakpointAtCatch + || m_params.type == BreakpointAtFork + || m_params.type == BreakpointAtExec + //|| m_params.type == BreakpointAtVFork + || m_params.type == BreakpointAtSysCall) + return typeToString(m_params.type); + if (m_params.type == WatchpointAtAddress) { + quint64 address = m_response.address ? m_response.address : m_params.address; + return BreakHandler::tr("Data at 0x%1").arg(address, 0, 16); } - if (params.type == WatchpointAtExpression) { - QString expression = !response.expression.isEmpty() - ? response.expression : params.expression; - return tr("Data at %1").arg(expression); + if (m_params.type == WatchpointAtExpression) { + QString expression = !m_response.expression.isEmpty() + ? m_response.expression : m_params.expression; + return BreakHandler::tr("Data at %1").arg(expression); } return empty; } @@ -546,10 +620,10 @@ QVariant BreakHandler::BreakpointItem::data(int column, int role) const case 2: if (role == Qt::DisplayRole) { QString str; - if (!response.fileName.isEmpty()) - str = response.fileName; - if (str.isEmpty() && !params.fileName.isEmpty()) - str = params.fileName; + if (!m_response.fileName.isEmpty()) + str = m_response.fileName; + if (str.isEmpty() && !m_params.fileName.isEmpty()) + str = m_params.fileName; if (str.isEmpty()) { QString s = QFileInfo(str).fileName(); if (!s.isEmpty()) @@ -565,18 +639,18 @@ QVariant BreakHandler::BreakpointItem::data(int column, int role) const break; case 3: if (role == Qt::DisplayRole) { - if (response.lineNumber > 0) - return response.lineNumber; - if (params.lineNumber > 0) - return params.lineNumber; + if (m_response.lineNumber > 0) + return m_response.lineNumber; + if (m_params.lineNumber > 0) + return m_params.lineNumber; return empty; } if (role == Qt::UserRole + 1) - return params.lineNumber; + return m_params.lineNumber; break; case 4: if (role == Qt::DisplayRole) { - const quint64 address = orig ? params.address : response.address; + const quint64 address = orig ? m_params.address : m_response.address; if (address) return QString::fromLatin1("0x%1").arg(address, 0, 16); return QVariant(); @@ -584,30 +658,30 @@ QVariant BreakHandler::BreakpointItem::data(int column, int role) const break; case 5: if (role == Qt::DisplayRole) - return orig ? params.condition : response.condition; + return orig ? m_params.condition : m_response.condition; if (role == Qt::ToolTipRole) - return tr("Breakpoint will only be hit if this condition is met."); + return BreakHandler::tr("Breakpoint will only be hit if this condition is met."); if (role == Qt::UserRole + 1) - return params.condition; + return m_params.condition; break; case 6: if (role == Qt::DisplayRole) { const int ignoreCount = - orig ? params.ignoreCount : response.ignoreCount; + orig ? m_params.ignoreCount : m_response.ignoreCount; return ignoreCount ? QVariant(ignoreCount) : QVariant(QString()); } if (role == Qt::ToolTipRole) - return tr("Breakpoint will only be hit after being ignored so many times."); + return BreakHandler::tr("Breakpoint will only be hit after being ignored so many times."); if (role == Qt::UserRole + 1) - return params.ignoreCount; + return m_params.ignoreCount; break; case 7: if (role == Qt::DisplayRole) - return displayFromThreadSpec(orig ? params.threadSpec : response.threadSpec); + return BreakHandler::displayFromThreadSpec(orig ? m_params.threadSpec : m_response.threadSpec); if (role == Qt::ToolTipRole) - return tr("Breakpoint will only be hit in the specified thread(s)."); + return BreakHandler::tr("Breakpoint will only be hit in the specified thread(s)."); if (role == Qt::UserRole + 1) - return displayFromThreadSpec(params.threadSpec); + return BreakHandler::displayFromThreadSpec(m_params.threadSpec); break; } @@ -617,172 +691,156 @@ QVariant BreakHandler::BreakpointItem::data(int column, int role) const return QVariant(); } -QVariant BreakHandler::LocationItem::data(int column, int role) const -{ - if (role == Qt::DisplayRole) { - switch (column) { - case 0: - return params.id.toString(); - case 1: - return params.functionName; - case 4: - if (params.address) - return QString::fromLatin1("0x%1").arg(params.address, 0, 16); - } - } - return QVariant(); -} - -#define GETTER(type, getter) \ -type BreakHandler::getter(BreakpointModelId id) const \ +#define PROPERTY(type, getter, setter) \ +\ +type Breakpoint::getter() const \ { \ - BreakpointItem *b = breakpointById(id); \ - BREAK_ASSERT(b, qDebug() << "ID" << id << "NOT KNOWN"; return type()); \ - return b->params.getter; \ -} - -#define SETTER(type, getter, setter) \ -void BreakHandler::setter(BreakpointModelId id, const type &value) \ + return parameters().getter; \ +} \ +\ +void Breakpoint::setter(const type &value) \ { \ - BreakpointItem *b = breakpointById(id); \ - BREAK_ASSERT(b, qDebug() << "ID" << id << "NOT KNOWN"; return); \ - if (b->params.getter == value) \ + QTC_ASSERT(b, return); \ + if (b->m_params.getter == value) \ return; \ - b->params.getter = value; \ - if (b->state != BreakpointNew) { \ - b->state = BreakpointChangeRequested; \ - scheduleSynchronization(); \ + b->m_params.getter = value; \ + if (b->m_state != BreakpointNew) { \ + b->m_state = BreakpointChangeRequested; \ + b->scheduleSynchronization(); \ } \ } -#define PROPERTY(type, getter, setter) \ - GETTER(type, getter) \ - SETTER(type, getter, setter) - - PROPERTY(BreakpointPathUsage, pathUsage, setPathUsage) PROPERTY(QString, fileName, setFileName) PROPERTY(QString, functionName, setFunctionName) PROPERTY(BreakpointType, type, setType) PROPERTY(int, threadSpec, setThreadSpec) PROPERTY(QByteArray, condition, setCondition) -GETTER(int, lineNumber) PROPERTY(quint64, address, setAddress) PROPERTY(QString, expression, setExpression) PROPERTY(QString, message, setMessage) PROPERTY(int, ignoreCount, setIgnoreCount) -bool BreakHandler::isEnabled(BreakpointModelId id) const +void BreakpointItem::scheduleSynchronization() { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->params.enabled; + m_handler->scheduleSynchronization(); } -void BreakHandler::setEnabled(BreakpointModelId id, bool on) +const BreakpointParameters &Breakpoint::parameters() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - //qDebug() << "SET ENABLED: " << id << b->params.isEnabled() << on; - if (b->params.enabled == on) - return; - b->params.enabled = on; - b->updateMarkerIcon(); - if (b->engine) { - b->state = BreakpointChangeRequested; - scheduleSynchronization(); - } + static BreakpointParameters p; + QTC_ASSERT(b, return p); + return b->m_params; +} + +BreakpointState Breakpoint::state() const +{ + QTC_ASSERT(b, return BreakpointState()); + return b->m_state; } -bool BreakHandler::isWatchpoint(BreakpointModelId id) const +int Breakpoint::lineNumber() const { return parameters().lineNumber; } + +bool Breakpoint::isEnabled() const { return parameters().enabled; } + +bool Breakpoint::isWatchpoint() const { return parameters().isWatchpoint(); } + +bool Breakpoint::isTracepoint() const { return parameters().isTracepoint(); } + +QIcon Breakpoint::icon() const { return b ? b->icon() : QIcon(); } + +DebuggerEngine *Breakpoint::engine() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->params.isWatchpoint(); + return b ? b->m_engine : 0; } -bool BreakHandler::isTracepoint(BreakpointModelId id) const +const BreakpointResponse &Breakpoint::response() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->params.tracepoint; + static BreakpointResponse r; + return b ? b->m_response : r; } -bool BreakHandler::isOneShot(BreakpointModelId id) const +bool Breakpoint::isOneShot() const { return parameters().oneShot; } + +void Breakpoint::removeAlienBreakpoint() { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->params.oneShot; + b->deleteThis(); } -bool BreakHandler::needsChildren(BreakpointModelId id) const +void Breakpoint::removeBreakpoint() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->response.multiple && b->rowCount() == 0; + b->deleteThis(); } -void BreakHandler::setTracepoint(BreakpointModelId id, bool on) +Breakpoint::Breakpoint(BreakpointItem *b) + : b(b) +{} + +void Breakpoint::setEnabled(bool on) const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - if (b->params.tracepoint == on) + QTC_ASSERT(b, return); + if (b->m_params.enabled == on) return; - b->params.tracepoint = on; + b->m_params.enabled = on; b->updateMarkerIcon(); - - if (b->engine) { - b->state = BreakpointChangeRequested; - scheduleSynchronization(); + if (b->m_engine) { + b->m_state = BreakpointChangeRequested; + b->scheduleSynchronization(); } } -void BreakHandler::setMarkerFileAndLine(BreakpointModelId id, - const QString &fileName, int lineNumber) +void Breakpoint::setMarkerFileAndLine(const QString &fileName, int lineNumber) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, qDebug() << "MARKER_FILE_AND_LINE: " << id; return); - if (b->response.fileName == fileName && b->response.lineNumber == lineNumber) - return; - b->response.fileName = fileName; - b->response.lineNumber = lineNumber; - b->destroyMarker(); - b->updateMarker(); - updateItem(b); + if (b) + b->setMarkerFileAndLine(fileName, lineNumber); } -BreakpointState BreakHandler::state(BreakpointModelId id) const +bool BreakpointItem::needsChildren() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, qDebug() << "STATE: " << id; return BreakpointDead); - return b->state; + return m_response.multiple && rowCount() == 0; } -DebuggerEngine *BreakHandler::engine(BreakpointModelId id) const +void Breakpoint::setTracepoint(bool on) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, qDebug() << id; return 0); - return b->engine; + if (b->m_params.tracepoint == on) + return; + b->m_params.tracepoint = on; + b->updateMarkerIcon(); + + if (b->m_engine) { + b->m_state = BreakpointChangeRequested; + b->scheduleSynchronization(); + } } -void BreakHandler::setEngine(BreakpointModelId id, DebuggerEngine *value) +void BreakpointItem::setMarkerFileAndLine(const QString &fileName, int lineNumber) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, qDebug() << "SET ENGINE" << id; return); - QTC_ASSERT(b->state == BreakpointNew, qDebug() << "STATE: " << b->state <<id); - QTC_ASSERT(!b->engine, qDebug() << "NO ENGINE" << id; return); - b->engine = value; - b->state = BreakpointInsertRequested; - b->response = BreakpointResponse(); + if (m_response.fileName == fileName && m_response.lineNumber == lineNumber) + return; + m_response.fileName = fileName; + m_response.lineNumber = lineNumber; + destroyMarker(); + updateMarker(); + update(); +} + +void Breakpoint::setEngine(DebuggerEngine *value) +{ + QTC_ASSERT(b->m_state == BreakpointNew, qDebug() << "STATE: " << b->m_state << b->m_id); + QTC_ASSERT(!b->m_engine, qDebug() << "NO ENGINE" << b->m_id; return); + b->m_engine = value; + b->m_state = BreakpointInsertRequested; + b->m_response = BreakpointResponse(); b->updateMarker(); - //scheduleSynchronization(); + //b->scheduleSynchronization(); } static bool isAllowedTransition(BreakpointState from, BreakpointState to) { switch (from) { case BreakpointNew: - return to == BreakpointInsertRequested; + return to == BreakpointInsertRequested + || to == BreakpointDead; case BreakpointInsertRequested: return to == BreakpointInsertProceeding; case BreakpointInsertProceeding: @@ -809,179 +867,175 @@ static bool isAllowedTransition(BreakpointState from, BreakpointState to) return false; } -bool BreakHandler::isEngineRunning(BreakpointModelId id) const +bool BreakpointItem::isEngineRunning() const { - if (const DebuggerEngine *e = engine(id)) { - const DebuggerState state = e->state(); - return state != DebuggerFinished && state != DebuggerNotReady; - } - return false; + if (!m_engine) + return false; + const DebuggerState state = m_engine->state(); + return state != DebuggerFinished && state != DebuggerNotReady; } -void BreakHandler::setState(BreakpointModelId id, BreakpointState state) +void BreakpointItem::setState(BreakpointState state) { - BreakpointItem *b = breakpointById(id); - //qDebug() << "BREAKPOINT STATE TRANSITION, ID: " << id - // << " FROM: " << b->state << " TO: " << state; - BREAK_ASSERT(b, qDebug() << id; return); - QTC_ASSERT(isAllowedTransition(b->state, state), - qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION" - << b->state << state); + //qDebug() << "BREAKPOINT STATE TRANSITION, ID: " << m_id + // << " FROM: " << state << " TO: " << state; + if (!isAllowedTransition(m_state, state)) { + qDebug() << "UNEXPECTED BREAKPOINT STATE TRANSITION" << m_state << state; + QTC_CHECK(false); + } - if (b->state == state) { - qDebug() << "STATE UNCHANGED: " << id << state; + if (m_state == state) { + qDebug() << "STATE UNCHANGED: " << m_id << m_state; return; } - b->state = state; + m_state = state; // FIXME: updateMarker() should recognize the need for icon changes. if (state == BreakpointInserted) { - b->destroyMarker(); - b->updateMarker(); + destroyMarker(); + updateMarker(); } - updateItem(b); + update(); +} + +void BreakpointItem::deleteThis() +{ + setState(BreakpointDead); + destroyMarker(); + + // This is called from b directly. So delay deletion of b. + ExtensionSystem::InvokerBase invoker; + invoker.addArgument(m_id); + invoker.setConnectionType(Qt::QueuedConnection); + invoker.invoke(m_handler, "deletionHelper"); + QTC_CHECK(invoker.wasSuccessful()); +} + +void BreakpointItem::update() +{ + m_handler->updateItem(this); +} + +void Breakpoint::gotoState(BreakpointState target, BreakpointState assumedCurrent) +{ + QTC_ASSERT(b, return); + QTC_ASSERT(b->m_state == assumedCurrent, qDebug() << b->m_state); + b->setState(target); } -void BreakHandler::notifyBreakpointChangeAfterInsertNeeded(BreakpointModelId id) +void Breakpoint::notifyBreakpointChangeAfterInsertNeeded() { - QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id)); - setState(id, BreakpointChangeRequested); + gotoState(BreakpointChangeRequested, BreakpointInsertProceeding); } -void BreakHandler::notifyBreakpointInsertProceeding(BreakpointModelId id) +void Breakpoint::notifyBreakpointInsertProceeding() { - QTC_ASSERT(state(id) == BreakpointInsertRequested, qDebug() << state(id)); - setState(id, BreakpointInsertProceeding); + gotoState(BreakpointInsertProceeding, BreakpointInsertRequested); } -void BreakHandler::notifyBreakpointInsertOk(BreakpointModelId id) +void Breakpoint::notifyBreakpointInsertOk() { - BreakpointItem *b = breakpointById(id); - QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id)); - setState(id, BreakpointInserted); - BREAK_ASSERT(b, return); + gotoState(BreakpointInserted, BreakpointInsertProceeding); } -void BreakHandler::notifyBreakpointInsertFailed(BreakpointModelId id) +void Breakpoint::notifyBreakpointInsertFailed() { - QTC_ASSERT(state(id) == BreakpointInsertProceeding, qDebug() << state(id)); - setState(id, BreakpointDead); + gotoState(BreakpointDead, BreakpointInsertProceeding); } -void BreakHandler::notifyBreakpointRemoveProceeding(BreakpointModelId id) +void Breakpoint::notifyBreakpointRemoveProceeding() { - QTC_ASSERT(state(id) == BreakpointRemoveRequested, qDebug() << state(id)); - setState(id, BreakpointRemoveProceeding); + gotoState(BreakpointRemoveProceeding, BreakpointRemoveRequested); } -void BreakHandler::notifyBreakpointRemoveOk(BreakpointModelId id) +void Breakpoint::notifyBreakpointRemoveOk() { - QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id)); - setState(id, BreakpointDead); - cleanupBreakpoint(id); + QTC_ASSERT(b, return); + QTC_ASSERT(b->m_state == BreakpointRemoveProceeding, qDebug() << b->m_state); + b->deleteThis(); } -void BreakHandler::notifyBreakpointRemoveFailed(BreakpointModelId id) +void Breakpoint::notifyBreakpointRemoveFailed() { - QTC_ASSERT(state(id) == BreakpointRemoveProceeding, qDebug() << state(id)); - setState(id, BreakpointDead); - cleanupBreakpoint(id); + QTC_ASSERT(b, return); + QTC_ASSERT(b->m_state == BreakpointRemoveProceeding, qDebug() << b->m_state); + b->deleteThis(); } -void BreakHandler::notifyBreakpointChangeProceeding(BreakpointModelId id) +void Breakpoint::notifyBreakpointChangeProceeding() { - QTC_ASSERT(state(id) == BreakpointChangeRequested, qDebug() << state(id)); - setState(id, BreakpointChangeProceeding); + gotoState(BreakpointChangeProceeding, BreakpointChangeRequested); } -void BreakHandler::notifyBreakpointChangeOk(BreakpointModelId id) +void Breakpoint::notifyBreakpointChangeOk() { - QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id)); - setState(id, BreakpointInserted); + gotoState(BreakpointInserted, BreakpointChangeProceeding); } -void BreakHandler::notifyBreakpointChangeFailed(BreakpointModelId id) +void Breakpoint::notifyBreakpointChangeFailed() { - QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id)); - setState(id, BreakpointDead); + gotoState(BreakpointDead, BreakpointChangeProceeding); } -void BreakHandler::notifyBreakpointReleased(BreakpointModelId id) +void Breakpoint::notifyBreakpointReleased() { - BreakpointItem *b = breakpointById(id); - removeAllSubItems(b); - //QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id)); - BREAK_ASSERT(b, return); - b->state = BreakpointNew; - b->engine = 0; - b->response = BreakpointResponse(); + QTC_ASSERT(b, return); + b->m_handler->removeAllSubItems(b); + //QTC_ASSERT(b->m_state == BreakpointChangeProceeding, qDebug() << b->m_state); + b->m_state = BreakpointNew; + b->m_engine = 0; + b->m_response = BreakpointResponse(); b->destroyMarker(); b->updateMarker(); - if (b->params.type == WatchpointAtAddress - || b->params.type == WatchpointAtExpression - || b->params.type == BreakpointByAddress) - b->params.enabled = false; + if (b->m_params.type == WatchpointAtAddress + || b->m_params.type == WatchpointAtExpression + || b->m_params.type == BreakpointByAddress) + b->m_params.enabled = false; else - b->params.address = 0; - updateItem(b); + b->m_params.address = 0; + b->update(); } -void BreakHandler::notifyBreakpointAdjusted(BreakpointModelId id, - const BreakpointParameters ¶ms) +void Breakpoint::notifyBreakpointAdjusted(const BreakpointParameters ¶ms) { - BreakpointItem *b = breakpointById(id); - QTC_ASSERT(state(id) == BreakpointInserted, qDebug() << state(id)); - BREAK_ASSERT(b, return); - b->params = params; + QTC_ASSERT(b, return); + QTC_ASSERT(b->m_state == BreakpointInserted, qDebug() << b->m_state); + b->m_params = params; //if (b->needsChange()) - // setState(id, BreakpointChangeRequested); + // b->setState(BreakpointChangeRequested); } -void BreakHandler::notifyBreakpointNeedsReinsertion(BreakpointModelId id) +void Breakpoint::notifyBreakpointNeedsReinsertion() { - BreakpointItem *b = breakpointById(id); - QTC_ASSERT(state(id) == BreakpointChangeProceeding, qDebug() << state(id)); - BREAK_ASSERT(b, return); - b->state = BreakpointInsertRequested; + QTC_ASSERT(b, return); + QTC_ASSERT(b->m_state == BreakpointChangeProceeding, qDebug() << b->m_state); + b->m_state = BreakpointInsertRequested; } -void BreakHandler::removeAlienBreakpoint(BreakpointModelId id) -{ - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - b->state = BreakpointDead; - cleanupBreakpoint(id); -} -void BreakHandler::removeBreakpoint(BreakpointModelId id) + +void BreakpointItem::removeBreakpoint() { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - switch (b->state) { + switch (m_state) { case BreakpointRemoveRequested: break; case BreakpointInserted: case BreakpointInsertProceeding: - setState(id, BreakpointRemoveRequested); + setState(BreakpointRemoveRequested); scheduleSynchronization(); break; case BreakpointNew: - b->state = BreakpointDead; - cleanupBreakpoint(id); + deleteThis(); break; default: qWarning("Warning: Cannot remove breakpoint %s in state '%s'.", - qPrintable(id.toString()), qPrintable(stateToString(b->state))); - b->state = BreakpointRemoveRequested; + qPrintable(m_id.toString()), qPrintable(stateToString(m_state))); + m_state = BreakpointRemoveRequested; break; } } -// Ok to be not thread-safe. The order does not matter and only the gui -// produces authoritative ids. -static int currentId = 0; - void BreakHandler::appendBreakpoint(const BreakpointParameters ¶ms) { appendBreakpointInternal(params); @@ -995,49 +1049,50 @@ void BreakHandler::appendBreakpointInternal(const BreakpointParameters ¶ms) return; } - BreakpointItem *b = new BreakpointItem; - b->id = BreakpointModelId(++currentId); - b->params = params; + BreakpointItem *b = new BreakpointItem(this); + b->m_params = params; b->updateMarker(); appendItem(rootItem(), b); } void BreakHandler::handleAlienBreakpoint(const BreakpointResponse &response, DebuggerEngine *engine) { - BreakpointModelId id = findSimilarBreakpoint(response); - if (id.isValid()) { + Breakpoint b = findSimilarBreakpoint(response); + if (b) { if (response.id.isMinor()) - insertSubBreakpoint(id, response); + b.insertSubBreakpoint(response); else - setResponse(id, response); + b.setResponse(response); } else { - BreakpointItem *b = new BreakpointItem; - b->id = BreakpointModelId(++currentId); - b->params = response; - b->response = response; - b->state = BreakpointInserted; - b->engine = engine; + auto b = new BreakpointItem(this); + b->m_params = response; + b->m_response = response; + b->m_state = BreakpointInserted; + b->m_engine = engine; b->updateMarker(); appendItem(rootItem(), b); } } -void BreakHandler::insertSubBreakpoint(BreakpointModelId id, - const BreakpointResponse ¶ms) +void Breakpoint::insertSubBreakpoint(const BreakpointResponse ¶ms) +{ + QTC_ASSERT(b, return); + b->insertSubBreakpoint(params); +} + +void BreakpointItem::insertSubBreakpoint(const BreakpointResponse ¶ms) { QTC_ASSERT(params.id.isMinor(), return); - QTC_ASSERT(id.isMajor(), return); - BreakpointItem *b = breakpointById(id); - QTC_ASSERT(b, qDebug() << "FAILED: " << id.toString(); return); int minorPart = params.id.minorPart(); - foreach (TreeItem *n, b->children()) { + const QVector<TreeItem *> &children = TreeItem::children(); + foreach (TreeItem *n, children) { LocationItem *l = static_cast<LocationItem *>(n); if (l->params.id.minorPart() == minorPart) { // This modifies an existing sub-breakpoint. l->params = params; - updateItem(l); + m_handler->updateItem(l); return; } } @@ -1045,9 +1100,9 @@ void BreakHandler::insertSubBreakpoint(BreakpointModelId id, // This is a new sub-breakpoint. LocationItem *l = new LocationItem; l->params = params; - appendItem(b, l); - requestExpansion(indexFromItem(b)); + m_handler->appendItem(this, l); + m_handler->requestExpansion(m_handler->indexFromItem(this)); } void BreakHandler::saveSessionData() @@ -1067,7 +1122,7 @@ void BreakHandler::breakByFunction(const QString &functionName) // combinations of multiple conditions and ignore counts, though. foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - const BreakpointParameters ¶ms = b->params; + const BreakpointParameters ¶ms = b->m_params; if (params.functionName == functionName && params.condition.isEmpty() && params.ignoreCount == 0) @@ -1078,12 +1133,6 @@ void BreakHandler::breakByFunction(const QString &functionName) appendBreakpoint(params); } -QIcon BreakHandler::icon(BreakpointModelId id) const -{ - BreakpointItem *b = breakpointById(id); - return b ? b->icon() : pendingBreakpointIcon(); -} - void BreakHandler::scheduleSynchronization() { if (m_syncTimerId == -1) @@ -1099,85 +1148,81 @@ void BreakHandler::timerEvent(QTimerEvent *event) Internal::synchronizeBreakpoints(); } -void BreakHandler::gotoLocation(BreakpointModelId id) const +void Breakpoint::gotoLocation() const { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - DebuggerEngine *engine = currentEngine(); - if (engine) { - if (b->params.type == BreakpointByAddress) - engine->gotoLocation(b->params.address); + if (DebuggerEngine *engine = currentEngine()) { + if (b->m_params.type == BreakpointByAddress) + engine->gotoLocation(b->m_params.address); else engine->gotoLocation(Location(b->markerFileName(), b->markerLineNumber(), false)); } } -void BreakHandler::updateFileNameFromMarker(BreakpointModelId id, const QString &fileName) +void BreakpointItem::updateFileNameFromMarker(const QString &fileName) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - b->params.fileName = fileName; - updateItem(b); + m_params.fileName = fileName; + update(); } -void BreakHandler::updateLineNumberFromMarker(BreakpointModelId id, int lineNumber) +void BreakpointItem::updateLineNumberFromMarker(int lineNumber) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); // Ignore updates to the "real" line number while the debugger is // running, as this can be triggered by moving the breakpoint to // the next line that generated code. - if (b->params.lineNumber == lineNumber) + if (m_params.lineNumber == lineNumber) ; // Nothing - else if (isEngineRunning(id)) - b->params.lineNumber += lineNumber - b->response.lineNumber; + else if (isEngineRunning()) + m_params.lineNumber += lineNumber - m_response.lineNumber; else - b->params.lineNumber = lineNumber; - b->updateMarker(); - updateItem(b); + m_params.lineNumber = lineNumber; + updateMarker(); + update(); } -void BreakHandler::changeLineNumberFromMarker(BreakpointModelId id, int lineNumber) +void BreakpointItem::changeLineNumberFromMarker(int lineNumber) { + m_params.lineNumber = lineNumber; + // We need to delay this as it is called from a marker which will be destroyed. ExtensionSystem::InvokerBase invoker; - invoker.addArgument(id); - invoker.addArgument(lineNumber); + invoker.addArgument(m_id); invoker.setConnectionType(Qt::QueuedConnection); - invoker.invoke(this, "changeLineNumberFromMarkerHelper"); + invoker.invoke(m_handler, "changeLineNumberFromMarkerHelper"); QTC_CHECK(invoker.wasSuccessful()); } -void BreakHandler::changeLineNumberFromMarkerHelper(BreakpointModelId id, int lineNumber) +void BreakHandler::changeLineNumberFromMarkerHelper(BreakpointModelId id) { - BreakpointParameters params = breakpointData(id); - params.lineNumber = lineNumber; - removeBreakpoint(id); + Breakpoint b = breakpointById(id); + QTC_ASSERT(b, return); + BreakpointParameters params = b.parameters(); + removeItem(b.b); + delete b.b; appendBreakpoint(params); } -BreakpointModelIds BreakHandler::allBreakpointIds() const +Breakpoints BreakHandler::allBreakpoints() const { - BreakpointModelIds ids; + Breakpoints items; foreach (TreeItem *n, rootItem()->children()) - ids.append(static_cast<BreakpointItem *>(n)->id); - return ids; + items.append(Breakpoint(static_cast<BreakpointItem *>(n))); + return items; } -BreakpointModelIds BreakHandler::unclaimedBreakpointIds() const +Breakpoints BreakHandler::unclaimedBreakpoints() const { - return engineBreakpointIds(0); + return engineBreakpoints(0); } -BreakpointModelIds BreakHandler::engineBreakpointIds(DebuggerEngine *engine) const +Breakpoints BreakHandler::engineBreakpoints(DebuggerEngine *engine) const { - BreakpointModelIds ids; + Breakpoints items; foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->engine == engine) - ids.append(b->id); + if (b->m_engine == engine) + items.append(Breakpoint(b)); } - return ids; + return items; } QStringList BreakHandler::engineBreakpointPaths(DebuggerEngine *engine) const @@ -1185,69 +1230,45 @@ QStringList BreakHandler::engineBreakpointPaths(DebuggerEngine *engine) const QSet<QString> set; foreach (TreeItem *n, rootItem()->children()) { BreakpointItem *b = static_cast<BreakpointItem *>(n); - if (b->engine == engine) { - if (b->params.type == BreakpointByFileAndLine) - set.insert(QFileInfo(b->params.fileName).dir().path()); + if (b->m_engine == engine) { + if (b->m_params.type == BreakpointByFileAndLine) + set.insert(QFileInfo(b->m_params.fileName).dir().path()); } } return set.toList(); } -void BreakHandler::cleanupBreakpoint(BreakpointModelId id) -{ - QTC_ASSERT(state(id) == BreakpointDead, qDebug() << state(id)); - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - b->destroyMarker(); - removeItem(b); - delete b; -} - -const BreakpointResponse &BreakHandler::response(BreakpointModelId id) const -{ - static BreakpointResponse dummy; - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, qDebug() << "NO RESPONSE FOR " << id; return dummy); - return b->response; -} - -bool BreakHandler::needsChange(BreakpointModelId id) const -{ - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return false); - return b->needsChange(); -} - -void BreakHandler::setResponse(BreakpointModelId id, - const BreakpointResponse &response) +void Breakpoint::setResponse(const BreakpointResponse &response) { - BreakpointItem *b = breakpointById(id); - BREAK_ASSERT(b, return); - b->response = response; + QTC_ASSERT(b, return); + b->m_response = response; b->destroyMarker(); b->updateMarker(); // Take over corrected values from response. - if ((b->params.type == BreakpointByFileAndLine - || b->params.type == BreakpointByFunction) + if ((b->m_params.type == BreakpointByFileAndLine + || b->m_params.type == BreakpointByFunction) && !response.module.isEmpty()) - b->params.module = response.module; + b->m_params.module = response.module; } -void BreakHandler::changeBreakpointData(BreakpointModelId id, - const BreakpointParameters ¶ms, BreakpointParts parts) +bool Internal::Breakpoint::needsChange() const { - BreakpointItem *b = breakpointById(id); - Q_UNUSED(parts); - BREAK_ASSERT(b, return); - if (params == b->params) + return b && b->needsChange(); +} + +void Breakpoint::changeBreakpointData(const BreakpointParameters ¶ms) +{ + if (!b) return; - b->params = params; + if (params == b->m_params) + return; + b->m_params = params; b->destroyMarker(); b->updateMarker(); - updateItem(b); - if (b->needsChange() && b->engine && b->state != BreakpointNew) { - setState(id, BreakpointChangeRequested); - scheduleSynchronization(); + b->update(); + if (b->needsChange() && b->m_engine && b->m_state != BreakpointNew) { + b->setState(BreakpointChangeRequested); + b->m_handler->scheduleSynchronization(); } } @@ -1257,46 +1278,52 @@ void BreakHandler::changeBreakpointData(BreakpointModelId id, // ////////////////////////////////////////////////////////////////// -BreakHandler::BreakpointItem::BreakpointItem() - : state(BreakpointNew), engine(0), marker(0) +// Ok to be not thread-safe. The order does not matter and only the gui +// produces authoritative ids. +static int currentId = 0; + +BreakpointItem::BreakpointItem(BreakHandler *handler) + : m_handler(handler), m_id(++currentId), m_state(BreakpointNew), m_engine(0), m_marker(0) {} -BreakHandler::BreakpointItem::~BreakpointItem() +BreakpointItem::~BreakpointItem() { - delete marker; + delete m_marker; } -void BreakHandler::BreakpointItem::destroyMarker() +void BreakpointItem::destroyMarker() { - BreakpointMarker *m = marker; - marker = 0; + BreakpointMarker *m = m_marker; + QTC_ASSERT(m, return); + m->m_bp = 0; + m_marker = 0; delete m; } -QString BreakHandler::BreakpointItem::markerFileName() const +QString BreakpointItem::markerFileName() const { // Some heuristics to find a "good" file name. - if (!params.fileName.isEmpty()) { - QFileInfo fi(params.fileName); + if (!m_params.fileName.isEmpty()) { + QFileInfo fi(m_params.fileName); if (fi.exists()) return fi.absoluteFilePath(); } - if (!response.fileName.isEmpty()) { - QFileInfo fi(response.fileName); + if (!m_response.fileName.isEmpty()) { + QFileInfo fi(m_response.fileName); if (fi.exists()) return fi.absoluteFilePath(); } - if (response.fileName.endsWith(params.fileName)) - return response.fileName; - if (params.fileName.endsWith(response.fileName)) - return params.fileName; - return response.fileName.size() > params.fileName.size() - ? response.fileName : params.fileName; + if (m_response.fileName.endsWith(m_params.fileName)) + return m_response.fileName; + if (m_params.fileName.endsWith(m_response.fileName)) + return m_params.fileName; + return m_response.fileName.size() > m_params.fileName.size() + ? m_response.fileName : m_params.fileName; } -int BreakHandler::BreakpointItem::markerLineNumber() const +int BreakpointItem::markerLineNumber() const { - return response.lineNumber ? response.lineNumber : params.lineNumber; + return m_response.lineNumber ? m_response.lineNumber : m_params.lineNumber; } static void formatAddress(QTextStream &str, quint64 address) @@ -1309,94 +1336,94 @@ static void formatAddress(QTextStream &str, quint64 address) } } -bool BreakHandler::BreakpointItem::needsChange() const +bool BreakpointItem::needsChange() const { - if (!params.conditionsMatch(response.condition)) + if (!m_params.conditionsMatch(m_response.condition)) return true; - if (params.ignoreCount != response.ignoreCount) + if (m_params.ignoreCount != m_response.ignoreCount) return true; - if (params.enabled != response.enabled) + if (m_params.enabled != m_response.enabled) return true; - if (params.threadSpec != response.threadSpec) + if (m_params.threadSpec != m_response.threadSpec) return true; - if (params.command != response.command) + if (m_params.command != m_response.command) return true; - if (params.type == BreakpointByFileAndLine && params.lineNumber != response.lineNumber) + if (m_params.type == BreakpointByFileAndLine && m_params.lineNumber != m_response.lineNumber) return true; // FIXME: Too strict, functions may have parameter lists, or not. - // if (params.type == BreakpointByFunction && params.functionName != response.functionName) + // if (m_params.type == BreakpointByFunction && m_params.functionName != m_response.functionName) // return true; - // if (params.type == BreakpointByAddress && params.address != response.address) + // if (m_params.type == BreakpointByAddress && m_params.address != m_response.address) // return true; return false; } -bool BreakHandler::BreakpointItem::isLocatedAt +bool BreakpointItem::isLocatedAt (const QString &fileName, int lineNumber, bool useMarkerPosition) const { - int line = useMarkerPosition ? response.lineNumber : params.lineNumber; + int line = useMarkerPosition ? m_response.lineNumber : m_params.lineNumber; return lineNumber == line - && (fileNameMatch(fileName, response.fileName) + && (fileNameMatch(fileName, m_response.fileName) || fileNameMatch(fileName, markerFileName())); } -void BreakHandler::BreakpointItem::updateMarkerIcon() +void BreakpointItem::updateMarkerIcon() { - if (marker) { - marker->setIcon(icon()); - marker->updateMarker(); + if (m_marker) { + m_marker->setIcon(icon()); + m_marker->updateMarker(); } } -void BreakHandler::BreakpointItem::updateMarker() +void BreakpointItem::updateMarker() { QString file = markerFileName(); int line = markerLineNumber(); - if (marker && (file != marker->fileName() || line != marker->lineNumber())) + if (m_marker && (file != m_marker->fileName() || line != m_marker->lineNumber())) destroyMarker(); - if (!marker && !file.isEmpty() && line > 0) - marker = new BreakpointMarker(id, file, line); + if (!m_marker && !file.isEmpty() && line > 0) + m_marker = new BreakpointMarker(this, file, line); } -QIcon BreakHandler::BreakpointItem::icon() const +QIcon BreakpointItem::icon() const { // FIXME: This seems to be called on each cursor blink as soon as the // cursor is near a line with a breakpoint marker (+/- 2 lines or so). - if (params.isTracepoint()) + if (m_params.isTracepoint()) return BreakHandler::tracepointIcon(); - if (params.type == WatchpointAtAddress) + if (m_params.type == WatchpointAtAddress) return BreakHandler::watchpointIcon(); - if (params.type == WatchpointAtExpression) + if (m_params.type == WatchpointAtExpression) return BreakHandler::watchpointIcon(); - if (!params.enabled) + if (!m_params.enabled) return BreakHandler::disabledBreakpointIcon(); - if (state == BreakpointInserted) + if (m_state == BreakpointInserted) return BreakHandler::breakpointIcon(); return BreakHandler::pendingBreakpointIcon(); } -QString BreakHandler::BreakpointItem::toToolTip() const +QString BreakpointItem::toToolTip() const { QString rc; QTextStream str(&rc); str << "<html><body><table>" //<< "<tr><td>" << tr("ID:") << "</td><td>" << m_id << "</td></tr>" << "<tr><td>" << tr("State:") - << "</td><td>" << (params.enabled ? tr("Enabled") : tr("Disabled")); - if (response.pending) + << "</td><td>" << (m_params.enabled ? tr("Enabled") : tr("Disabled")); + if (m_response.pending) str << tr(", pending"); - str << ", " << state << " (" << stateToString(state) << ")</td></tr>"; - if (engine) { + str << ", " << m_state << " (" << stateToString(m_state) << ")</td></tr>"; + if (m_engine) { str << "<tr><td>" << tr("Engine:") - << "</td><td>" << engine->objectName() << "</td></tr>"; + << "</td><td>" << m_engine->objectName() << "</td></tr>"; } - if (!response.pending) { + if (!m_response.pending) { str << "<tr><td>" << tr("Breakpoint Number:") - << "</td><td>" << response.id.toString() << "</td></tr>"; + << "</td><td>" << m_response.id.toString() << "</td></tr>"; } str << "<tr><td>" << tr("Breakpoint Type:") - << "</td><td>" << typeToString(params.type) << "</td></tr>" + << "</td><td>" << typeToString(m_params.type) << "</td></tr>" << "<tr><td>" << tr("Marker File:") << "</td><td>" << QDir::toNativeSeparators(markerFileName()) << "</td></tr>" << "<tr><td>" << tr("Marker Line:") @@ -1406,77 +1433,77 @@ QString BreakHandler::BreakpointItem::toToolTip() const << "</th><th>" << tr("Requested") << "</th><th>" << tr("Obtained") << "</th></tr>" << "<tr><td>" << tr("Internal Number:") - << "</td><td>—</td><td>" << response.id.toString() << "</td></tr>"; - if (params.type == BreakpointByFunction) { + << "</td><td>—</td><td>" << m_response.id.toString() << "</td></tr>"; + if (m_params.type == BreakpointByFunction) { str << "<tr><td>" << tr("Function Name:") - << "</td><td>" << params.functionName - << "</td><td>" << response.functionName + << "</td><td>" << m_params.functionName + << "</td><td>" << m_response.functionName << "</td></tr>"; } - if (params.type == BreakpointByFileAndLine) { + if (m_params.type == BreakpointByFileAndLine) { str << "<tr><td>" << tr("File Name:") - << "</td><td>" << QDir::toNativeSeparators(params.fileName) - << "</td><td>" << QDir::toNativeSeparators(response.fileName) + << "</td><td>" << QDir::toNativeSeparators(m_params.fileName) + << "</td><td>" << QDir::toNativeSeparators(m_response.fileName) << "</td></tr>" << "<tr><td>" << tr("Line Number:") - << "</td><td>" << params.lineNumber - << "</td><td>" << response.lineNumber << "</td></tr>" + << "</td><td>" << m_params.lineNumber + << "</td><td>" << m_response.lineNumber << "</td></tr>" << "<tr><td>" << tr("Corrected Line Number:") << "</td><td>-" - << "</td><td>" << response.correctedLineNumber << "</td></tr>"; + << "</td><td>" << m_response.correctedLineNumber << "</td></tr>"; } - if (params.type == BreakpointByFunction || params.type == BreakpointByFileAndLine) { + if (m_params.type == BreakpointByFunction || m_params.type == BreakpointByFileAndLine) { str << "<tr><td>" << tr("Module:") - << "</td><td>" << params.module - << "</td><td>" << response.module + << "</td><td>" << m_params.module + << "</td><td>" << m_response.module << "</td></tr>"; } str << "<tr><td>" << tr("Breakpoint Address:") << "</td><td>"; - formatAddress(str, params.address); + formatAddress(str, m_params.address); str << "</td><td>"; - formatAddress(str, response.address); + formatAddress(str, m_response.address); str << "</td></tr>"; - if (response.multiple) { + if (m_response.multiple) { str << "<tr><td>" << tr("Multiple Addresses:") << "</td><td>" << "</td></tr>"; } - if (!params.command.isEmpty() || !response.command.isEmpty()) { + if (!m_params.command.isEmpty() || !m_response.command.isEmpty()) { str << "<tr><td>" << tr("Command:") - << "</td><td>" << params.command - << "</td><td>" << response.command + << "</td><td>" << m_params.command + << "</td><td>" << m_response.command << "</td></tr>"; } - if (!params.message.isEmpty() || !response.message.isEmpty()) { + if (!m_params.message.isEmpty() || !m_response.message.isEmpty()) { str << "<tr><td>" << tr("Message:") - << "</td><td>" << params.message - << "</td><td>" << response.message + << "</td><td>" << m_params.message + << "</td><td>" << m_response.message << "</td></tr>"; } - if (!params.condition.isEmpty() || !response.condition.isEmpty()) { + if (!m_params.condition.isEmpty() || !m_response.condition.isEmpty()) { str << "<tr><td>" << tr("Condition:") - << "</td><td>" << params.condition - << "</td><td>" << response.condition + << "</td><td>" << m_params.condition + << "</td><td>" << m_response.condition << "</td></tr>"; } - if (params.ignoreCount || response.ignoreCount) { + if (m_params.ignoreCount || m_response.ignoreCount) { str << "<tr><td>" << tr("Ignore Count:") << "</td><td>"; - if (params.ignoreCount) - str << params.ignoreCount; + if (m_params.ignoreCount) + str << m_params.ignoreCount; str << "</td><td>"; - if (response.ignoreCount) - str << response.ignoreCount; + if (m_response.ignoreCount) + str << m_response.ignoreCount; str << "</td></tr>"; } - if (params.threadSpec >= 0 || response.threadSpec >= 0) { + if (m_params.threadSpec >= 0 || m_response.threadSpec >= 0) { str << "<tr><td>" << tr("Thread Specification:") << "</td><td>"; - if (params.threadSpec >= 0) - str << params.threadSpec; + if (m_params.threadSpec >= 0) + str << m_params.threadSpec; str << "</td><td>"; - if (response.threadSpec >= 0) - str << response.threadSpec; + if (m_response.threadSpec >= 0) + str << m_response.threadSpec; str << "</td></tr>"; } str << "</table></body></html>"; @@ -1488,8 +1515,7 @@ void BreakHandler::setWatchpointAtAddress(quint64 address, unsigned size) BreakpointParameters params(WatchpointAtAddress); params.address = address; params.size = size; - BreakpointModelId id = findWatchpoint(params); - if (id) { + if (findWatchpoint(params)) { qDebug() << "WATCHPOINT EXISTS"; // removeBreakpoint(index); return; @@ -1501,8 +1527,7 @@ void BreakHandler::setWatchpointAtExpression(const QString &exp) { BreakpointParameters params(WatchpointAtExpression); params.expression = exp; - BreakpointModelId id = findWatchpoint(params); - if (id) { + if (findWatchpoint(params)) { qDebug() << "WATCHPOINT EXISTS"; // removeBreakpoint(index); return; @@ -1510,5 +1535,67 @@ void BreakHandler::setWatchpointAtExpression(const QString &exp) appendBreakpoint(params); } +bool Breakpoint::isValid() const +{ + return b && b->m_id.isValid(); +} + +uint Breakpoint::hash() const +{ + return b ? 0 : qHash(b->m_id); +} + +BreakpointModelId Breakpoint::id() const +{ + return b ? b->m_id : BreakpointModelId(); +} + +QString Breakpoint::msgWatchpointByExpressionTriggered(const int number, const QString &expr) const +{ + return id() + ? tr("Data breakpoint %1 (%2) at %3 triggered.") + .arg(id().toString()).arg(number).arg(expr) + : tr("Internal data breakpoint %1 at %2 triggered.") + .arg(number).arg(expr); +} + +QString Breakpoint::msgWatchpointByExpressionTriggered(const int number, const QString &expr, + const QString &threadId) const +{ + return id() + ? tr("Data breakpoint %1 (%2) at %3 in thread %4 triggered.") + .arg(id().toString()).arg(number).arg(expr).arg(threadId) + : tr("Internal data breakpoint %1 at %2 in thread %3 triggered.") + .arg(number).arg(expr).arg(threadId); +} + +QString Breakpoint::msgWatchpointByAddressTriggered(const int number, quint64 address) const +{ + return id() + ? tr("Data breakpoint %1 (%2) at 0x%3 triggered.") + .arg(id().toString()).arg(number).arg(address, 0, 16) + : tr("Internal data breakpoint %1 at 0x%2 triggered.") + .arg(number).arg(address, 0, 16); +} + +QString Breakpoint::msgWatchpointByAddressTriggered( + const int number, quint64 address, const QString &threadId) const +{ + return id() + ? tr("Data breakpoint %1 (%2) at 0x%3 in thread %4 triggered.") + .arg(id().toString()).arg(number).arg(address, 0, 16).arg(threadId) + : tr("Internal data breakpoint %1 at 0x%2 in thread %3 triggered.") + .arg(id().toString()).arg(number).arg(address, 0, 16).arg(threadId); +} + +QString Breakpoint::msgBreakpointTriggered(const int number, const QString &threadId) const +{ + return id() + ? tr("Stopped at breakpoint %1 (%2) in thread %3.") + .arg(id().toString()).arg(number).arg(threadId) + : tr("Stopped at internal breakpoint %1 in thread %2.") + .arg(number).arg(threadId); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/breakhandler.h b/src/plugins/debugger/breakhandler.h index 6b3e08fc63..8342e24ed0 100644 --- a/src/plugins/debugger/breakhandler.h +++ b/src/plugins/debugger/breakhandler.h @@ -35,6 +35,9 @@ #include <utils/treemodel.h> +#include <QCoreApplication> +#include <QPointer> + ////////////////////////////////////////////////////////////////// // // BreakHandler @@ -44,9 +47,122 @@ namespace Debugger { namespace Internal { -class BreakpointMarker; +class BreakpointItem; +class BreakHandler; class DebuggerEngine; +// Non-owning "deletion-safe" wrapper around a BreakpointItem * +class Breakpoint +{ + Q_DECLARE_TR_FUNCTIONS(Debugger::Internal::BreakHandler) + +public: + Breakpoint() {} + + bool isValid() const; + operator const void *() const { return isValid() ? this : 0; } + bool operator!() const { return !isValid(); } + + uint hash() const; + + const BreakpointParameters ¶meters() const; + + BreakpointModelId id() const; + bool isLocatedAt(const QString &fileName, int lineNumber, + bool useMarkerPosition) const; + + QIcon icon() const; + BreakpointState state() const; + void setEngine(DebuggerEngine *engine); + + // State transitions. + void notifyBreakpointChangeAfterInsertNeeded(); + void notifyBreakpointInsertProceeding(); + void notifyBreakpointInsertOk(); + void notifyBreakpointInsertFailed(); + void notifyBreakpointChangeOk(); + void notifyBreakpointChangeProceeding(); + void notifyBreakpointChangeFailed(); + void notifyBreakpointPending(); + void notifyBreakpointRemoveProceeding(); + void notifyBreakpointRemoveOk(); + void notifyBreakpointRemoveFailed(); + void notifyBreakpointReleased(); + void notifyBreakpointNeedsReinsertion(); + void notifyBreakpointAdjusted(const BreakpointParameters ¶ms); + + void update(); + + void gotoLocation() const; + + // Getter retrieves property value. + // Setter sets property value and triggers update if changed. + // Only use setters when it is safe to assume that the breakpoint still + // exist. That's not the case if the event loop could run after you + // obtained the BreakpointItem pointer. + BreakpointPathUsage pathUsage() const; + void setPathUsage(const BreakpointPathUsage &u); + QByteArray condition() const; + void setCondition(const QByteArray &condition); + int ignoreCount() const; + void setIgnoreCount(const int &count); + int threadSpec() const; + void setThreadSpec(const int &spec); + QString fileName() const; + void setFileName(const QString &fileName); + QString functionName() const; + void setFunctionName(const QString &functionName); + QString expression() const; + void setExpression(const QString &expression); + QString message() const; + void setMessage(const QString &m); + BreakpointType type() const; + void setType(const BreakpointType &type); + quint64 address() const; + void setAddress(const quint64 &address); + int lineNumber() const; + void changeBreakpointData(const BreakpointParameters &data); + bool isEnabled() const; + void setEnabled(bool on) const; + void updateFileNameFromMarker(const QString &fileName); + void updateLineNumberFromMarker(int lineNumber); + void changeLineNumberFromMarker(int lineNumber); + void setMarkerFileAndLine(const QString &fileName, int lineNumber); + bool isWatchpoint() const; + bool isTracepoint() const; + void setTracepoint(bool on); + DebuggerEngine *engine() const; + const BreakpointResponse &response() const; + void setResponse(const BreakpointResponse &data); + bool needsChange() const; + bool needsChildren() const; + + bool isOneShot() const; + void insertSubBreakpoint(const BreakpointResponse &data); + void removeAlienBreakpoint(); + void removeBreakpoint() const; + + QString msgWatchpointByAddressTriggered(int number, quint64 address) const; + QString msgWatchpointByAddressTriggered( + int number, quint64 address, const QString &threadId) const; + QString msgWatchpointByExpressionTriggered(int number, const QString &expr) const; + QString msgWatchpointByExpressionTriggered( + int number, const QString &expr, const QString &threadId) const; + QString msgBreakpointTriggered(int number, const QString &threadId) const; + +private: + void gotoState(BreakpointState target, BreakpointState assumedCurrent); + + friend class BreakHandler; + explicit Breakpoint(BreakpointItem *b); + + QPointer<BreakpointItem> b; +}; + +inline uint qHash(const Debugger::Internal::Breakpoint &b) { return b.hash(); } + +typedef QList<Breakpoint> Breakpoints; + class BreakHandler : public Utils::TreeModel { Q_OBJECT @@ -62,21 +178,19 @@ public: // The only way to add a new breakpoint. void appendBreakpoint(const BreakpointParameters &data); void handleAlienBreakpoint(const BreakpointResponse &response, DebuggerEngine *engine); - void insertSubBreakpoint(BreakpointModelId id, const BreakpointResponse &data); - void removeAlienBreakpoint(BreakpointModelId id); - BreakpointModelIds allBreakpointIds() const; - BreakpointModelIds engineBreakpointIds(DebuggerEngine *engine) const; - BreakpointModelIds unclaimedBreakpointIds() const; + Breakpoints allBreakpoints() const; + Breakpoints engineBreakpoints(DebuggerEngine *engine) const; + Breakpoints unclaimedBreakpoints() const; QStringList engineBreakpointPaths(DebuggerEngine *engine) const; // Find a breakpoint matching approximately the data in needle. - BreakpointModelId findSimilarBreakpoint(const BreakpointResponse &needle) const; - BreakpointModelId findBreakpointByResponseId(const BreakpointResponseId &resultId) const; - BreakpointModelId findWatchpoint(const BreakpointParameters &data) const; - BreakpointModelId findBreakpointByFunction(const QString &functionName) const; - BreakpointModelId findBreakpointByIndex(const QModelIndex &index) const; - BreakpointModelIds findBreakpointsByIndex(const QList<QModelIndex> &list) const; + Breakpoint findSimilarBreakpoint(const BreakpointResponse &needle) const; + Breakpoint findBreakpointByResponseId(const BreakpointResponseId &resultId) const; + Breakpoint findWatchpoint(const BreakpointParameters &data) const; + Breakpoint findBreakpointByFunction(const QString &functionName) const; + Breakpoint findBreakpointByIndex(const QModelIndex &index) const; + Breakpoints findBreakpointsByIndex(const QList<QModelIndex> &list) const; void updateMarkers(); static QIcon breakpointIcon(); @@ -86,77 +200,11 @@ public: static QIcon watchpointIcon(); static QIcon tracepointIcon(); - BreakpointModelId findBreakpointByFileAndLine(const QString &fileName, + Breakpoint findBreakpointByFileAndLine(const QString &fileName, int lineNumber, bool useMarkerPosition = true); - BreakpointModelId findBreakpointByAddress(quint64 address) const; + Breakpoint findBreakpointByAddress(quint64 address) const; void breakByFunction(const QString &functionName); - void removeBreakpoint(BreakpointModelId id); - QIcon icon(BreakpointModelId id) const; - void gotoLocation(BreakpointModelId id) const; - - // Getter retrieves property value. - // Setter sets property value and triggers update if changed. - BreakpointPathUsage pathUsage(BreakpointModelId id) const; - void setPathUsage(BreakpointModelId, const BreakpointPathUsage &u); - QByteArray condition(BreakpointModelId id) const; - void setCondition(BreakpointModelId, const QByteArray &condition); - int ignoreCount(BreakpointModelId id) const; - void setIgnoreCount(BreakpointModelId, const int &count); - int threadSpec(BreakpointModelId id) const; - void setThreadSpec(BreakpointModelId, const int &spec); - QString fileName(BreakpointModelId id) const; - void setFileName(BreakpointModelId, const QString &fileName); - QString functionName(BreakpointModelId id) const; - void setFunctionName(BreakpointModelId, const QString &functionName); - QString expression(BreakpointModelId id) const; - void setExpression(BreakpointModelId, const QString &expression); - QString message(BreakpointModelId id) const; - void setMessage(BreakpointModelId, const QString &m); - BreakpointType type(BreakpointModelId id) const; - void setType(BreakpointModelId id, const BreakpointType &type); - quint64 address(BreakpointModelId id) const; - void setAddress(BreakpointModelId id, const quint64 &address); - int lineNumber(BreakpointModelId id) const; - void changeBreakpointData(BreakpointModelId id, const BreakpointParameters &data, - BreakpointParts parts); - const BreakpointParameters &breakpointData(BreakpointModelId id) const; - BreakpointState state(BreakpointModelId id) const; - bool isEnabled(BreakpointModelId id) const; - void setEnabled(BreakpointModelId id, bool on); - void updateFileNameFromMarker(BreakpointModelId id, const QString &fileName); - void updateLineNumberFromMarker(BreakpointModelId id, int lineNumber); - void changeLineNumberFromMarker(BreakpointModelId id, int lineNumber); - void setMarkerFileAndLine(BreakpointModelId id, - const QString &fileName, int lineNumber); - bool isOneShot(BreakpointModelId id) const; - bool isWatchpoint(BreakpointModelId id) const; - bool isTracepoint(BreakpointModelId id) const; - void setTracepoint(BreakpointModelId, bool on); - DebuggerEngine *engine(BreakpointModelId id) const; - void setEngine(BreakpointModelId id, DebuggerEngine *engine); - const BreakpointResponse &response(BreakpointModelId id) const; - void setResponse(BreakpointModelId id, const BreakpointResponse &data); - bool needsChange(BreakpointModelId id) const; - bool needsChildren(BreakpointModelId id) const; - - // State transitions. - void notifyBreakpointChangeAfterInsertNeeded(BreakpointModelId id); - void notifyBreakpointInsertProceeding(BreakpointModelId id); - void notifyBreakpointInsertOk(BreakpointModelId id); - void notifyBreakpointInsertFailed(BreakpointModelId id); - void notifyBreakpointChangeOk(BreakpointModelId id); - void notifyBreakpointChangeProceeding(BreakpointModelId id); - void notifyBreakpointChangeFailed(BreakpointModelId id); - void notifyBreakpointPending(BreakpointModelId id); - void notifyBreakpointRemoveProceeding(BreakpointModelId id); - void notifyBreakpointRemoveOk(BreakpointModelId id); - void notifyBreakpointRemoveFailed(BreakpointModelId id); - void notifyBreakpointReleased(BreakpointModelId id); - void notifyBreakpointNeedsReinsertion(BreakpointModelId id); - void notifyBreakpointAdjusted(BreakpointModelId id, - const BreakpointParameters &data); - static QString displayFromThreadSpec(int spec); static int threadSpecFromDisplay(const QString &str); @@ -164,54 +212,22 @@ public: void setWatchpointAtAddress(quint64 address, unsigned size); void setWatchpointAtExpression(const QString &exp); + Breakpoint breakpointById(BreakpointModelId id) const; + signals: void requestExpansion(QModelIndex); private: - bool isEngineRunning(BreakpointModelId id) const; - void setState(BreakpointModelId id, BreakpointState state); + friend class BreakpointItem; + friend class Breakpoint; + void loadBreakpoints(); void saveBreakpoints(); - void cleanupBreakpoint(BreakpointModelId id); + void appendBreakpointInternal(const BreakpointParameters &data); - Q_SLOT void changeLineNumberFromMarkerHelper(Debugger::Internal::BreakpointModelId id, int lineNumber); - - struct BreakpointItem : public Utils::TreeItem - { - BreakpointItem(); - ~BreakpointItem(); - - int columnCount() const { return 8; } - QVariant data(int column, int role) const; - - void destroyMarker(); - bool needsChange() const; - bool isLocatedAt(const QString &fileName, int lineNumber, - bool useMarkerPosition) const; - void updateMarker(); - void updateMarkerIcon(); - QString toToolTip() const; - QString markerFileName() const; - int markerLineNumber() const; - QIcon icon() const; - - BreakpointModelId id; - BreakpointParameters params; - BreakpointState state; // Current state of breakpoint. - DebuggerEngine *engine; // Engine currently handling the breakpoint. - BreakpointResponse response; - BreakpointMarker *marker; - }; - - struct LocationItem : public Utils::TreeItem - { - int columnCount() const { return 8; } - QVariant data(int column, int role) const; - - BreakpointResponse params; - }; - - BreakpointItem *breakpointById(BreakpointModelId id) const; + + Q_SLOT void changeLineNumberFromMarkerHelper(Debugger::Internal::BreakpointModelId id); + Q_SLOT void deletionHelper(Debugger::Internal::BreakpointModelId id); void scheduleSynchronization(); void timerEvent(QTimerEvent *event); @@ -221,4 +237,6 @@ private: } // namespace Internal } // namespace Debugger +Q_DECLARE_METATYPE(Debugger::Internal::Breakpoint) + #endif // DEBUGGER_BREAKHANDLER_H diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index 5358ac0e80..e99e15ce2b 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -199,7 +199,6 @@ inline void operator|=(BreakpointParts &p, BreakpointParts r) p = BreakpointParts(int(p) | int(r)); } - class BreakpointParameters { public: @@ -257,8 +256,6 @@ public: int correctedLineNumber; //!< Line number as seen by gdb. }; -typedef QList<BreakpointModelId> BreakpointModelIds; - inline uint qHash(const Debugger::Internal::BreakpointModelId &id) { return id.toInternalId(); diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index 47f9edc719..5c343106db 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -80,7 +80,7 @@ class BreakpointDialog : public QDialog { Q_OBJECT public: - explicit BreakpointDialog(BreakpointModelId id, QWidget *parent = 0); + explicit BreakpointDialog(Breakpoint b, QWidget *parent = 0); bool showDialog(BreakpointParameters *data, BreakpointParts *parts); void setParameters(const BreakpointParameters &data); @@ -138,7 +138,7 @@ private: QDialogButtonBox *m_buttonBox; }; -BreakpointDialog::BreakpointDialog(BreakpointModelId id, QWidget *parent) +BreakpointDialog::BreakpointDialog(Breakpoint b, QWidget *parent) : QDialog(parent), m_enabledParts(~0), m_previousType(UnknownBreakpointType), m_firstTypeChange(true) { @@ -268,8 +268,8 @@ BreakpointDialog::BreakpointDialog(BreakpointModelId id, QWidget *parent) m_buttonBox = new QDialogButtonBox(this); m_buttonBox->setStandardButtons(QDialogButtonBox::Cancel|QDialogButtonBox::Ok); - if (id.isValid()) { - if (DebuggerEngine *engine = breakHandler()->engine(id)) { + if (b) { + if (DebuggerEngine *engine = b.engine()) { if (!engine->hasCapability(BreakConditionCapability)) m_enabledParts &= ~ConditionPart; if (!engine->hasCapability(BreakModuleCapability)) @@ -695,7 +695,7 @@ void BreakTreeView::keyPressEvent(QKeyEvent *ev) QModelIndexList si = sm->selectedRows(); if (si.isEmpty()) si.append(currentIndex()); - const BreakpointModelIds ids = breakHandler()->findBreakpointsByIndex(si); + const Breakpoints ids = breakHandler()->findBreakpointsByIndex(si); int row = qMin(model()->rowCount() - ids.size() - 1, currentIndex().row()); deleteBreakpoints(ids); setCurrentIndex(model()->index(row, 0)); @@ -704,10 +704,9 @@ void BreakTreeView::keyPressEvent(QKeyEvent *ev) QTC_ASSERT(sm, return); const QModelIndexList selectedIds = sm->selectedRows(); if (!selectedIds.isEmpty()) { - BreakHandler *handler = breakHandler(); - const BreakpointModelIds validIds = handler->findBreakpointsByIndex(selectedIds); - const bool isEnabled = validIds.isEmpty() || handler->isEnabled(validIds.at(0)); - setBreakpointsEnabled(validIds, !isEnabled); + const Breakpoints items = breakHandler()->findBreakpointsByIndex(selectedIds); + const bool isEnabled = items.isEmpty() || items.at(0).isEnabled(); + setBreakpointsEnabled(items, !isEnabled); foreach (const QModelIndex &id, selectedIds) update(id); } @@ -720,8 +719,9 @@ void BreakTreeView::mouseDoubleClickEvent(QMouseEvent *ev) QModelIndex indexUnderMouse = indexAt(ev->pos()); if (indexUnderMouse.isValid()) { if (indexUnderMouse.column() >= 4) { - BreakpointModelId id = breakHandler()->findBreakpointByIndex(indexUnderMouse); - editBreakpoints(BreakpointModelIds() << id); + Breakpoint b = breakHandler()->findBreakpointByIndex(indexUnderMouse); + QTC_ASSERT(b, return); + editBreakpoints(Breakpoints() << b); } } else { addBreakpoint(); @@ -740,21 +740,18 @@ void BreakTreeView::contextMenuEvent(QContextMenuEvent *ev) selectedIndices.append(indexUnderMouse); BreakHandler *handler = breakHandler(); - BreakpointModelIds selectedIds; - foreach (BreakpointModelId id, handler->findBreakpointsByIndex(selectedIndices)) - if (id.isMajor()) - selectedIds.append(id); + Breakpoints selectedItems = handler->findBreakpointsByIndex(selectedIndices); const int rowCount = model()->rowCount(); - QAction *deleteAction = new QAction(tr("Delete Breakpoint"), &menu); - deleteAction->setEnabled(!selectedIds.empty()); + auto deleteAction = new QAction(tr("Delete Breakpoint"), &menu); + deleteAction->setEnabled(!selectedItems.empty()); - QAction *deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu); + auto deleteAllAction = new QAction(tr("Delete All Breakpoints"), &menu); deleteAllAction->setEnabled(model()->rowCount() > 0); // Delete by file: Find indices of breakpoints of the same file. QAction *deleteByFileAction = 0; - BreakpointModelIds breakpointsInFile; + Breakpoints breakpointsInFile; if (indexUnderMouse.isValid()) { const QModelIndex index = indexUnderMouse.sibling(indexUnderMouse.row(), 2); const QString file = index.data().toString(); @@ -774,36 +771,33 @@ void BreakTreeView::contextMenuEvent(QContextMenuEvent *ev) deleteByFileAction->setEnabled(false); } - QAction *editBreakpointAction = - new QAction(tr("Edit Breakpoint..."), &menu); - editBreakpointAction->setEnabled(!selectedIds.isEmpty()); + auto editBreakpointAction = new QAction(tr("Edit Breakpoint..."), &menu); + editBreakpointAction->setEnabled(!selectedItems.isEmpty()); int threadId = 0; // FIXME BP: m_engine->threadsHandler()->currentThreadId(); QString associateTitle = threadId == -1 ? tr("Associate Breakpoint With All Threads") : tr("Associate Breakpoint With Thread %1").arg(threadId); - QAction *associateBreakpointAction = new QAction(associateTitle, &menu); - associateBreakpointAction->setEnabled(!selectedIds.isEmpty()); + auto associateBreakpointAction = new QAction(associateTitle, &menu); + associateBreakpointAction->setEnabled(!selectedItems.isEmpty()); - QAction *synchronizeAction = - new QAction(tr("Synchronize Breakpoints"), &menu); + auto synchronizeAction = new QAction(tr("Synchronize Breakpoints"), &menu); synchronizeAction->setEnabled(Internal::hasSnapshots()); - bool enabled = selectedIds.isEmpty() || handler->isEnabled(selectedIds.at(0)); + bool enabled = selectedItems.isEmpty() || selectedItems.at(0).isEnabled(); - const QString str5 = selectedIds.size() > 1 + const QString str5 = selectedItems.size() > 1 ? enabled ? tr("Disable Selected Breakpoints") : tr("Enable Selected Breakpoints") : enabled ? tr("Disable Breakpoint") : tr("Enable Breakpoint"); - QAction *toggleEnabledAction = new QAction(str5, &menu); - toggleEnabledAction->setEnabled(!selectedIds.isEmpty()); + auto toggleEnabledAction = new QAction(str5, &menu); + toggleEnabledAction->setEnabled(!selectedItems.isEmpty()); - QAction *addBreakpointAction = - new QAction(tr("Add Breakpoint..."), this); + auto addBreakpointAction = new QAction(tr("Add Breakpoint..."), this); menu.addAction(addBreakpointAction); menu.addAction(deleteAction); @@ -825,28 +819,27 @@ void BreakTreeView::contextMenuEvent(QContextMenuEvent *ev) QAction *act = menu.exec(ev->globalPos()); if (act == deleteAction) - deleteBreakpoints(selectedIds); + deleteBreakpoints(selectedItems); else if (act == deleteAllAction) deleteAllBreakpoints(); else if (act == deleteByFileAction) deleteBreakpoints(breakpointsInFile); else if (act == editBreakpointAction) - editBreakpoints(selectedIds); + editBreakpoints(selectedItems); else if (act == associateBreakpointAction) - associateBreakpoint(selectedIds, threadId); + associateBreakpoint(selectedItems, threadId); else if (act == synchronizeAction) ; //synchronizeBreakpoints(); else if (act == toggleEnabledAction) - setBreakpointsEnabled(selectedIds, !enabled); + setBreakpointsEnabled(selectedItems, !enabled); else if (act == addBreakpointAction) addBreakpoint(); } -void BreakTreeView::setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled) +void BreakTreeView::setBreakpointsEnabled(const Breakpoints &bps, bool enabled) { - BreakHandler *handler = breakHandler(); - foreach (const BreakpointModelId id, ids) - handler->setEnabled(id, enabled); + foreach (Breakpoint b, bps) + b.setEnabled(enabled); } void BreakTreeView::deleteAllBreakpoints() @@ -857,55 +850,56 @@ void BreakTreeView::deleteAllBreakpoints() "from all files in the current session?"), Core::ICore::settings(), QLatin1String("RemoveAllBreakpoints")) == QDialogButtonBox::Yes) - deleteBreakpoints(breakHandler()->allBreakpointIds()); + deleteBreakpoints(breakHandler()->allBreakpoints()); } -void BreakTreeView::deleteBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::deleteBreakpoints(const Breakpoints &bps) { - BreakHandler *handler = breakHandler(); - foreach (const BreakpointModelId id, ids) - handler->removeBreakpoint(id); + foreach (Breakpoint bp, bps) + bp.removeBreakpoint(); } -void BreakTreeView::editBreakpoint(BreakpointModelId id, QWidget *parent) +void BreakTreeView::editBreakpoint(Breakpoint bp, QWidget *parent) { - BreakpointParameters data = breakHandler()->breakpointData(id); + BreakpointParameters data = bp.parameters(); BreakpointParts parts = NoParts; - BreakpointDialog dialog(id, parent); - if (dialog.showDialog(&data, &parts)) - breakHandler()->changeBreakpointData(id, data, parts); + + BreakpointDialog dialog(bp, parent); + if (!dialog.showDialog(&data, &parts)) + return; + + bp.changeBreakpointData(data); } void BreakTreeView::addBreakpoint() { BreakpointParameters data(BreakpointByFileAndLine); BreakpointParts parts = NoParts; - BreakpointDialog dialog(BreakpointModelId(), this); + BreakpointDialog dialog(Breakpoint(), this); dialog.setWindowTitle(tr("Add Breakpoint")); if (dialog.showDialog(&data, &parts)) breakHandler()->appendBreakpoint(data); } -void BreakTreeView::editBreakpoints(const BreakpointModelIds &ids) +void BreakTreeView::editBreakpoints(const Breakpoints &bps) { - QTC_ASSERT(!ids.isEmpty(), return); + QTC_ASSERT(!bps.isEmpty(), return); - const BreakpointModelId id = ids.at(0); + const Breakpoint bp = bps.at(0); - if (ids.size() == 1) { - editBreakpoint(id, this); + if (bps.size() == 1) { + editBreakpoint(bp, this); return; } // This allows to change properties of multiple breakpoints at a time. - BreakHandler *handler = breakHandler(); + if (!bp) + return; + MultiBreakPointsDialog dialog; - const QString oldCondition = QString::fromLatin1(handler->condition(id)); - dialog.setCondition(oldCondition); - const int oldIgnoreCount = handler->ignoreCount(id); - dialog.setIgnoreCount(oldIgnoreCount); - const int oldThreadSpec = handler->threadSpec(id); - dialog.setThreadSpec(oldThreadSpec); + dialog.setCondition(QString::fromLatin1(bp.condition())); + dialog.setIgnoreCount(bp.ignoreCount()); + dialog.setThreadSpec(bp.threadSpec()); if (dialog.exec() == QDialog::Rejected) return; @@ -914,27 +908,27 @@ void BreakTreeView::editBreakpoints(const BreakpointModelIds &ids) const int newIgnoreCount = dialog.ignoreCount(); const int newThreadSpec = dialog.threadSpec(); - if (newCondition == oldCondition && newIgnoreCount == oldIgnoreCount - && newThreadSpec == oldThreadSpec) - return; - - foreach (const BreakpointModelId id, ids) { - handler->setCondition(id, newCondition.toLatin1()); - handler->setIgnoreCount(id, newIgnoreCount); - handler->setThreadSpec(id, newThreadSpec); + foreach (Breakpoint bp, bps) { + if (bp) { + bp.setCondition(newCondition.toLatin1()); + bp.setIgnoreCount(newIgnoreCount); + bp.setThreadSpec(newThreadSpec); + } } } -void BreakTreeView::associateBreakpoint(const BreakpointModelIds &ids, int threadId) +void BreakTreeView::associateBreakpoint(const Breakpoints &bps, int threadId) { - BreakHandler *handler = breakHandler(); - foreach (const BreakpointModelId id, ids) - handler->setThreadSpec(id, threadId); + foreach (Breakpoint bp, bps) { + if (bp) + bp.setThreadSpec(threadId); + } } void BreakTreeView::rowActivated(const QModelIndex &index) { - breakHandler()->gotoLocation(breakHandler()->findBreakpointByIndex(index)); + if (Breakpoint bp = breakHandler()->findBreakpointByIndex(index)) + bp.gotoLocation(); } } // namespace Internal diff --git a/src/plugins/debugger/breakwindow.h b/src/plugins/debugger/breakwindow.h index 4d7b06e4a5..d41a91eb45 100644 --- a/src/plugins/debugger/breakwindow.h +++ b/src/plugins/debugger/breakwindow.h @@ -31,7 +31,7 @@ #ifndef DEBUGGER_BREAKWINDOW_H #define DEBUGGER_BREAKWINDOW_H -#include "breakpoint.h" +#include "breakhandler.h" #include <utils/basetreeview.h> namespace Debugger { @@ -44,7 +44,7 @@ class BreakTreeView : public Utils::BaseTreeView public: BreakTreeView(); - static void editBreakpoint(BreakpointModelId id, QWidget *parent); + static void editBreakpoint(Breakpoint bp, QWidget *parent); private slots: void showAddressColumn(bool on); @@ -55,12 +55,12 @@ private: void keyPressEvent(QKeyEvent *ev); void mouseDoubleClickEvent(QMouseEvent *ev); - void deleteBreakpoints(const BreakpointModelIds &ids); + void deleteBreakpoints(const Breakpoints &bps); void deleteAllBreakpoints(); void addBreakpoint(); - void editBreakpoints(const BreakpointModelIds &ids); - void associateBreakpoint(const BreakpointModelIds &ids, int thread); - void setBreakpointsEnabled(const BreakpointModelIds &ids, bool enabled); + void editBreakpoints(const Breakpoints &bps); + void associateBreakpoint(const Breakpoints &bps, int thread); + void setBreakpointsEnabled(const Breakpoints &bps, bool enabled); }; } // namespace Internal diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 8710b8e6b2..ab3a964c13 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -2073,9 +2073,10 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason, // Step out creates temporary breakpoints with id 10000. int number = 0; BreakpointModelId id = cdbIdToBreakpointModelId(stopReason["breakpointId"]); - if (id.isValid()) { - if (breakHandler()->engineBreakpointIds(this).contains(id)) { - const BreakpointResponse parameters = breakHandler()->response(id); + Breakpoint bp = breakHandler()->breakpointById(id); + if (bp) { + if (bp.engine() == this) { + const BreakpointResponse parameters = bp.response(); if (!parameters.message.isEmpty()) { showMessage(parameters.message + QLatin1Char('\n'), AppOutput); showMessage(parameters.message, LogMisc); @@ -2096,16 +2097,16 @@ unsigned CdbEngine::examineStopReason(const GdbMi &stopReason, return StopReportLog; } } else { - id = BreakpointModelId(); + bp = Breakpoint(); } } QString tid = QString::number(threadId); - if (id && breakHandler()->type(id) == WatchpointAtAddress) - *message = msgWatchpointByAddressTriggered(id, number, breakHandler()->address(id), tid); - else if (id && breakHandler()->type(id) == WatchpointAtExpression) - *message = msgWatchpointByExpressionTriggered(id, number, breakHandler()->expression(id), tid); + if (bp.type() == WatchpointAtAddress) + *message = bp.msgWatchpointByAddressTriggered(number, bp.address(), tid); + else if (bp.type() == WatchpointAtExpression) + *message = bp.msgWatchpointByExpressionTriggered(number, bp.expression(), tid); else - *message = msgBreakpointTriggered(id, number, tid); + *message = bp.msgBreakpointTriggered(number, tid); rc |= StopReportStatusMessage|StopNotifyStop; return rc; } @@ -2317,6 +2318,7 @@ void CdbEngine::handleBreakInsert(const CdbBuiltinCommandPtr &cmd) if (!ok) return; const BreakpointModelId &originalId = cdbIdToBreakpointModelId(cdbBreakPointId); + Breakpoint bp = breakHandler()->breakpointById(originalId); // add break point for every match const QList<QByteArray>::const_iterator &end = reply.constEnd(); int subBreakPointID = 0; @@ -2336,7 +2338,7 @@ void CdbEngine::handleBreakInsert(const CdbBuiltinCommandPtr &cmd) continue; BreakpointModelId id(originalId.majorPart(), ++subBreakPointID); - BreakpointResponse res = breakHandler()->response(originalId); + BreakpointResponse res = bp.response(); res.type = BreakpointByAddress; res.address = address; m_insertSubBreakpointMap.insert(id, res); @@ -2748,12 +2750,11 @@ bool CdbEngine::stateAcceptsBreakpointChanges() const return false; } -bool CdbEngine::acceptsBreakpoint(BreakpointModelId id) const +bool CdbEngine::acceptsBreakpoint(Breakpoint bp) const { - const BreakpointParameters &data = breakHandler()->breakpointData(id); - if (!data.isCppBreakpoint()) + if (!bp.parameters().isCppBreakpoint()) return false; - switch (data.type) { + switch (bp.type()) { case UnknownBreakpointType: case LastBreakpointType: case BreakpointAtFork: @@ -2827,23 +2828,21 @@ unsigned BreakpointCorrectionContext::fixLineNumber(const QString &fileName, void CdbEngine::attemptBreakpointSynchronization() { - - if (debug) qDebug("attemptBreakpointSynchronization in %s", stateName(state())); // Check if there is anything to be done at all. BreakHandler *handler = breakHandler(); // Take ownership of the breakpoint. Requests insertion. TODO: Cpp only? - foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) - if (acceptsBreakpoint(id)) - handler->setEngine(id, this); + foreach (Breakpoint bp, handler->unclaimedBreakpoints()) + if (acceptsBreakpoint(bp)) + bp.setEngine(this); // Quick check: is there a need to change something? - Populate module cache bool changed = !m_insertSubBreakpointMap.isEmpty(); - const BreakpointModelIds ids = handler->engineBreakpointIds(this); + const Breakpoints bps = handler->engineBreakpoints(this); if (!changed) { - foreach (BreakpointModelId id, ids) { - switch (handler->state(id)) { + foreach (Breakpoint bp, bps) { + switch (bp.state()) { case BreakpointInsertRequested: case BreakpointRemoveRequested: case BreakpointChangeRequested: @@ -2852,7 +2851,7 @@ void CdbEngine::attemptBreakpointSynchronization() case BreakpointInserted: { // Collect the new modules matching the files. // In the future, that information should be obtained from the build system. - const BreakpointParameters &data = handler->breakpointData(id); + const BreakpointParameters &data = bp.parameters(); if (data.type == BreakpointByFileAndLine && !data.module.isEmpty()) m_fileNameModuleHash.insert(data.fileName, data.module); } @@ -2865,7 +2864,7 @@ void CdbEngine::attemptBreakpointSynchronization() if (debugBreakpoints) qDebug("attemptBreakpointSynchronizationI %dms accessible=%d, %s %d breakpoints, changed=%d", - elapsedLogTime(), m_accessible, stateName(state()), ids.size(), changed); + elapsedLogTime(), m_accessible, stateName(state()), bps.size(), changed); if (!changed) return; @@ -2880,8 +2879,9 @@ void CdbEngine::attemptBreakpointSynchronization() // handleBreakPoints will the complete that information and set it on the break handler. bool addedChanged = false; QScopedPointer<BreakpointCorrectionContext> lineCorrection; - foreach (BreakpointModelId id, ids) { - BreakpointParameters parameters = handler->breakpointData(id); + foreach (Breakpoint bp, bps) { + BreakpointParameters parameters = bp.parameters(); + BreakpointModelId id = bp.id(); BreakpointResponse response; response.fromParameters(parameters); response.id = BreakpointResponseId(id.majorPart(), id.minorPart()); @@ -2891,7 +2891,7 @@ void CdbEngine::attemptBreakpointSynchronization() if (it != m_fileNameModuleHash.constEnd()) parameters.module = it.value(); } - switch (handler->state(id)) { + switch (bp.state()) { case BreakpointInsertRequested: if (!m_autoBreakPointCorrection && parameters.type == BreakpointByFileAndLine @@ -2910,29 +2910,29 @@ void CdbEngine::attemptBreakpointSynchronization() } if (!parameters.enabled) postCommand("bd " + QByteArray::number(breakPointIdToCdbId(id)), 0); - handler->notifyBreakpointInsertProceeding(id); - handler->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertProceeding(); + bp.notifyBreakpointInsertOk(); m_pendingBreakpointMap.insert(id, response); addedChanged = true; // Ensure enabled/disabled is correct in handler and line number is there. - handler->setResponse(id, response); + bp.setResponse(response); if (debugBreakpoints) qDebug("Adding %d %s\n", id.toInternalId(), qPrintable(response.toString())); break; case BreakpointChangeRequested: - handler->notifyBreakpointChangeProceeding(id); + bp.notifyBreakpointChangeProceeding(); if (debugBreakpoints) qDebug("Changing %d:\n %s\nTo %s\n", id.toInternalId(), - qPrintable(handler->response(id).toString()), + qPrintable(bp.response().toString()), qPrintable(parameters.toString())); - if (parameters.enabled != handler->response(id).enabled) { + if (parameters.enabled != bp.response().enabled) { // Change enabled/disabled breakpoints without triggering update. postCommand((parameters.enabled ? "be " : "bd ") + QByteArray::number(breakPointIdToCdbId(id)), 0); response.pending = false; response.enabled = parameters.enabled; - handler->setResponse(id, response); + bp.setResponse(response); } else { // Delete and re-add, triggering update addedChanged = true; @@ -2942,12 +2942,12 @@ void CdbEngine::attemptBreakpointSynchronization() &CdbEngine::handleBreakInsert); m_pendingBreakpointMap.insert(id, response); } - handler->notifyBreakpointChangeOk(id); + bp.notifyBreakpointChangeOk(); break; case BreakpointRemoveRequested: postCommand(cdbClearBreakpointCommand(id), 0); - handler->notifyBreakpointRemoveProceeding(id); - handler->notifyBreakpointRemoveOk(id); + bp.notifyBreakpointRemoveProceeding(); + bp.notifyBreakpointRemoveOk(); m_pendingBreakpointMap.remove(id); break; default: @@ -3290,12 +3290,12 @@ void CdbEngine::handleBreakPoints(const GdbMi &value) reportedResponse.pending, qPrintable(reportedResponse.toString())); if (reportedResponse.id.isValid() && !reportedResponse.pending) { - const BreakpointModelId mid = handler->findBreakpointByResponseId(reportedResponse.id); - if (!mid.isValid() && reportedResponse.type == BreakpointByFunction) + Breakpoint bp = handler->findBreakpointByResponseId(reportedResponse.id); + if (!bp && reportedResponse.type == BreakpointByFunction) continue; // Breakpoints from options, CrtDbgReport() and others. - QTC_ASSERT(mid.isValid(), continue); - const PendingBreakPointMap::iterator it = m_pendingBreakpointMap.find(mid); - const PendingBreakPointMap::iterator subIt = m_pendingSubBreakpointMap.find( + QTC_ASSERT(bp, continue); + const auto it = m_pendingBreakpointMap.find(bp.id()); + const auto subIt = m_pendingSubBreakpointMap.find( BreakpointModelId(reportedResponse.id.majorPart(), reportedResponse.id.minorPart())); if (it != m_pendingBreakpointMap.end() || subIt != m_pendingSubBreakpointMap.end()) { @@ -3310,16 +3310,16 @@ void CdbEngine::handleBreakPoints(const GdbMi &value) currentResponse.enabled = reportedResponse.enabled; currentResponse.fileName = reportedResponse.fileName; currentResponse.lineNumber = reportedResponse.lineNumber; - formatCdbBreakPointResponse(mid, currentResponse, str); + formatCdbBreakPointResponse(bp.id(), currentResponse, str); if (debugBreakpoints) qDebug(" Setting for %d: %s\n", currentResponse.id.majorPart(), qPrintable(currentResponse.toString())); if (it != m_pendingBreakpointMap.end()) { - handler->setResponse(mid, currentResponse); + bp.setResponse(currentResponse); m_pendingBreakpointMap.erase(it); } if (subIt != m_pendingSubBreakpointMap.end()) { - handler->insertSubBreakpoint(mid, currentResponse); + bp.insertSubBreakpoint(currentResponse); m_pendingSubBreakpointMap.erase(subIt); } } diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index b8e6dc38f6..b63bb5d610 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -32,6 +32,7 @@ #define DEBUGGER_CDBENGINE_H #include <debugger/debuggerengine.h> +#include <debugger/breakhandler.h> #include <projectexplorer/devicesupport/idevice.h> @@ -111,7 +112,7 @@ public: virtual void selectThread(ThreadId threadId); virtual bool stateAcceptsBreakpointChanges() const; - virtual bool acceptsBreakpoint(BreakpointModelId id) const; + virtual bool acceptsBreakpoint(Breakpoint bp) const; virtual void attemptBreakpointSynchronization(); virtual void fetchDisassembler(DisassemblerAgent *agent); diff --git a/src/plugins/debugger/debuggerengine.cpp b/src/plugins/debugger/debuggerengine.cpp index 78df0bdfa1..801abef5a7 100644 --- a/src/plugins/debugger/debuggerengine.cpp +++ b/src/plugins/debugger/debuggerengine.cpp @@ -1206,9 +1206,8 @@ void DebuggerEngine::setState(DebuggerState state, bool forced) if (state == DebuggerFinished) { // Give up ownership on claimed breakpoints. - BreakHandler *handler = breakHandler(); - foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) - handler->notifyBreakpointReleased(id); + foreach (Breakpoint bp, breakHandler()->engineBreakpoints(this)) + bp.notifyBreakpointReleased(); DebuggerToolTipManager::deregisterEngine(this); } @@ -1499,36 +1498,36 @@ void DebuggerEngine::attemptBreakpointSynchronization() BreakHandler *handler = breakHandler(); - foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { + foreach (Breakpoint bp, handler->unclaimedBreakpoints()) { // Take ownership of the breakpoint. Requests insertion. - if (acceptsBreakpoint(id)) { + if (acceptsBreakpoint(bp)) { showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2") - .arg(id.toString()).arg(handler->state(id))); - handler->setEngine(id, this); + .arg(bp.id().toString()).arg(bp.state())); + bp.setEngine(this); } else { showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE") - .arg(id.toString()).arg(handler->state(id))); + .arg(bp.id().toString()).arg(bp.state())); } } bool done = true; - foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) { - switch (handler->state(id)) { + foreach (Breakpoint bp, handler->engineBreakpoints(this)) { + switch (bp.state()) { case BreakpointNew: // Should not happen once claimed. QTC_CHECK(false); continue; case BreakpointInsertRequested: done = false; - insertBreakpoint(id); + insertBreakpoint(bp); continue; case BreakpointChangeRequested: done = false; - changeBreakpoint(id); + changeBreakpoint(bp); continue; case BreakpointRemoveRequested: done = false; - removeBreakpoint(id); + removeBreakpoint(bp); continue; case BreakpointChangeProceeding: case BreakpointInsertProceeding: @@ -1545,7 +1544,7 @@ void DebuggerEngine::attemptBreakpointSynchronization() QTC_CHECK(false); continue; } - QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); + QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << bp.id() << state()); } if (done) { @@ -1556,24 +1555,33 @@ void DebuggerEngine::attemptBreakpointSynchronization() } } -void DebuggerEngine::insertBreakpoint(BreakpointModelId id) +bool DebuggerEngine::acceptsBreakpoint(Breakpoint bp) const { - BreakpointState state = breakHandler()->state(id); - QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << id << this << state); + Q_UNUSED(bp); + return false; +} + +void DebuggerEngine::insertBreakpoint(Breakpoint bp) +{ + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointInsertRequested, + qDebug() << bp.id() << this << state); QTC_CHECK(false); } -void DebuggerEngine::removeBreakpoint(BreakpointModelId id) +void DebuggerEngine::removeBreakpoint(Breakpoint bp) { - BreakpointState state = breakHandler()->state(id); - QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << id << this << state); + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointRemoveRequested, + qDebug() << bp.id() << this << state); QTC_CHECK(false); } -void DebuggerEngine::changeBreakpoint(BreakpointModelId id) +void DebuggerEngine::changeBreakpoint(Breakpoint bp) { - BreakpointState state = breakHandler()->state(id); - QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << id << this << state); + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointChangeRequested, + qDebug() << bp.id() << this << state); QTC_CHECK(false); } @@ -1652,56 +1660,6 @@ bool DebuggerEngine::isDying() const return targetState() == DebuggerFinished; } -QString DebuggerEngine::msgWatchpointByExpressionTriggered(BreakpointModelId id, - const int number, const QString &expr) -{ - return id - ? tr("Data breakpoint %1 (%2) at %3 triggered.") - .arg(id.toString()).arg(number).arg(expr) - : tr("Internal data breakpoint %1 at %2 triggered.") - .arg(number).arg(expr); -} - -QString DebuggerEngine::msgWatchpointByExpressionTriggered(BreakpointModelId id, - const int number, const QString &expr, const QString &threadId) -{ - return id - ? tr("Data breakpoint %1 (%2) at %3 in thread %4 triggered.") - .arg(id.toString()).arg(number).arg(expr).arg(threadId) - : tr("Internal data breakpoint %1 at %2 in thread %3 triggered.") - .arg(number).arg(expr).arg(threadId); -} - -QString DebuggerEngine::msgWatchpointByAddressTriggered(BreakpointModelId id, - const int number, quint64 address) -{ - return id - ? tr("Data breakpoint %1 (%2) at 0x%3 triggered.") - .arg(id.toString()).arg(number).arg(address, 0, 16) - : tr("Internal data breakpoint %1 at 0x%2 triggered.") - .arg(number).arg(address, 0, 16); -} - -QString DebuggerEngine::msgWatchpointByAddressTriggered(BreakpointModelId id, - const int number, quint64 address, const QString &threadId) -{ - return id - ? tr("Data breakpoint %1 (%2) at 0x%3 in thread %4 triggered.") - .arg(id.toString()).arg(number).arg(address, 0, 16).arg(threadId) - : tr("Internal data breakpoint %1 at 0x%2 in thread %3 triggered.") - .arg(id.toString()).arg(number).arg(address, 0, 16).arg(threadId); -} - -QString DebuggerEngine::msgBreakpointTriggered(BreakpointModelId id, - const int number, const QString &threadId) -{ - return id - ? tr("Stopped at breakpoint %1 (%2) in thread %3.") - .arg(id.toString()).arg(number).arg(threadId) - : tr("Stopped at internal breakpoint %1 in thread %2.") - .arg(number).arg(threadId); -} - QString DebuggerEngine::msgStopped(const QString &reason) { return reason.isEmpty() ? tr("Stopped.") : tr("Stopped: \"%1\"").arg(reason); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index 81197569e6..f5d06c7d4e 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -34,7 +34,6 @@ #include "debugger_global.h" #include "debuggerconstants.h" #include "debuggerstartparameters.h" -#include "breakpoint.h" // For BreakpointModelId. #include "threaddata.h" // For ThreadId. #include <QObject> @@ -71,7 +70,7 @@ class StackFrame; class SourceFilesHandler; class ThreadsHandler; class WatchHandler; -class BreakpointParameters; +class Breakpoint; class QmlAdapter; class QmlCppEngine; class DebuggerToolTipContext; @@ -193,13 +192,12 @@ public: virtual void createSnapshot(); virtual void updateAll(); - typedef Internal::BreakpointModelId BreakpointModelId; virtual bool stateAcceptsBreakpointChanges() const { return true; } virtual void attemptBreakpointSynchronization(); - virtual bool acceptsBreakpoint(BreakpointModelId id) const = 0; - virtual void insertBreakpoint(BreakpointModelId id); // FIXME: make pure - virtual void removeBreakpoint(BreakpointModelId id); // FIXME: make pure - virtual void changeBreakpoint(BreakpointModelId id); // FIXME: make pure + virtual bool acceptsBreakpoint(Breakpoint bp) const = 0; + virtual void insertBreakpoint(Breakpoint bp); // FIXME: make pure + virtual void removeBreakpoint(Breakpoint bp); // FIXME: make pure + virtual void changeBreakpoint(Breakpoint bp); // FIXME: make pure virtual bool acceptsDebuggerCommands() const { return true; } virtual void executeDebuggerCommand(const QString &command, DebuggerLanguages languages); @@ -355,16 +353,6 @@ protected: DebuggerRunControl *runControl() const; - static QString msgWatchpointByAddressTriggered(BreakpointModelId id, - int number, quint64 address); - static QString msgWatchpointByAddressTriggered(BreakpointModelId id, - int number, quint64 address, const QString &threadId); - static QString msgWatchpointByExpressionTriggered(BreakpointModelId id, - int number, const QString &expr); - static QString msgWatchpointByExpressionTriggered(BreakpointModelId id, - int number, const QString &expr, const QString &threadId); - static QString msgBreakpointTriggered(BreakpointModelId id, - int number, const QString &threadId); static QString msgStopped(const QString &reason = QString()); static QString msgStoppedBySignal(const QString &meaning, const QString &name); static QString msgStoppedByException(const QString &description, diff --git a/src/plugins/debugger/debuggerplugin.cpp b/src/plugins/debugger/debuggerplugin.cpp index 715ae0bc2f..83d8d7440c 100644 --- a/src/plugins/debugger/debuggerplugin.cpp +++ b/src/plugins/debugger/debuggerplugin.cpp @@ -389,19 +389,6 @@ namespace PE = ProjectExplorer::Constants; namespace Debugger { namespace Internal { -// To be passed through margin menu action's data -struct BreakpointMenuContextData : public ContextData -{ - enum Mode - { - Breakpoint, - MessageTracePoint - }; - - BreakpointMenuContextData() : mode(Breakpoint) {} - Mode mode; -}; - struct TestCallBack { TestCallBack() : receiver(0), slot(0) {} @@ -416,7 +403,6 @@ struct TestCallBack } // namespace Internal } // namespace Debugger -Q_DECLARE_METATYPE(Debugger::Internal::BreakpointMenuContextData) Q_DECLARE_METATYPE(Debugger::Internal::TestCallBack) namespace Debugger { @@ -450,8 +436,6 @@ static QToolButton *toolButton(Core::Id id) class DummyEngine : public DebuggerEngine { - Q_OBJECT - public: DummyEngine() : DebuggerEngine(DebuggerStartParameters()) {} ~DummyEngine() {} @@ -462,7 +446,7 @@ public: void shutdownEngine() {} void shutdownInferior() {} bool hasCapability(unsigned cap) const; - bool acceptsBreakpoint(BreakpointModelId) const { return false; } + bool acceptsBreakpoint(Breakpoint) const { return false; } bool acceptsDebuggerCommands() const { return false; } void selectThread(ThreadId) {} }; @@ -641,14 +625,10 @@ public: m_currentEngine->selectThread(id); } - void breakpointSetMarginActionTriggered() + void breakpointSetMarginActionTriggered(bool isMessageOnly, const ContextData &data) { - const QAction *action = qobject_cast<const QAction *>(sender()); - QTC_ASSERT(action, return); - const BreakpointMenuContextData data = - action->data().value<BreakpointMenuContextData>(); QString message; - if (data.mode == BreakpointMenuContextData::MessageTracePoint) { + if (isMessageOnly) { if (data.address) { //: Message tracepoint: Address hit. message = tr("0x%1 hit").arg(data.address, 0, 16); @@ -675,30 +655,6 @@ public: toggleBreakpointByFileAndLine(data.fileName, data.lineNumber, message); } - void breakpointRemoveMarginActionTriggered() - { - const QAction *act = qobject_cast<QAction *>(sender()); - QTC_ASSERT(act, return); - BreakpointModelId id = act->data().value<BreakpointModelId>(); - m_breakHandler->removeBreakpoint(id); - } - - void breakpointEnableMarginActionTriggered() - { - const QAction *act = qobject_cast<QAction *>(sender()); - QTC_ASSERT(act, return); - BreakpointModelId id = act->data().value<BreakpointModelId>(); - breakHandler()->setEnabled(id, true); - } - - void breakpointDisableMarginActionTriggered() - { - const QAction *act = qobject_cast<QAction *>(sender()); - QTC_ASSERT(act, return); - BreakpointModelId id = act->data().value<BreakpointModelId>(); - breakHandler()->setEnabled(id, false); - } - void updateWatchersHeader(int section, int, int newSize) { m_watchersView->header()->resizeSection(section, newSize); @@ -946,31 +902,6 @@ public slots: } } - void slotEditBreakpoint() - { - const QAction *act = qobject_cast<QAction *>(sender()); - QTC_ASSERT(act, return); - const BreakpointModelId id = act->data().value<BreakpointModelId>(); - QTC_ASSERT(id > 0, return); - BreakTreeView::editBreakpoint(id, ICore::dialogParent()); - } - - void slotRunToLine() - { - const QAction *action = qobject_cast<const QAction *>(sender()); - QTC_ASSERT(action, return); - const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>(); - currentEngine()->executeRunToLine(data); - } - - void slotJumpToLine() - { - const QAction *action = qobject_cast<const QAction *>(sender()); - QTC_ASSERT(action, return); - const BreakpointMenuContextData data = action->data().value<BreakpointMenuContextData>(); - currentEngine()->executeJumpToLine(data); - } - void slotDisassembleFunction() { const QAction *action = qobject_cast<const QAction *>(sender()); @@ -1716,11 +1647,11 @@ void DebuggerPluginPrivate::updateBreakMenuItem(IEditor *editor) void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget, int lineNumber, QMenu *menu) { - BreakpointMenuContextData args; + ContextData args; args.lineNumber = lineNumber; bool contextUsable = true; - BreakpointModelId id = BreakpointModelId(); + Breakpoint bp; TextDocument *document = widget->textDocument(); args.fileName = document->filePath().toString(); if (document->property(Constants::OPENED_WITH_DISASSEMBLY).toBool()) { @@ -1731,87 +1662,77 @@ void DebuggerPluginPrivate::requestContextMenu(TextEditorWidget *widget, needle.address = DisassemblerLine::addressFromDisassemblyLine(line); args.address = needle.address; needle.lineNumber = -1; - id = breakHandler()->findSimilarBreakpoint(needle); + bp = breakHandler()->findSimilarBreakpoint(needle); contextUsable = args.address != 0; } else { - id = breakHandler() + bp = breakHandler() ->findBreakpointByFileAndLine(args.fileName, lineNumber); - if (!id) - id = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber, false); + if (!bp) + bp = breakHandler()->findBreakpointByFileAndLine(args.fileName, lineNumber, false); } - if (id) { + if (bp) { + QString id = bp.id().toString(); + // Remove existing breakpoint. - QAction *act = new QAction(menu); - act->setData(QVariant::fromValue(id)); - act->setText(tr("Remove Breakpoint %1").arg(id.toString())); - connect(act, &QAction::triggered, - this, &DebuggerPluginPrivate::breakpointRemoveMarginActionTriggered); - menu->addAction(act); + auto act = menu->addAction(tr("Remove Breakpoint %1").arg(id)); + connect(act, &QAction::triggered, [bp] { bp.removeBreakpoint(); }); // Enable/disable existing breakpoint. - act = new QAction(menu); - act->setData(QVariant::fromValue(id)); - if (breakHandler()->isEnabled(id)) { - act->setText(tr("Disable Breakpoint %1").arg(id.toString())); - connect(act, &QAction::triggered, - this, &DebuggerPluginPrivate::breakpointDisableMarginActionTriggered); + if (bp.isEnabled()) { + act = menu->addAction(tr("Disable Breakpoint %1").arg(id)); + connect(act, &QAction::triggered, [bp] { bp.setEnabled(false); }); } else { - act->setText(tr("Enable Breakpoint %1").arg(id.toString())); - connect(act, &QAction::triggered, - this, &DebuggerPluginPrivate::breakpointEnableMarginActionTriggered); + act = menu->addAction(tr("Enable Breakpoint %1").arg(id)); + connect(act, &QAction::triggered, [bp] { bp.setEnabled(true); }); } - menu->addAction(act); // Edit existing breakpoint. - act = new QAction(menu); - act->setText(tr("Edit Breakpoint %1...").arg(id.toString())); - connect(act, &QAction::triggered, this, &DebuggerPluginPrivate::slotEditBreakpoint); - act->setData(QVariant::fromValue(id)); - menu->addAction(act); + act = menu->addAction(tr("Edit Breakpoint %1...").arg(id)); + connect(act, &QAction::triggered, [bp] { + BreakTreeView::editBreakpoint(bp, ICore::dialogParent()); + }); + } else { // Handle non-existing breakpoint. const QString text = args.address ? tr("Set Breakpoint at 0x%1").arg(args.address, 0, 16) : tr("Set Breakpoint at Line %1").arg(lineNumber); - QAction *act = new QAction(text, menu); - act->setData(QVariant::fromValue(args)); + auto act = menu->addAction(text); act->setEnabled(contextUsable); - connect(act, &QAction::triggered, - this, &DebuggerPluginPrivate::breakpointSetMarginActionTriggered); - menu->addAction(act); + connect(act, &QAction::triggered, [this, args] { + breakpointSetMarginActionTriggered(false, args); + }); + // Message trace point - args.mode = BreakpointMenuContextData::MessageTracePoint; const QString tracePointText = args.address ? tr("Set Message Tracepoint at 0x%1...").arg(args.address, 0, 16) : tr("Set Message Tracepoint at Line %1...").arg(lineNumber); - act = new QAction(tracePointText, menu); - act->setData(QVariant::fromValue(args)); + act = menu->addAction(tracePointText); act->setEnabled(contextUsable); - connect(act, &QAction::triggered, - this, &DebuggerPluginPrivate::breakpointSetMarginActionTriggered); - menu->addAction(act); + connect(act, &QAction::triggered, [this, args] { + breakpointSetMarginActionTriggered(true, args); + }); } + // Run to, jump to line below in stopped state. if (currentEngine()->state() == InferiorStopOk && contextUsable) { menu->addSeparator(); if (currentEngine()->hasCapability(RunToLineCapability)) { - const QString runText = args.address + auto act = menu->addAction(args.address ? DebuggerEngine::tr("Run to Address 0x%1").arg(args.address, 0, 16) - : DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber); - QAction *runToLineAction = new QAction(runText, menu); - runToLineAction->setData(QVariant::fromValue(args)); - connect(runToLineAction, &QAction::triggered, this, &DebuggerPluginPrivate::slotRunToLine); - menu->addAction(runToLineAction); + : DebuggerEngine::tr("Run to Line %1").arg(args.lineNumber)); + connect(act, &QAction::triggered, [this, args] { + currentEngine()->executeRunToLine(args); + }); } if (currentEngine()->hasCapability(JumpToLineCapability)) { - const QString jumpText = args.address + auto act = menu->addAction(args.address ? DebuggerEngine::tr("Jump to Address 0x%1").arg(args.address, 0, 16) - : DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber); - QAction *jumpToLineAction = new QAction(jumpText, menu); - jumpToLineAction->setData(QVariant::fromValue(args)); - connect(jumpToLineAction, &QAction::triggered, this, &DebuggerPluginPrivate::slotJumpToLine); - menu->addAction(jumpToLineAction); + : DebuggerEngine::tr("Jump to Line %1").arg(args.lineNumber)); + connect(act, &QAction::triggered, [this, args] { + currentEngine()->executeJumpToLine(args); + }); } // Disassemble current function in stopped state. if (currentEngine()->state() == InferiorStopOk @@ -1850,13 +1771,12 @@ void DebuggerPluginPrivate::toggleBreakpointByFileAndLine(const QString &fileNam int lineNumber, const QString &tracePointMessage) { BreakHandler *handler = m_breakHandler; - BreakpointModelId id = - handler->findBreakpointByFileAndLine(fileName, lineNumber, true); - if (!id) - id = handler->findBreakpointByFileAndLine(fileName, lineNumber, false); + Breakpoint bp = handler->findBreakpointByFileAndLine(fileName, lineNumber, true); + if (!bp) + bp = handler->findBreakpointByFileAndLine(fileName, lineNumber, false); - if (id) { - handler->removeBreakpoint(id); + if (bp) { + bp.removeBreakpoint(); } else { BreakpointParameters data(BreakpointByFileAndLine); if (boolSetting(BreakpointsFullPathByDefault)) @@ -1873,10 +1793,8 @@ void DebuggerPluginPrivate::toggleBreakpointByAddress(quint64 address, const QString &tracePointMessage) { BreakHandler *handler = m_breakHandler; - BreakpointModelId id = handler->findBreakpointByAddress(address); - - if (id) { - handler->removeBreakpoint(id); + if (Breakpoint bp = handler->findBreakpointByAddress(address)) { + bp.removeBreakpoint(); } else { BreakpointParameters data(BreakpointByAddress); data.tracepoint = !tracePointMessage.isEmpty(); diff --git a/src/plugins/debugger/debuggerruncontrol.cpp b/src/plugins/debugger/debuggerruncontrol.cpp index d6d1b8081c..7d4ac51874 100644 --- a/src/plugins/debugger/debuggerruncontrol.cpp +++ b/src/plugins/debugger/debuggerruncontrol.cpp @@ -148,10 +148,9 @@ void DebuggerRunControl::start() if (m_engine->startParameters().startMode == StartInternal) { QStringList unhandledIds; - foreach (const BreakpointModelId &id, breakHandler()->allBreakpointIds()) { - if (m_engine->breakHandler()->breakpointData(id).enabled - && !m_engine->acceptsBreakpoint(id)) - unhandledIds.append(id.toString()); + foreach (Breakpoint bp, breakHandler()->allBreakpoints()) { + if (bp.isEnabled() && !m_engine->acceptsBreakpoint(bp)) + unhandledIds.append(bp.id().toString()); } if (!unhandledIds.isEmpty()) { QString warningMessage = diff --git a/src/plugins/debugger/disassembleragent.cpp b/src/plugins/debugger/disassembleragent.cpp index 0b74ef4ce8..32cac854aa 100644 --- a/src/plugins/debugger/disassembleragent.cpp +++ b/src/plugins/debugger/disassembleragent.cpp @@ -332,9 +332,8 @@ void DisassemblerAgent::updateBreakpointMarkers() if (!d->document) return; - BreakHandler *handler = breakHandler(); - BreakpointModelIds ids = handler->engineBreakpointIds(d->engine); - if (ids.isEmpty()) + Breakpoints bps = breakHandler()->engineBreakpoints(d->engine); + if (bps.isEmpty()) return; const DisassemblerLines contents = d->contentsAtCurrentLocation(); @@ -342,15 +341,15 @@ void DisassemblerAgent::updateBreakpointMarkers() d->document->removeMark(marker); qDeleteAll(d->breakpointMarks); d->breakpointMarks.clear(); - foreach (BreakpointModelId id, ids) { - const quint64 address = handler->response(id).address; + foreach (Breakpoint bp, bps) { + const quint64 address = bp.response().address; if (!address) continue; const int lineNumber = contents.lineForAddress(address); if (!lineNumber) continue; TextMark *marker = new TextMark(QString(), lineNumber); - marker->setIcon(handler->icon(id)); + marker->setIcon(bp.icon()); marker->setPriority(TextMark::NormalPriority); d->breakpointMarks.append(marker); d->document->addMark(marker); diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 1231a65070..1141c85943 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -534,7 +534,7 @@ void GdbEngine::handleResponse(const QByteArray &buff) result = GdbMi(); result.fromString(ba); BreakHandler *handler = breakHandler(); - BreakpointModelId id; + Breakpoint bp; BreakpointResponse br; foreach (const GdbMi &bkpt, result.children()) { const QByteArray nr = bkpt["number"].data(); @@ -546,17 +546,15 @@ void GdbEngine::handleResponse(const QByteArray &buff) updateResponse(sub, bkpt); sub.id = rid; sub.type = br.type; - handler->insertSubBreakpoint(id, sub); + bp.insertSubBreakpoint(sub); } else { // A primary breakpoint. - id = handler->findBreakpointByResponseId(rid); + bp = handler->findBreakpointByResponseId(rid); //qDebug() << "NR: " << nr << "RID: " << rid - // << "ID: " << id; - //BreakpointModelId id = - // handler->findBreakpointByResponseId(rid); - br = handler->response(id); + // << "ID: " << bp.id(); + br = bp.response(); updateResponse(br, bkpt); - handler->setResponse(id, br); + bp.setResponse(br); } } } @@ -576,16 +574,14 @@ void GdbEngine::handleResponse(const QByteArray &buff) } else if (asyncClass == "breakpoint-deleted") { // "breakpoint-deleted" "{id="1"}" // New in FSF gdb since 2011-04-27. - BreakHandler *handler = breakHandler(); QByteArray nr = result["id"].data(); BreakpointResponseId rid(nr); - BreakpointModelId id = handler->findBreakpointByResponseId(rid); - if (id.isValid()) { + if (Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid)) { // This also triggers when a temporary breakpoint is hit. // We do not really want that, as this loses all information. // FIXME: Use a special marker for this case? - if (!handler->isOneShot(id)) - handler->removeAlienBreakpoint(id); + if (!bp.isOneShot()) + bp.removeAlienBreakpoint(); } } else if (asyncClass == "cmd-param-changed") { // New since 2012-08-09 @@ -1397,19 +1393,18 @@ void GdbEngine::handleStopResponse(const GdbMi &data) if (rid.isValid() && frame.isValid() && !isQFatalBreakpoint(rid)) { // Use opportunity to update the breakpoint marker position. - BreakHandler *handler = breakHandler(); //qDebug() << " PROBLEM: " << m_qmlBreakpointNumbers << rid // << isQmlStepBreakpoint1(rid) // << isQmlStepBreakpoint2(rid) - BreakpointModelId id = handler->findBreakpointByResponseId(rid); - const BreakpointResponse &response = handler->response(id); + Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid); + const BreakpointResponse &response = bp.response(); QString fileName = response.fileName; if (fileName.isEmpty()) - fileName = handler->fileName(id); + fileName = bp.fileName(); if (fileName.isEmpty()) fileName = fullName; if (!fileName.isEmpty()) - handler->setMarkerFileAndLine(id, fileName, lineNumber); + bp.setMarkerFileAndLine(fileName, lineNumber); } //qDebug() << "BP " << rid << data.toString(); @@ -1615,14 +1610,13 @@ void GdbEngine::handleStop2(const GdbMi &data) // thread-id="1",stopped-threads="all",core="2" const GdbMi wpt = data["wpt"]; const BreakpointResponseId rid(wpt["number"].data()); - const BreakpointModelId id = breakHandler()->findBreakpointByResponseId(rid); + const Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid); const quint64 bpAddress = wpt["exp"].data().mid(1).toULongLong(0, 0); QString msg; - if (id && breakHandler()->type(id) == WatchpointAtExpression) - msg = msgWatchpointByExpressionTriggered(id, rid.majorPart(), - breakHandler()->expression(id)); - if (id && breakHandler()->type(id) == WatchpointAtAddress) - msg = msgWatchpointByAddressTriggered(id, rid.majorPart(), bpAddress); + if (bp.type() == WatchpointAtExpression) + msg = bp.msgWatchpointByExpressionTriggered(rid.majorPart(), bp.expression()); + if (bp.type() == WatchpointAtAddress) + msg = bp.msgWatchpointByAddressTriggered(rid.majorPart(), bpAddress); GdbMi value = data["value"]; GdbMi oldValue = value["old"]; GdbMi newValue = value["new"]; @@ -1638,8 +1632,8 @@ void GdbEngine::handleStop2(const GdbMi &data) gNumber = data["number"]; const BreakpointResponseId rid(gNumber.data()); const QByteArray threadId = data["thread-id"].data(); - const BreakpointModelId id = breakHandler()->findBreakpointByResponseId(rid); - showStatusMessage(msgBreakpointTriggered(id, rid.majorPart(), _(threadId))); + const Breakpoint bp = breakHandler()->findBreakpointByResponseId(rid); + showStatusMessage(bp.msgBreakpointTriggered(rid.majorPart(), _(threadId))); m_currentThread = threadId; } else { QString reasontr = msgStopped(_(reason)); @@ -2449,10 +2443,8 @@ QString GdbEngine::breakLocation(const QString &file) const return where; } -QByteArray GdbEngine::breakpointLocation(BreakpointModelId id) +QByteArray GdbEngine::breakpointLocation(const BreakpointParameters &data) { - BreakHandler *handler = breakHandler(); - const BreakpointParameters &data = handler->breakpointData(id); QTC_ASSERT(data.type != UnknownBreakpointType, return QByteArray()); // FIXME: Non-GCC-runtime if (data.type == BreakpointAtThrow) @@ -2480,12 +2472,8 @@ QByteArray GdbEngine::breakpointLocation(BreakpointModelId id) + QByteArray::number(data.lineNumber) + '"'; } -QByteArray GdbEngine::breakpointLocation2(BreakpointModelId id) +QByteArray GdbEngine::breakpointLocation2(const BreakpointParameters &data) { - BreakHandler *handler = breakHandler(); - - const BreakpointParameters &data = handler->breakpointData(id); - BreakpointPathUsage usage = data.pathUsage; if (usage == BreakpointPathUsageEngineDefault) usage = BreakpointUseShortPath; @@ -2498,10 +2486,9 @@ QByteArray GdbEngine::breakpointLocation2(BreakpointModelId id) void GdbEngine::handleWatchInsert(const GdbResponse &response) { - BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - if (response.resultClass == GdbResultDone) { - BreakHandler *handler = breakHandler(); - BreakpointResponse br = handler->response(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + if (bp && response.resultClass == GdbResultDone) { + BreakpointResponse br = bp.response(); // "Hardware watchpoint 2: *0xbfffed40\n" QByteArray ba = response.consoleStreamOutput; GdbMi wpt = response.data["wpt"]; @@ -2512,9 +2499,9 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response) QByteArray exp = wpt["exp"].data(); if (exp.startsWith('*')) br.address = exp.mid(1).toULongLong(0, 0); - handler->setResponse(id, br); - QTC_CHECK(!handler->needsChange(id)); - handler->notifyBreakpointInsertOk(id); + bp.setResponse(br); + QTC_CHECK(!bp.needsChange()); + bp.notifyBreakpointInsertOk(); } else if (ba.startsWith("Hardware watchpoint ") || ba.startsWith("Watchpoint ")) { // Non-Mac: "Hardware watchpoint 2: *0xbfffed40\n" @@ -2524,9 +2511,9 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response) br.id = BreakpointResponseId(ba.mid(begin, end - begin)); if (address.startsWith('*')) br.address = address.mid(1).toULongLong(0, 0); - handler->setResponse(id, br); - QTC_CHECK(!handler->needsChange(id)); - handler->notifyBreakpointInsertOk(id); + bp.setResponse(br); + QTC_CHECK(!bp.needsChange()); + bp.notifyBreakpointInsertOk(); } else { showMessage(_("CANNOT PARSE WATCHPOINT FROM " + ba)); } @@ -2535,16 +2522,15 @@ void GdbEngine::handleWatchInsert(const GdbResponse &response) void GdbEngine::handleCatchInsert(const GdbResponse &response) { - BreakHandler *handler = breakHandler(); - BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - if (response.resultClass == GdbResultDone) - handler->notifyBreakpointInsertOk(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + if (bp && response.resultClass == GdbResultDone) + bp.notifyBreakpointInsertOk(); } -void GdbEngine::handleBkpt(const GdbMi &bkpt, const BreakpointModelId &id) +void GdbEngine::handleBkpt(const GdbMi &bkpt, Breakpoint bp) { - BreakHandler *handler = breakHandler(); - BreakpointResponse br = handler->response(id); + BreakpointResponse br = bp.response(); + QTC_ASSERT(bp, return); const QByteArray nr = bkpt["number"].data(); const BreakpointResponseId rid(nr); QTC_ASSERT(rid.isValid(), return); @@ -2553,8 +2539,8 @@ void GdbEngine::handleBkpt(const GdbMi &bkpt, const BreakpointModelId &id) BreakpointResponse sub; updateResponse(sub, bkpt); sub.id = rid; - sub.type = br.type; - handler->insertSubBreakpoint(id, sub); + sub.type = bp.type(); + bp.insertSubBreakpoint(sub); return; } @@ -2570,29 +2556,28 @@ void GdbEngine::handleBkpt(const GdbMi &bkpt, const BreakpointModelId &id) updateResponse(sub, loc); sub.id = subrid; sub.type = br.type; - handler->insertSubBreakpoint(id, sub); + bp.insertSubBreakpoint(sub); } } // A (the?) primary breakpoint. updateResponse(br, bkpt); br.id = rid; - handler->setResponse(id, br); + bp.setResponse(br); } void GdbEngine::handleBreakInsert1(const GdbResponse &response) { - BreakHandler *handler = breakHandler(); - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - if (handler->state(id) == BreakpointRemoveRequested) { + Breakpoint bp = response.cookie.value<Breakpoint>(); + if (bp.state() == BreakpointRemoveRequested) { if (response.resultClass == GdbResultDone) { // This delete was deferred. Act now. const GdbMi mainbkpt = response.data["bkpt"]; - handler->notifyBreakpointRemoveProceeding(id); + bp.notifyBreakpointRemoveProceeding(); QByteArray nr = mainbkpt["number"].data(); postCommand("-break-delete " + nr, NeedsStop | RebuildBreakpointModel); - handler->notifyBreakpointRemoveOk(id); + bp.notifyBreakpointRemoveOk(); return; } } @@ -2607,19 +2592,19 @@ void GdbEngine::handleBreakInsert1(const GdbResponse &response) const BreakpointResponseId mainrid(mainnr); if (!isHiddenBreakpoint(mainrid)) { foreach (const GdbMi &bkpt, response.data.children()) - handleBkpt(bkpt, id); - if (handler->needsChange(id)) { - handler->notifyBreakpointChangeAfterInsertNeeded(id); - changeBreakpoint(id); + handleBkpt(bkpt, bp); + if (bp.needsChange()) { + bp.notifyBreakpointChangeAfterInsertNeeded(); + changeBreakpoint(bp); } else { - handler->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertOk(); } } } else if (response.data["msg"].data().contains("Unknown option")) { // Older version of gdb don't know the -a option to set tracepoints // ^error,msg="mi_cmd_break_insert: Unknown option ``a''" - const QString fileName = handler->fileName(id); - const int lineNumber = handler->lineNumber(id); + const QString fileName = bp.fileName(); + const int lineNumber = bp.lineNumber(); QByteArray cmd = "trace " "\"" + GdbMi::escapeCString(fileName.toLocal8Bit()) + "\":" + QByteArray::number(lineNumber); @@ -2628,18 +2613,18 @@ void GdbEngine::handleBreakInsert1(const GdbResponse &response) // Some versions of gdb like "GNU gdb (GDB) SUSE (6.8.91.20090930-2.4)" // know how to do pending breakpoints using CLI but not MI. So try // again with MI. - QByteArray cmd = "break " + breakpointLocation2(id); - QVariant vid = QVariant::fromValue(id); + QByteArray cmd = "break " + breakpointLocation2(bp.parameters()); postCommand(cmd, NeedsStop | RebuildBreakpointModel, - CB(handleBreakInsert2), vid); + CB(handleBreakInsert2), QVariant::fromValue(bp)); } } void GdbEngine::handleBreakInsert2(const GdbResponse &response) { if (response.resultClass == GdbResultDone) { - BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - breakHandler()->notifyBreakpointInsertOk(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + QTC_ASSERT(bp, return); + bp.notifyBreakpointInsertOk(); } else { // Note: gdb < 60800 doesn't "do" pending breakpoints. // Not much we can do about it except implementing the @@ -2651,51 +2636,47 @@ void GdbEngine::handleBreakInsert2(const GdbResponse &response) void GdbEngine::handleBreakDisable(const GdbResponse &response) { QTC_CHECK(response.resultClass == GdbResultDone); - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); + Breakpoint bp = response.cookie.value<Breakpoint>(); // This should only be the requested state. - QTC_ASSERT(!handler->isEnabled(id), /* Prevent later recursion */); - BreakpointResponse br = handler->response(id); + QTC_ASSERT(!bp.isEnabled(), /* Prevent later recursion */); + BreakpointResponse br = bp.response(); br.enabled = false; - handler->setResponse(id, br); - changeBreakpoint(id); // Maybe there's more to do. + bp.setResponse(br); + changeBreakpoint(bp); // Maybe there's more to do. } void GdbEngine::handleBreakEnable(const GdbResponse &response) { QTC_CHECK(response.resultClass == GdbResultDone); - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); + Breakpoint bp = response.cookie.value<Breakpoint>(); // This should only be the requested state. - QTC_ASSERT(handler->isEnabled(id), /* Prevent later recursion */); - BreakpointResponse br = handler->response(id); + QTC_ASSERT(bp.isEnabled(), /* Prevent later recursion */); + BreakpointResponse br = bp.response(); br.enabled = true; - handler->setResponse(id, br); - changeBreakpoint(id); // Maybe there's more to do. + bp.setResponse(br); + changeBreakpoint(bp); // Maybe there's more to do. } void GdbEngine::handleBreakThreadSpec(const GdbResponse &response) { QTC_CHECK(response.resultClass == GdbResultDone); - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); - BreakpointResponse br = handler->response(id); - br.threadSpec = handler->threadSpec(id); - handler->setResponse(id, br); - handler->notifyBreakpointNeedsReinsertion(id); - insertBreakpoint(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + BreakpointResponse br = bp.response(); + br.threadSpec = bp.threadSpec(); + bp.setResponse(br); + bp.notifyBreakpointNeedsReinsertion(); + insertBreakpoint(bp); } void GdbEngine::handleBreakLineNumber(const GdbResponse &response) { QTC_CHECK(response.resultClass == GdbResultDone); - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); - BreakpointResponse br = handler->response(id); - br.lineNumber = handler->lineNumber(id); - handler->setResponse(id, br); - handler->notifyBreakpointNeedsReinsertion(id); - insertBreakpoint(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + BreakpointResponse br = bp.response(); + br.lineNumber = bp.lineNumber(); + bp.setResponse(br); + bp.notifyBreakpointNeedsReinsertion(); + insertBreakpoint(bp); } void GdbEngine::handleBreakIgnore(const GdbResponse &response) @@ -2712,37 +2693,35 @@ void GdbEngine::handleBreakIgnore(const GdbResponse &response) // gdb 6.3 does not produce any console output QTC_CHECK(response.resultClass == GdbResultDone); //QString msg = _(response.consoleStreamOutput); - BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); - BreakpointResponse br = handler->response(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + BreakpointResponse br = bp.response(); //if (msg.contains(__("Will stop next time breakpoint"))) // response.ignoreCount = _("0"); //else if (msg.contains(__("Will ignore next"))) // response.ignoreCount = data->ignoreCount; // FIXME: this assumes it is doing the right thing... - const BreakpointParameters ¶meters = handler->breakpointData(id); + const BreakpointParameters ¶meters = bp.parameters(); br.ignoreCount = parameters.ignoreCount; br.command = parameters.command; - handler->setResponse(id, br); - changeBreakpoint(id); // Maybe there's more to do. + bp.setResponse(br); + changeBreakpoint(bp); // Maybe there's more to do. } void GdbEngine::handleBreakCondition(const GdbResponse &response) { // Can happen at invalid condition strings. //QTC_CHECK(response.resultClass == GdbResultDone) - const BreakpointModelId id = response.cookie.value<BreakpointModelId>(); - BreakHandler *handler = breakHandler(); + Breakpoint bp = response.cookie.value<Breakpoint>(); // We just assume it was successful. Otherwise we had to parse // the output stream data. // The following happens on Mac: // QByteArray msg = response.data.findChild("msg").data(); // if (msg.startsWith("Error parsing breakpoint condition. " // " Will try again when we hit the breakpoint.")) - BreakpointResponse br = handler->response(id); - br.condition = handler->condition(id); - handler->setResponse(id, br); - changeBreakpoint(id); // Maybe there's more to do. + BreakpointResponse br = bp.response(); + br.condition = bp.condition(); + bp.setResponse(br); + changeBreakpoint(bp); // Maybe there's more to do. } bool GdbEngine::stateAcceptsBreakpointChanges() const @@ -2759,42 +2738,42 @@ bool GdbEngine::stateAcceptsBreakpointChanges() const } } -bool GdbEngine::acceptsBreakpoint(BreakpointModelId id) const +bool GdbEngine::acceptsBreakpoint(Breakpoint bp) const { if (startParameters().startMode == AttachCore) return false; // We handle QML breakpoint unless specifically if (isNativeMixedEnabled() && !(startParameters().languages & QmlLanguage)) return true; - return breakHandler()->breakpointData(id).isCppBreakpoint(); + return bp.parameters().isCppBreakpoint(); } -void GdbEngine::insertBreakpoint(BreakpointModelId id) +void GdbEngine::insertBreakpoint(Breakpoint bp) { // Set up fallback in case of pending breakpoints which aren't handled // by the MI interface. - BreakHandler *handler = breakHandler(); - QTC_CHECK(handler->state(id) == BreakpointInsertRequested); - handler->notifyBreakpointInsertProceeding(id); + QTC_CHECK(bp.state() == BreakpointInsertRequested); + bp.notifyBreakpointInsertProceeding(); + + const BreakpointParameters &data = bp.parameters(); + QVariant vid = QVariant::fromValue(bp); - if (!handler->breakpointData(id).isCppBreakpoint()) { - const BreakpointParameters &data = handler->breakpointData(id); + if (!data.isCppBreakpoint()) { postCommand("insertQmlBreakpoint " + data.fileName.toUtf8() + ' ' + QByteArray::number(data.lineNumber)); - handler->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertOk(); return; } - BreakpointType type = handler->type(id); - QVariant vid = QVariant::fromValue(id); + BreakpointType type = bp.type(); if (type == WatchpointAtAddress) { - postCommand("watch " + addressSpec(handler->address(id)), + postCommand("watch " + addressSpec(bp.address()), NeedsStop | RebuildBreakpointModel | ConsoleCommand, CB(handleWatchInsert), vid); return; } if (type == WatchpointAtExpression) { - postCommand("watch " + handler->expression(id).toLocal8Bit(), + postCommand("watch " + bp.expression().toLocal8Bit(), NeedsStop | RebuildBreakpointModel | ConsoleCommand, CB(handleWatchInsert), vid); return; @@ -2827,48 +2806,47 @@ void GdbEngine::insertBreakpoint(BreakpointModelId id) } QByteArray cmd; - if (handler->isTracepoint(id)) { + if (bp.isTracepoint()) { cmd = "-break-insert -a -f "; } else { - int spec = handler->threadSpec(id); + int spec = bp.threadSpec(); cmd = "-break-insert "; if (spec >= 0) cmd += "-p " + QByteArray::number(spec); cmd += " -f "; } - if (handler->isOneShot(id)) + if (bp.isOneShot()) cmd += "-t "; - if (!handler->isEnabled(id)) + if (!bp.isEnabled()) cmd += "-d "; - if (int ignoreCount = handler->ignoreCount(id)) + if (int ignoreCount = bp.ignoreCount()) cmd += "-i " + QByteArray::number(ignoreCount) + ' '; - QByteArray condition = handler->condition(id); + QByteArray condition = bp.condition(); if (!condition.isEmpty()) cmd += " -c \"" + condition + "\" "; - cmd += breakpointLocation(id); + cmd += breakpointLocation(bp.parameters()); postCommand(cmd, NeedsStop | RebuildBreakpointModel, CB(handleBreakInsert1), vid); } -void GdbEngine::changeBreakpoint(BreakpointModelId id) +void GdbEngine::changeBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - const BreakpointParameters &data = handler->breakpointData(id); + const BreakpointParameters &data = bp.parameters(); QTC_ASSERT(data.type != UnknownBreakpointType, return); - const BreakpointResponse &response = handler->response(id); + const BreakpointResponse &response = bp.response(); QTC_ASSERT(response.id.isValid(), return); const QByteArray bpnr = response.id.toByteArray(); - const BreakpointState state = handler->state(id); + const BreakpointState state = bp.state(); if (state == BreakpointChangeRequested) - handler->notifyBreakpointChangeProceeding(id); - const BreakpointState state2 = handler->state(id); + bp.notifyBreakpointChangeProceeding(); + const BreakpointState state2 = bp.state(); QTC_ASSERT(state2 == BreakpointChangeProceeding, qDebug() << state2); - QVariant vid = QVariant::fromValue(id); + QVariant vid = QVariant::fromValue(bp); if (!response.pending && data.threadSpec != response.threadSpec) { // The only way to change this seems to be to re-set the bp completely. @@ -2921,24 +2899,22 @@ void GdbEngine::changeBreakpoint(BreakpointModelId id) CB(handleBreakEnable), vid); return; } - handler->notifyBreakpointChangeOk(id); + bp.notifyBreakpointChangeOk(); } -void GdbEngine::removeBreakpoint(BreakpointModelId id) +void GdbEngine::removeBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - QTC_CHECK(handler->state(id) == BreakpointRemoveRequested); - BreakpointResponse br = handler->response(id); + QTC_CHECK(bp.state() == BreakpointRemoveRequested); + BreakpointResponse br = bp.response(); if (br.id.isValid()) { // We already have a fully inserted breakpoint. - handler->notifyBreakpointRemoveProceeding(id); - showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString()) - .arg(handler->fileName(id))); + bp.notifyBreakpointRemoveProceeding(); + showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString()).arg(bp.fileName())); postCommand("-break-delete " + br.id.toByteArray(), NeedsStop | RebuildBreakpointModel); // Pretend it succeeds without waiting for response. Feels better. // FIXME: Really? - handler->notifyBreakpointRemoveOk(id); + bp.notifyBreakpointRemoveOk(); } else { // Breakpoint was scheduled to be inserted, but we haven't had // an answer so far. Postpone activity by doing nothing. @@ -4715,8 +4691,8 @@ bool GdbEngine::attemptQuickStart() const // Don't try if there are breakpoints we might be able to handle. BreakHandler *handler = breakHandler(); - foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { - if (acceptsBreakpoint(id)) + foreach (Breakpoint bp, handler->unclaimedBreakpoints()) { + if (acceptsBreakpoint(bp)) return false; } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 5b4bd4ff57..e029fd259c 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -33,6 +33,7 @@ #include <debugger/debuggerengine.h> +#include <debugger/breakhandler.h> #include <debugger/watchhandler.h> #include <debugger/watchutils.h> #include <debugger/debuggertooltipmanager.h> @@ -55,6 +56,8 @@ class DebugInfoTaskHandler; class GdbResponse; class GdbMi; class MemoryAgentCookie; +class BreakpointParameters; +class BreakpointResponse; class WatchData; class DisassemblerAgentCookie; @@ -259,10 +262,10 @@ private: ////////// Inferior Management ////////// // This should be always the last call in a function. bool stateAcceptsBreakpointChanges() const; - bool acceptsBreakpoint(BreakpointModelId id) const; - void insertBreakpoint(BreakpointModelId id); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id); + bool acceptsBreakpoint(Breakpoint bp) const; + void insertBreakpoint(Breakpoint bp); + void removeBreakpoint(Breakpoint bp); + void changeBreakpoint(Breakpoint bp); void executeStep(); void executeStepOut(); @@ -314,10 +317,10 @@ private: ////////// View & Data Stuff ////////// void handleBreakLineNumber(const GdbResponse &response); void handleWatchInsert(const GdbResponse &response); void handleCatchInsert(const GdbResponse &response); - void handleBkpt(const GdbMi &bkpt, const BreakpointModelId &id); + void handleBkpt(const GdbMi &bkpt, Breakpoint bp); void updateResponse(BreakpointResponse &response, const GdbMi &bkpt); - QByteArray breakpointLocation(BreakpointModelId id); // For gdb/MI. - QByteArray breakpointLocation2(BreakpointModelId id); // For gdb/CLI fallback. + QByteArray breakpointLocation(const BreakpointParameters &data); // For gdb/MI. + QByteArray breakpointLocation2(const BreakpointParameters &data); // For gdb/CLI fallback. QString breakLocation(const QString &file) const; // diff --git a/src/plugins/debugger/lldb/lldbengine.cpp b/src/plugins/debugger/lldb/lldbengine.cpp index 5523020d6c..b024787cc5 100644 --- a/src/plugins/debugger/lldb/lldbengine.cpp +++ b/src/plugins/debugger/lldb/lldbengine.cpp @@ -528,33 +528,32 @@ void LldbEngine::selectThread(ThreadId threadId) runCommand(Command("selectThread").arg("id", threadId.raw())); } -bool LldbEngine::acceptsBreakpoint(BreakpointModelId id) const +bool LldbEngine::acceptsBreakpoint(Breakpoint bp) const { - return breakHandler()->breakpointData(id).isCppBreakpoint() - && startParameters().startMode != AttachCore; + return bp.parameters().isCppBreakpoint() && startParameters().startMode != AttachCore; } bool LldbEngine::attemptBreakpointSynchronizationHelper(Command *cmd) { BreakHandler *handler = breakHandler(); - foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { + foreach (Breakpoint bp, handler->unclaimedBreakpoints()) { // Take ownership of the breakpoint. Requests insertion. - if (acceptsBreakpoint(id)) { + if (acceptsBreakpoint(bp)) { showMessage(_("TAKING OWNERSHIP OF BREAKPOINT %1 IN STATE %2") - .arg(id.toString()).arg(handler->state(id))); - handler->setEngine(id, this); + .arg(bp.id().toString()).arg(bp.state())); + bp.setEngine(this); } else { showMessage(_("BREAKPOINT %1 IN STATE %2 IS NOT ACCEPTABLE") - .arg(id.toString()).arg(handler->state(id))); + .arg(bp.id().toString()).arg(bp.state())); } } bool done = true; cmd->beginList("bkpts"); - foreach (BreakpointModelId id, handler->engineBreakpointIds(this)) { - const BreakpointResponse &response = handler->response(id); - const BreakpointState bpState = handler->state(id); + foreach (Breakpoint bp, handler->engineBreakpoints(this)) { + const BreakpointResponse &response = bp.response(); + const BreakpointState bpState = bp.state(); switch (bpState) { case BreakpointNew: // Should not happen once claimed. @@ -564,57 +563,57 @@ bool LldbEngine::attemptBreakpointSynchronizationHelper(Command *cmd) done = false; cmd->beginGroup() .arg("operation", "add") - .arg("modelid", id.toByteArray()) - .arg("type", handler->type(id)) - .arg("ignorecount", handler->ignoreCount(id)) - .arg("condition", handler->condition(id).toHex()) - .arg("function", handler->functionName(id).toUtf8()) - .arg("oneshot", handler->isOneShot(id)) - .arg("enabled", handler->isEnabled(id)) - .arg("file", handler->fileName(id).toUtf8()) - .arg("line", handler->lineNumber(id)) - .arg("address", handler->address(id)) - .arg("expression", handler->expression(id)) + .arg("modelid", bp.id().toByteArray()) + .arg("type", bp.type()) + .arg("ignorecount", bp.ignoreCount()) + .arg("condition", bp.condition().toHex()) + .arg("function", bp.functionName().toUtf8()) + .arg("oneshot", bp.isOneShot()) + .arg("enabled", bp.isEnabled()) + .arg("file", bp.fileName().toUtf8()) + .arg("line", bp.lineNumber()) + .arg("address", bp.address()) + .arg("expression", bp.expression()) .endGroup(); - handler->notifyBreakpointInsertProceeding(id); + bp.notifyBreakpointInsertProceeding(); break; case BreakpointChangeRequested: done = false; cmd->beginGroup() .arg("operation", "change") - .arg("modelid", id.toByteArray()) + .arg("modelid", bp.id().toByteArray()) .arg("lldbid", response.id.toByteArray()) - .arg("type", handler->type(id)) - .arg("ignorecount", handler->ignoreCount(id)) - .arg("condition", handler->condition(id).toHex()) - .arg("function", handler->functionName(id).toUtf8()) - .arg("oneshot", handler->isOneShot(id)) - .arg("enabled", handler->isEnabled(id)) - .arg("file", handler->fileName(id).toUtf8()) - .arg("line", handler->lineNumber(id)) - .arg("address", handler->address(id)) - .arg("expression", handler->expression(id)) + .arg("type", bp.type()) + .arg("ignorecount", bp.ignoreCount()) + .arg("condition", bp.condition().toHex()) + .arg("function", bp.functionName().toUtf8()) + .arg("oneshot", bp.isOneShot()) + .arg("enabled", bp.isEnabled()) + .arg("file", bp.fileName().toUtf8()) + .arg("line", bp.lineNumber()) + .arg("address", bp.address()) + .arg("expression", bp.expression()) .endGroup(); - handler->notifyBreakpointChangeProceeding(id); + bp.notifyBreakpointChangeProceeding(); break; case BreakpointRemoveRequested: done = false; cmd->beginGroup() .arg("operation", "remove") - .arg("modelid", id.toByteArray()) + .arg("modelid", bp.id().toByteArray()) .arg("lldbid", response.id.toByteArray()) .endGroup(); - handler->notifyBreakpointRemoveProceeding(id); + bp.notifyBreakpointRemoveProceeding(); break; case BreakpointChangeProceeding: case BreakpointInsertProceeding: case BreakpointRemoveProceeding: case BreakpointInserted: case BreakpointDead: - QTC_ASSERT(false, qDebug() << "UNEXPECTED STATE" << bpState << "FOR BP " << id); + QTC_ASSERT(false, qDebug() << "UNEXPECTED STATE" << bpState << "FOR BP " << bp.id()); break; default: - QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << bpState << "FOR BP" << id); + QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << bpState << "FOR BP" << bp.id()); } } cmd->endList(); @@ -643,9 +642,10 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added) BreakHandler *handler = breakHandler(); BreakpointResponseId rid = BreakpointResponseId(bkpt["lldbid"].data()); BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data()); - if (!id.isValid()) - id = handler->findBreakpointByResponseId(rid); - BreakpointResponse response = handler->response(id); + Breakpoint bp = handler->breakpointById(id); + if (!bp.isValid()) + bp = handler->findBreakpointByResponseId(rid); + BreakpointResponse response = bp.response(); if (added) response.id = rid; QTC_CHECK(response.id == rid); @@ -669,7 +669,7 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added) sub.functionName = location["func"].toUtf8(); sub.fileName = location["file"].toUtf8(); sub.lineNumber = location["line"].toInt(); - handler->insertSubBreakpoint(id, sub); + bp.insertSubBreakpoint(sub); } } else if (numChild == 1) { const GdbMi location = locations.childAt(0); @@ -679,11 +679,11 @@ void LldbEngine::updateBreakpointData(const GdbMi &bkpt, bool added) // This can happen for pending breakpoints. showMessage(_("NO LOCATIONS (YET) FOR BP %1").arg(response.toString())); } - handler->setResponse(id, response); + bp.setResponse(response); if (added) - handler->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertOk(); else - handler->notifyBreakpointChangeOk(id); + bp.notifyBreakpointChangeOk(); } void LldbEngine::refreshDisassembly(const GdbMi &data) @@ -736,23 +736,25 @@ void LldbEngine::refreshOutput(const GdbMi &output) void LldbEngine::refreshAddedBreakpoint(const GdbMi &bkpt) { BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data()); - QTC_CHECK(breakHandler()->state(id) == BreakpointInsertProceeding); + Breakpoint bp = breakHandler()->breakpointById(id); + QTC_CHECK(bp.state() == BreakpointInsertProceeding); updateBreakpointData(bkpt, true); } void LldbEngine::refreshChangedBreakpoint(const GdbMi &bkpt) { BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data()); - QTC_CHECK(!id.isValid() || breakHandler()->state(id) == BreakpointChangeProceeding); + Breakpoint bp = breakHandler()->breakpointById(id); + QTC_CHECK(!bp.isValid() || bp.state() == BreakpointChangeProceeding); updateBreakpointData(bkpt, false); } void LldbEngine::refreshRemovedBreakpoint(const GdbMi &bkpt) { - BreakHandler *handler = breakHandler(); BreakpointModelId id = BreakpointModelId(bkpt["modelid"].data()); - QTC_CHECK(handler->state(id) == BreakpointRemoveProceeding); - handler->notifyBreakpointRemoveOk(id); + Breakpoint bp = breakHandler()->breakpointById(id); + QTC_CHECK(bp.state() == BreakpointRemoveProceeding); + bp.notifyBreakpointRemoveOk(); } void LldbEngine::loadSymbols(const QString &moduleName) diff --git a/src/plugins/debugger/lldb/lldbengine.h b/src/plugins/debugger/lldb/lldbengine.h index 491688c57d..81be06af49 100644 --- a/src/plugins/debugger/lldb/lldbengine.h +++ b/src/plugins/debugger/lldb/lldbengine.h @@ -122,7 +122,7 @@ private: void activateFrame(int index); void selectThread(ThreadId threadId); - bool acceptsBreakpoint(BreakpointModelId id) const; + bool acceptsBreakpoint(Breakpoint bp) const; void attemptBreakpointSynchronization(); bool attemptBreakpointSynchronizationHelper(Command *command); diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 708b0d3f9b..f19ac57661 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -327,34 +327,31 @@ void PdbEngine::selectThread(ThreadId threadId) Q_UNUSED(threadId) } -bool PdbEngine::acceptsBreakpoint(BreakpointModelId id) const +bool PdbEngine::acceptsBreakpoint(Breakpoint bp) const { - const QString fileName = breakHandler()->fileName(id); + const QString fileName = bp.fileName(); return fileName.endsWith(QLatin1String(".py")); } -void PdbEngine::insertBreakpoint(BreakpointModelId id) +void PdbEngine::insertBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - QTC_CHECK(handler->state(id) == BreakpointInsertRequested); - handler->notifyBreakpointInsertProceeding(id); + QTC_CHECK(bp.state() == BreakpointInsertRequested); + bp.notifyBreakpointInsertProceeding(); QByteArray loc; - if (handler->type(id) == BreakpointByFunction) - loc = handler->functionName(id).toLatin1(); + if (bp.type() == BreakpointByFunction) + loc = bp.functionName().toLatin1(); else - loc = handler->fileName(id).toLocal8Bit() + ':' - + QByteArray::number(handler->lineNumber(id)); + loc = bp.fileName().toLocal8Bit() + ':' + + QByteArray::number(bp.lineNumber()); - postCommand("break " + loc, CB(handleBreakInsert), QVariant(id)); + postCommand("break " + loc, CB(handleBreakInsert), QVariant::fromValue(bp)); } void PdbEngine::handleBreakInsert(const PdbResponse &response) { //qDebug() << "BP RESPONSE: " << response.data; // "Breakpoint 1 at /pdb/math.py:10" - BreakpointModelId id(response.cookie.toInt()); - BreakHandler *handler = breakHandler(); QTC_ASSERT(response.data.startsWith("Breakpoint "), return); int pos1 = response.data.indexOf(" at "); QTC_ASSERT(pos1 != -1, return); @@ -366,22 +363,21 @@ void PdbEngine::handleBreakInsert(const PdbResponse &response) br.id = BreakpointResponseId(bpnr); br.fileName = _(file); br.lineNumber = line.toInt(); - handler->setResponse(id, br); - QTC_CHECK(!handler->needsChange(id)); - handler->notifyBreakpointInsertOk(id); + Breakpoint bp = response.cookie.value<Breakpoint>(); + bp.setResponse(br); + QTC_CHECK(!bp.needsChange()); + bp.notifyBreakpointInsertOk(); } -void PdbEngine::removeBreakpoint(BreakpointModelId id) +void PdbEngine::removeBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - QTC_CHECK(handler->state(id) == BreakpointRemoveRequested); - handler->notifyBreakpointRemoveProceeding(id); - BreakpointResponse br = handler->response(id); - showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString()) - .arg(handler->fileName(id))); + QTC_CHECK(bp.state() == BreakpointRemoveRequested); + bp.notifyBreakpointRemoveProceeding(); + BreakpointResponse br = bp.response(); + showMessage(_("DELETING BP %1 IN %2").arg(br.id.toString()).arg(bp.fileName())); postCommand("clear " + br.id.toByteArray()); // Pretend it succeeds without waiting for response. - handler->notifyBreakpointRemoveOk(id); + bp.notifyBreakpointRemoveOk(); } void PdbEngine::loadSymbols(const QString &moduleName) diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h index a325689e8d..058f607498 100644 --- a/src/plugins/debugger/pdb/pdbengine.h +++ b/src/plugins/debugger/pdb/pdbengine.h @@ -89,9 +89,9 @@ private: void activateFrame(int index); void selectThread(ThreadId threadId); - bool acceptsBreakpoint(BreakpointModelId id) const; - void insertBreakpoint(BreakpointModelId id); - void removeBreakpoint(BreakpointModelId id); + bool acceptsBreakpoint(Breakpoint bp) const; + void insertBreakpoint(Breakpoint bp); + void removeBreakpoint(Breakpoint bp); void assignValueInDebugger(const WatchData *data, const QString &expr, const QVariant &value); diff --git a/src/plugins/debugger/qml/baseqmldebuggerclient.cpp b/src/plugins/debugger/qml/baseqmldebuggerclient.cpp index f55c346fb5..00921bd17a 100644 --- a/src/plugins/debugger/qml/baseqmldebuggerclient.cpp +++ b/src/plugins/debugger/qml/baseqmldebuggerclient.cpp @@ -29,6 +29,7 @@ ****************************************************************************/ #include "baseqmldebuggerclient.h" +#include <debugger/breakhandler.h> #include <utils/qtcassert.h> @@ -52,7 +53,7 @@ BaseQmlDebuggerClient::~BaseQmlDebuggerClient() delete d; } -bool BaseQmlDebuggerClient::acceptsBreakpoint(const BreakpointModelId &/*id*/) +bool BaseQmlDebuggerClient::acceptsBreakpoint(Breakpoint /*bp*/) { return false; } diff --git a/src/plugins/debugger/qml/baseqmldebuggerclient.h b/src/plugins/debugger/qml/baseqmldebuggerclient.h index b39fb10368..9dd594e8a5 100644 --- a/src/plugins/debugger/qml/baseqmldebuggerclient.h +++ b/src/plugins/debugger/qml/baseqmldebuggerclient.h @@ -67,11 +67,11 @@ public: virtual void activateFrame(int index) = 0; - virtual bool acceptsBreakpoint(const BreakpointModelId &id); - virtual void insertBreakpoint(const BreakpointModelId &id, int adjustedLine, + virtual bool acceptsBreakpoint(Breakpoint bp); + virtual void insertBreakpoint(Breakpoint bp, int adjustedLine, int adjustedColumn = -1) = 0; - virtual void removeBreakpoint(const BreakpointModelId &id) = 0; - virtual void changeBreakpoint(const BreakpointModelId &id) = 0; + virtual void removeBreakpoint(Breakpoint bp) = 0; + virtual void changeBreakpoint(Breakpoint bp) = 0; virtual void synchronizeBreakpoints() = 0; virtual void assignValueInDebugger(const WatchData *data, diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 9882b7deb2..b65e9d8a44 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -30,8 +30,10 @@ #include "qmlcppengine.h" #include "qmlengine.h" + #include <debugger/debuggerruncontrol.h> #include <debugger/debuggerstartparameters.h> +#include <debugger/breakhandler.h> #include <debugger/stackhandler.h> #include <debugger/watchhandler.h> @@ -244,10 +246,10 @@ void QmlCppEngine::attemptBreakpointSynchronization() } } -bool QmlCppEngine::acceptsBreakpoint(BreakpointModelId id) const +bool QmlCppEngine::acceptsBreakpoint(Breakpoint bp) const { - return m_cppEngine->acceptsBreakpoint(id) - || m_qmlEngine->acceptsBreakpoint(id); + return m_cppEngine->acceptsBreakpoint(bp) + || m_qmlEngine->acceptsBreakpoint(bp); } void QmlCppEngine::selectThread(ThreadId threadId) diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index 050bf87731..fe11251023 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -78,7 +78,7 @@ public: void updateAll(); void attemptBreakpointSynchronization(); - bool acceptsBreakpoint(BreakpointModelId id) const; + bool acceptsBreakpoint(Breakpoint bp) const; void selectThread(ThreadId threadId); void assignValueInDebugger(const WatchData *data, diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index 188686195a..441c8e0e60 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -797,21 +797,20 @@ void QmlEngine::selectThread(ThreadId threadId) Q_UNUSED(threadId) } -void QmlEngine::insertBreakpoint(BreakpointModelId id) +void QmlEngine::insertBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - BreakpointState state = handler->state(id); - QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << id << this << state); - handler->notifyBreakpointInsertProceeding(id); + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointInsertRequested, qDebug() << bp << this << state); + bp.notifyBreakpointInsertProceeding(); - const BreakpointParameters ¶ms = handler->breakpointData(id); + const BreakpointParameters ¶ms = bp.parameters(); quint32 line = params.lineNumber; quint32 column = 0; if (params.type == BreakpointByFileAndLine) { bool valid = false; if (!adjustBreakpointLineAndColumn(params.fileName, &line, &column, &valid)) { - pendingBreakpoints.insertMulti(params.fileName, id); + pendingBreakpoints.insertMulti(params.fileName, bp); return; } if (!valid) @@ -819,65 +818,61 @@ void QmlEngine::insertBreakpoint(BreakpointModelId id) } if (m_adapter.activeDebuggerClient()) { - m_adapter.activeDebuggerClient()->insertBreakpoint(id, line, column); + m_adapter.activeDebuggerClient()->insertBreakpoint(bp, line, column); } else { foreach (BaseQmlDebuggerClient *client, m_adapter.debuggerClients()) { - client->insertBreakpoint(id, line, column); + client->insertBreakpoint(bp, line, column); } } } -void QmlEngine::removeBreakpoint(BreakpointModelId id) +void QmlEngine::removeBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - - const BreakpointParameters ¶ms = handler->breakpointData(id); + const BreakpointParameters ¶ms = bp.parameters(); if (params.type == BreakpointByFileAndLine && pendingBreakpoints.contains(params.fileName)) { - QHash<QString, BreakpointModelId>::iterator i = - pendingBreakpoints.find(params.fileName); - while (i != pendingBreakpoints.end() && i.key() == params.fileName) { - if (i.value() == id) { - pendingBreakpoints.erase(i); + auto it = pendingBreakpoints.find(params.fileName); + while (it != pendingBreakpoints.end() && it.key() == params.fileName) { + if (it.value() == bp.id()) { + pendingBreakpoints.erase(it); return; } - ++i; + ++it; } } - BreakpointState state = handler->state(id); - QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << id << this << state); - handler->notifyBreakpointRemoveProceeding(id); + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointRemoveRequested, qDebug() << bp << this << state); + bp.notifyBreakpointRemoveProceeding(); if (m_adapter.activeDebuggerClient()) { - m_adapter.activeDebuggerClient()->removeBreakpoint(id); + m_adapter.activeDebuggerClient()->removeBreakpoint(bp); } else { foreach (BaseQmlDebuggerClient *client, m_adapter.debuggerClients()) { - client->removeBreakpoint(id); + client->removeBreakpoint(bp); } } - if (handler->state(id) == BreakpointRemoveProceeding) - handler->notifyBreakpointRemoveOk(id); + if (bp.state() == BreakpointRemoveProceeding) + bp.notifyBreakpointRemoveOk(); } -void QmlEngine::changeBreakpoint(BreakpointModelId id) +void QmlEngine::changeBreakpoint(Breakpoint bp) { - BreakHandler *handler = breakHandler(); - BreakpointState state = handler->state(id); - QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << id << this << state); - handler->notifyBreakpointChangeProceeding(id); + BreakpointState state = bp.state(); + QTC_ASSERT(state == BreakpointChangeRequested, qDebug() << bp << this << state); + bp.notifyBreakpointChangeProceeding(); if (m_adapter.activeDebuggerClient()) { - m_adapter.activeDebuggerClient()->changeBreakpoint(id); + m_adapter.activeDebuggerClient()->changeBreakpoint(bp); } else { foreach (BaseQmlDebuggerClient *client, m_adapter.debuggerClients()) { - client->changeBreakpoint(id); + client->changeBreakpoint(bp); } } - if (handler->state(id) == BreakpointChangeProceeding) - handler->notifyBreakpointChangeOk(id); + if (bp.state() == BreakpointChangeProceeding) + bp.notifyBreakpointChangeOk(); } void QmlEngine::attemptBreakpointSynchronization() @@ -890,26 +885,26 @@ void QmlEngine::attemptBreakpointSynchronization() BreakHandler *handler = breakHandler(); DebuggerEngine *bpOwner = isSlaveEngine() ? masterEngine() : this; - foreach (BreakpointModelId id, handler->unclaimedBreakpointIds()) { + foreach (Breakpoint bp, handler->unclaimedBreakpoints()) { // Take ownership of the breakpoint. Requests insertion. - if (acceptsBreakpoint(id)) - handler->setEngine(id, bpOwner); + if (acceptsBreakpoint(bp)) + bp.setEngine(bpOwner); } - foreach (BreakpointModelId id, handler->engineBreakpointIds(bpOwner)) { - switch (handler->state(id)) { + foreach (Breakpoint bp, handler->engineBreakpoints(bpOwner)) { + switch (bp.state()) { case BreakpointNew: // Should not happen once claimed. QTC_CHECK(false); continue; case BreakpointInsertRequested: - insertBreakpoint(id); + insertBreakpoint(bp); continue; case BreakpointChangeRequested: - changeBreakpoint(id); + changeBreakpoint(bp); continue; case BreakpointRemoveRequested: - removeBreakpoint(id); + removeBreakpoint(bp); continue; case BreakpointChangeProceeding: case BreakpointInsertProceeding: @@ -918,7 +913,7 @@ void QmlEngine::attemptBreakpointSynchronization() case BreakpointDead: continue; } - QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << id << state()); + QTC_ASSERT(false, qDebug() << "UNKNOWN STATE" << bp << state()); } DebuggerEngine::attemptBreakpointSynchronization(); @@ -932,9 +927,9 @@ void QmlEngine::attemptBreakpointSynchronization() } } -bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const +bool QmlEngine::acceptsBreakpoint(Breakpoint bp) const { - if (!breakHandler()->breakpointData(id).isCppBreakpoint()) + if (!bp.parameters().isCppBreakpoint()) return true; //If it is a Cpp Breakpoint query if the type can be also handled by the debugger client @@ -943,7 +938,7 @@ bool QmlEngine::acceptsBreakpoint(BreakpointModelId id) const //This is because the older client does not support BreakpointOnQmlSignalHandler bool acceptBreakpoint = false; if (m_adapter.activeDebuggerClient()) - acceptBreakpoint = m_adapter.activeDebuggerClient()->acceptsBreakpoint(id); + acceptBreakpoint = m_adapter.activeDebuggerClient()->acceptsBreakpoint(bp); return acceptBreakpoint; } @@ -1144,10 +1139,10 @@ void QmlEngine::documentUpdated(QmlJS::Document::Ptr doc) { QString fileName = doc->fileName(); if (pendingBreakpoints.contains(fileName)) { - QList<BreakpointModelId> ids = pendingBreakpoints.values(fileName); + QList<Breakpoint> bps = pendingBreakpoints.values(fileName); pendingBreakpoints.remove(fileName); - foreach (const BreakpointModelId &id, ids) - insertBreakpoint(id); + foreach (const Breakpoint bp, bps) + insertBreakpoint(bp); } } diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index b5f296f5e3..8cf640b9a5 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -84,7 +84,7 @@ public: void updateScriptSource(const QString &fileName, int lineOffset, int columnOffset, const QString &source); - void insertBreakpoint(BreakpointModelId id); + void insertBreakpoint(Breakpoint bp); signals: void tooltipRequested(const QPoint &mousePos, @@ -140,9 +140,9 @@ private: void selectThread(ThreadId threadId); void attemptBreakpointSynchronization(); - void removeBreakpoint(BreakpointModelId id); - void changeBreakpoint(BreakpointModelId id); - bool acceptsBreakpoint(BreakpointModelId id) const; + void removeBreakpoint(Breakpoint bp); + void changeBreakpoint(Breakpoint bp); + bool acceptsBreakpoint(Breakpoint bp) const; void assignValueInDebugger(const WatchData *data, const QString &expr, const QVariant &value); @@ -190,7 +190,7 @@ private: QHash<QString, QTextDocument*> m_sourceDocuments; QHash<QString, QWeakPointer<TextEditor::BaseTextEditor> > m_sourceEditors; InteractiveInterpreter m_interpreter; - QHash<QString,BreakpointModelId> pendingBreakpoints; + QHash<QString,Breakpoint> pendingBreakpoints; QList<quint32> queryIds; bool m_retryOnConnectFail; bool m_automaticConnect; diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp index 1de81dbdbf..5823b1c51d 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.cpp +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.cpp @@ -842,23 +842,22 @@ void QmlV8DebuggerClient::activateFrame(int index) d->engine->stackHandler()->setCurrentIndex(index); } -bool QmlV8DebuggerClient::acceptsBreakpoint(const BreakpointModelId &id) +bool QmlV8DebuggerClient::acceptsBreakpoint(Breakpoint bp) { - BreakpointType type = d->engine->breakHandler()->breakpointData(id).type; + BreakpointType type = bp.type(); return (type == BreakpointOnQmlSignalEmit || type == BreakpointByFileAndLine || type == BreakpointAtJavaScriptThrow); } -void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id, +void QmlV8DebuggerClient::insertBreakpoint(Breakpoint bp, int adjustedLine, int adjustedColumn) { - BreakHandler *handler = d->engine->breakHandler(); - const BreakpointParameters ¶ms = handler->breakpointData(id); + const BreakpointParameters ¶ms = bp.parameters(); if (params.type == BreakpointAtJavaScriptThrow) { - handler->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertOk(); d->setExceptionBreak(AllExceptions, params.enabled); } else if (params.type == BreakpointByFileAndLine) { @@ -868,19 +867,18 @@ void QmlV8DebuggerClient::insertBreakpoint(const BreakpointModelId &id, } else if (params.type == BreakpointOnQmlSignalEmit) { d->setBreakpoint(QString(_(EVENT)), params.functionName, params.enabled); - d->engine->breakHandler()->notifyBreakpointInsertOk(id); + bp.notifyBreakpointInsertOk(); } - d->breakpointsSync.insert(d->sequence, id); + d->breakpointsSync.insert(d->sequence, bp.id()); } -void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id) +void QmlV8DebuggerClient::removeBreakpoint(Breakpoint bp) { - BreakHandler *handler = d->engine->breakHandler(); - const BreakpointParameters ¶ms = handler->breakpointData(id); + const BreakpointParameters ¶ms = bp.parameters(); - int breakpoint = d->breakpoints.value(id); - d->breakpoints.remove(id); + int breakpoint = d->breakpoints.value(bp.id()); + d->breakpoints.remove(bp.id()); if (params.type == BreakpointAtJavaScriptThrow) d->setExceptionBreak(AllExceptions); @@ -890,25 +888,25 @@ void QmlV8DebuggerClient::removeBreakpoint(const BreakpointModelId &id) d->clearBreakpoint(breakpoint); } -void QmlV8DebuggerClient::changeBreakpoint(const BreakpointModelId &id) +void QmlV8DebuggerClient::changeBreakpoint(Breakpoint bp) { - BreakHandler *handler = d->engine->breakHandler(); - const BreakpointParameters ¶ms = handler->breakpointData(id); + const BreakpointParameters ¶ms = bp.parameters(); - BreakpointResponse br = handler->response(id); + BreakpointResponse br = bp.response(); if (params.type == BreakpointAtJavaScriptThrow) { d->setExceptionBreak(AllExceptions, params.enabled); br.enabled = params.enabled; - handler->setResponse(id, br); + bp.setResponse(br); } else if (params.type == BreakpointOnQmlSignalEmit) { d->setBreakpoint(QString(_(EVENT)), params.functionName, params.enabled); br.enabled = params.enabled; - handler->setResponse(id, br); + bp.setResponse(br); } else { //V8 supports only minimalistic changes in breakpoint //Remove the breakpoint and add again - handler->notifyBreakpointChangeOk(id); - handler->removeBreakpoint(id); + bp.notifyBreakpointChangeOk(); + bp.removeBreakpoint(); + BreakHandler *handler = d->engine->breakHandler(); handler->appendBreakpoint(params); } } @@ -1086,12 +1084,12 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) //The breakpoint requested line should be same as //actual line BreakHandler *handler = d->engine->breakHandler(); - if (handler->state(id) != BreakpointInserted) { - BreakpointResponse br = handler->response(id); - br.lineNumber = breakpointData.value(_("line") - ).toInt() + 1; - handler->setResponse(id, br); - handler->notifyBreakpointInsertOk(id); + Breakpoint bp = handler->breakpointById(id); + if (bp.state() != BreakpointInserted) { + BreakpointResponse br = bp.response(); + br.lineNumber = breakpointData.value(_("line")).toInt() + 1; + bp.setResponse(br); + bp.notifyBreakpointInsertOk(); } } @@ -1211,10 +1209,10 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) BreakHandler *handler = d->engine->breakHandler(); foreach (int v8Id, v8BreakpointIds) { - const BreakpointModelId internalId = d->breakpoints.key(v8Id); - - if (internalId.isValid()) { - const BreakpointParameters ¶ms = handler->breakpointData(internalId); + const BreakpointModelId id = d->breakpoints.key(v8Id); + Breakpoint bp = handler->breakpointById(id); + if (bp.isValid()) { + const BreakpointParameters ¶ms = bp.parameters(); d->clearBreakpoint(v8Id); d->setBreakpoint(QString(_(SCRIPTREGEXP)), @@ -1224,7 +1222,7 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) newColumn, QString(QString::fromLatin1(params.condition)), params.ignoreCount); - d->breakpointsSync.insert(d->sequence, internalId); + d->breakpointsSync.insert(d->sequence, id); } } d->continueDebugging(Continue); @@ -1242,17 +1240,18 @@ void QmlV8DebuggerClient::messageReceived(const QByteArray &data) BreakHandler *handler = d->engine->breakHandler(); foreach (int v8Id, v8BreakpointIds) { const BreakpointModelId id = d->breakpoints.key(v8Id); - if (id.isValid()) { - BreakpointResponse br = handler->response(id); + Breakpoint bp = handler->breakpointById(id); + if (bp) { + BreakpointResponse br = bp.response(); if (br.functionName.isEmpty()) { br.functionName = invocationText; - handler->setResponse(id, br); + bp.setResponse(br); } - if (handler->state(id) != BreakpointInserted) { + if (bp.state() != BreakpointInserted) { br.lineNumber = breakData.value( _("sourceLine")).toInt() + 1; - handler->setResponse(id, br); - handler->notifyBreakpointInsertOk(id); + bp.setResponse(br); + bp.notifyBreakpointInsertOk(); } } } diff --git a/src/plugins/debugger/qml/qmlv8debuggerclient.h b/src/plugins/debugger/qml/qmlv8debuggerclient.h index f5a64e1c2b..06894d0ebb 100644 --- a/src/plugins/debugger/qml/qmlv8debuggerclient.h +++ b/src/plugins/debugger/qml/qmlv8debuggerclient.h @@ -77,11 +77,11 @@ public: void activateFrame(int index); - bool acceptsBreakpoint(const BreakpointModelId &id); - void insertBreakpoint(const BreakpointModelId &id, int adjustedLine, + bool acceptsBreakpoint(Breakpoint bp); + void insertBreakpoint(Breakpoint bp, int adjustedLine, int adjustedColumn = -1); - void removeBreakpoint(const BreakpointModelId &id); - void changeBreakpoint(const BreakpointModelId &id); + void removeBreakpoint(Breakpoint bp); + void changeBreakpoint(Breakpoint bp); void synchronizeBreakpoints(); void assignValueInDebugger(const WatchData *data, diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp index 61d3664552..82dbe4d1f7 100644 --- a/src/plugins/debugger/qml/qscriptdebuggerclient.cpp +++ b/src/plugins/debugger/qml/qscriptdebuggerclient.cpp @@ -220,9 +220,9 @@ void QScriptDebuggerClient::startSession() BreakHandler *handler = d->engine->breakHandler(); DebuggerEngine * engine = d->engine->isSlaveEngine() ? d->engine->masterEngine() : d->engine; - foreach (BreakpointModelId id, handler->engineBreakpointIds(engine)) { - QTC_CHECK(handler->state(id) == BreakpointInsertProceeding); - handler->notifyBreakpointInsertOk(id); + foreach (Breakpoint bp, handler->engineBreakpoints(engine)) { + QTC_CHECK(bp.state() == BreakpointInsertProceeding); + bp.notifyBreakpointInsertOk(); } d->sessionStarted = true; } @@ -247,46 +247,42 @@ void QScriptDebuggerClient::activateFrame(int index) sendMessage(reply); } -void QScriptDebuggerClient::insertBreakpoint(const BreakpointModelId &id, +void QScriptDebuggerClient::insertBreakpoint(Breakpoint bp, int adjustedLine, int /*adjustedColumn*/) { - BreakHandler *handler = d->engine->breakHandler(); - JSAgentBreakpointData bp; - bp.fileUrl = QUrl::fromLocalFile(handler->fileName(id)).toString().toUtf8(); - bp.lineNumber = adjustedLine; - bp.functionName = handler->functionName(id).toUtf8(); - d->breakpoints.insert(bp); + JSAgentBreakpointData jsbp; + jsbp.fileUrl = QUrl::fromLocalFile(bp.fileName()).toString().toUtf8(); + jsbp.lineNumber = adjustedLine; + jsbp.functionName = bp.functionName().toUtf8(); + d->breakpoints.insert(jsbp); - BreakpointResponse br = handler->response(id); + BreakpointResponse br = bp.response(); br.lineNumber = adjustedLine; - handler->setResponse(id, br); - if (d->sessionStarted && handler->state(id) == BreakpointInsertProceeding) - handler->notifyBreakpointInsertOk(id); + bp.setResponse(br); + if (d->sessionStarted && bp.state() == BreakpointInsertProceeding) + bp.notifyBreakpointInsertOk(); } -void QScriptDebuggerClient::removeBreakpoint(const BreakpointModelId &id) +void QScriptDebuggerClient::removeBreakpoint(Breakpoint bp) { - BreakHandler *handler = d->engine->breakHandler(); - JSAgentBreakpointData bp; - bp.fileUrl = QUrl::fromLocalFile(handler->fileName(id)).toString().toUtf8(); - bp.lineNumber = handler->lineNumber(id); - bp.functionName = handler->functionName(id).toUtf8(); - d->breakpoints.remove(bp); + JSAgentBreakpointData jsbp; + jsbp.fileUrl = QUrl::fromLocalFile(bp.fileName()).toString().toUtf8(); + jsbp.lineNumber = bp.lineNumber(); + jsbp.functionName = bp.functionName().toUtf8(); + d->breakpoints.remove(jsbp); } -void QScriptDebuggerClient::changeBreakpoint(const BreakpointModelId &id) +void QScriptDebuggerClient::changeBreakpoint(Breakpoint bp) { - BreakHandler *handler = d->engine->breakHandler(); - if (handler->isEnabled(id)) { - BreakpointResponse br = handler->response(id); - insertBreakpoint(id, br.lineNumber); - } else { - removeBreakpoint(id); - } - BreakpointResponse br = handler->response(id); - br.enabled = handler->isEnabled(id); - handler->setResponse(id, br); + if (bp.isEnabled()) + insertBreakpoint(bp, bp.response().lineNumber); + else + removeBreakpoint(bp); + + BreakpointResponse br = bp.response(); + br.enabled = bp.isEnabled(); + bp.setResponse(br); } void QScriptDebuggerClient::synchronizeBreakpoints() diff --git a/src/plugins/debugger/qml/qscriptdebuggerclient.h b/src/plugins/debugger/qml/qscriptdebuggerclient.h index 85ba9dbaeb..3bf71e89ae 100644 --- a/src/plugins/debugger/qml/qscriptdebuggerclient.h +++ b/src/plugins/debugger/qml/qscriptdebuggerclient.h @@ -62,10 +62,10 @@ public: void activateFrame(int index); - void insertBreakpoint(const BreakpointModelId &id, int adjustedLine, + void insertBreakpoint(Breakpoint bp, int adjustedLine, int adjustedColumn = -1); - void removeBreakpoint(const BreakpointModelId &id); - void changeBreakpoint(const BreakpointModelId &id); + void removeBreakpoint(Breakpoint bp); + void changeBreakpoint(Breakpoint bp); void synchronizeBreakpoints(); void assignValueInDebugger(const WatchData *data, const QString &expression, |