diff --git a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp index 60d691f5c372549a8394cc3d51090670a06693be..db314d587fe3e93116f75b3cc5f6d3e14c8a39e4 100644 --- a/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp +++ b/share/qtcreator/qml/qmljsdebugger/jsdebuggeragent.cpp @@ -90,7 +90,34 @@ QDataStream &operator<<(QDataStream &s, const JSAgentStackData &data) return s << data.functionName << data.fileName << data.lineNumber; } -typedef JSAgentStackData JSBreakpointData; +struct JSAgentBreakpointData +{ + QByteArray functionName; + QByteArray fileName; + qint32 lineNumber; +}; + +typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints; + +QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data) +{ + return s << data.functionName << data.fileName << data.lineNumber; +} + +QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data) +{ + return s >> data.functionName >> data.fileName >> data.lineNumber; +} + +bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2) +{ + return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName; +} + +uint qHash(const JSAgentBreakpointData &b) +{ + return b.lineNumber ^ qHash(b.fileName); +} class JSDebuggerAgentPrivate { @@ -115,8 +142,8 @@ public: int stepCount; QEventLoop loop; - QHash <qint64, QString> filenames; - QSet< QPair<QString, qint32> > breakpointList; + QHash<qint64, QString> filenames; + JSAgentBreakpoints breakpoints; QStringList watchExpressions; QSet<qint64> knownObjectIds; }; @@ -348,7 +375,7 @@ void JSDebuggerAgentPrivate::positionChange return; //no re-entrency // check breakpoints - if (!breakpointList.isEmpty()) { + if (!breakpoints.isEmpty()) { QHash<qint64, QString>::const_iterator it = filenames.constFind(scriptId); QScriptContext *ctx = engine()->currentContext(); QScriptContextInfo info(ctx); @@ -362,8 +389,10 @@ void JSDebuggerAgentPrivate::positionChange QPair<QString, qint32> key = qMakePair(filename, lineNumber); it = filenames.insert(scriptId, filename); } - QPair<QString, qint32> key = qMakePair(*it, lineNumber); - if (breakpointList.contains(key)) { + JSAgentBreakpointData bp; + bp.fileName = it->toUtf8(); + bp.lineNumber = lineNumber; + if (breakpoints.contains(bp)) { stopped(); return; } @@ -440,7 +469,10 @@ void JSDebuggerAgentPrivate::messageReceived(const QByteArray &message) QByteArray command; ds >> command; if (command == "BREAKPOINTS") { - ds >> breakpointList; + ds >> breakpoints; + //qDebug() << "BREAKPOINTS"; + //foreach (const JSAgentBreakpointData &bp, breakpoints) + // qDebug() << "BREAKPOINT: " << bp.fileName << bp.lineNumber; } else if (command == "WATCH_EXPRESSIONS") { ds >> watchExpressions; } else if (command == "STEPOVER") { diff --git a/src/plugins/debugger/breakhandler.cpp b/src/plugins/debugger/breakhandler.cpp index 1bcfafcbdd84ace682b5c6f0aa4d029cda9bbd73..90ef5b0039990b8b01d141f3b8f4e513cf79e17d 100644 --- a/src/plugins/debugger/breakhandler.cpp +++ b/src/plugins/debugger/breakhandler.cpp @@ -148,7 +148,7 @@ int BreakHandler::findWatchPointIndexByAddress(quint64 address) const { for (int index = size() - 1; index >= 0; --index) { BreakpointData *bd = at(index); - if (bd->type == BreakpointData::WatchpointType && bd->address == address) + if (bd->isWatchpoint() && bd->address == address) return index; } return -1; @@ -168,9 +168,9 @@ void BreakHandler::saveBreakpoints() const BreakpointData *data = at(index); QMap<QString, QVariant> map; // Do not persist Watchpoints. - //if (data->type == BreakpointData::WatchpointType) + //if (data->isWatchpoint()) // continue; - if (data->type != BreakpointData::BreakpointType) + if (data->type != BreakpointByFileAndLine) map.insert(_("type"), data->type); if (!data->fileName.isEmpty()) map.insert(_("filename"), data->fileName); @@ -235,7 +235,7 @@ void BreakHandler::loadBreakpoints() data->useFullPath = bool(v.toInt()); v = map.value(_("type")); if (v.isValid()) - data->type = BreakpointData::Type(v.toInt()); + data->type = BreakpointType(v.toInt()); data->setMarkerFileName(data->fileName); data->setMarkerLineNumber(data->lineNumber); append(data); @@ -344,7 +344,7 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const return str.isEmpty() ? empty : str; } if (role == Qt::DecorationRole) { - if (data->type == BreakpointData::WatchpointType) + if (data->isWatchpoint()) return m_watchpointIcon; if (!data->enabled) return m_disabledBreakpointIcon; @@ -414,8 +414,8 @@ QVariant BreakHandler::data(const QModelIndex &mi, int role) const case 7: if (role == Qt::DisplayRole) { QString displayValue; - const quint64 effectiveAddress = data->type == BreakpointData::WatchpointType ? - data->address : data->bpAddress; + const quint64 effectiveAddress + = data->isWatchpoint() ? data->address : data->bpAddress; if (effectiveAddress) displayValue += QString::fromAscii("0x%1").arg(effectiveAddress, 0, 16); if (!data->bpState.isEmpty()) { diff --git a/src/plugins/debugger/breakpoint.cpp b/src/plugins/debugger/breakpoint.cpp index 9f0732407b7aa1d2ff090688060832798f40a380..ece39457dd5f51cb753e457eb28ecf6c7bdce2f4 100644 --- a/src/plugins/debugger/breakpoint.cpp +++ b/src/plugins/debugger/breakpoint.cpp @@ -61,7 +61,7 @@ static quint64 nextBPId() { BreakpointData::BreakpointData() : id(nextBPId()), enabled(true), - pending(true), type(BreakpointType), + pending(true), type(BreakpointByFileAndLine), ignoreCount(0), lineNumber(0), address(0), useFullPath(false), bpIgnoreCount(0), bpLineNumber(0), @@ -84,7 +84,7 @@ BreakpointData *BreakpointData::clone() const data->threadSpec = threadSpec; data->funcName = funcName; data->useFullPath = useFullPath; - if (isSetByFunction()) { + if (data->type == BreakpointByFunction) { // FIXME: Would removing it be better then leaving this // "history" around? data->m_markerFileName = m_markerFileName; @@ -142,6 +142,22 @@ static inline void formatAddress(QTextStream &str, quint64 address) QString BreakpointData::toToolTip() const { + QString t = tr("Unknown Breakpoint Type"); + switch (type) { + case BreakpointByFileAndLine: + t = tr("Breakpoint by File and Line"); + break; + case BreakpointByFunction: + t = tr("Breakpoint by Function"); + break; + case BreakpointByAddress: + t = tr("Breakpoint by Address"); + break; + case Watchpoint: + t = tr("Watchpoint"); + break; + } + QString rc; QTextStream str(&rc); str << "<html><body><table>" @@ -152,11 +168,7 @@ QString BreakpointData::toToolTip() const << "<tr><td>" << tr("Breakpoint Number:") << "</td><td>" << bpNumber << "</td></tr>" << "<tr><td>" << tr("Breakpoint Type:") - << "</td><td>" - << (type == BreakpointType ? tr("Breakpoint") - : type == WatchpointType ? tr("Watchpoint") - : tr("Unknown breakpoint type")) - << "</td></tr>" + << "</td><td>" << t << "</td></tr>" << "<tr><td>" << tr("State:") << "</td><td>" << bpState << "</td></tr>" << "</table><br><hr><table>" @@ -166,7 +178,8 @@ QString BreakpointData::toToolTip() const << "<tr><td>" << tr("Internal Number:") << "</td><td>—</td><td>" << bpNumber << "</td></tr>" << "<tr><td>" << tr("File Name:") - << "</td><td>" << QDir::toNativeSeparators(fileName) << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>" + << "</td><td>" << QDir::toNativeSeparators(fileName) + << "</td><td>" << QDir::toNativeSeparators(bpFileName) << "</td></tr>" << "<tr><td>" << tr("Function Name:") << "</td><td>" << funcName << "</td><td>" << bpFuncName << "</td></tr>" << "<tr><td>" << tr("Line Number:") << "</td><td>"; diff --git a/src/plugins/debugger/breakpoint.h b/src/plugins/debugger/breakpoint.h index eaf6d543dcb7b92d1c8f736130222f9704933414..8bdc3f1108c3d394fe662e61de89fa4e2f43cb8b 100644 --- a/src/plugins/debugger/breakpoint.h +++ b/src/plugins/debugger/breakpoint.h @@ -47,6 +47,14 @@ class BreakHandler; // ////////////////////////////////////////////////////////////////// +enum BreakpointType +{ + BreakpointByFileAndLine, + BreakpointByFunction, + BreakpointByAddress, + Watchpoint, +}; + class BreakpointData { public: @@ -77,13 +85,11 @@ private: friend class BreakHandler; public: - enum Type { BreakpointType, WatchpointType }; - quint64 id; bool enabled; // Should we talk to the debugger engine? bool pending; // Does the debugger engine know about us already? - Type type; // Type of breakpoint. + BreakpointType type; // Type of breakpoint. // This "user requested information" will get stored in the session. QString fileName; // Short name of source file. @@ -118,12 +124,13 @@ public: void setMarkerLineNumber(int lineNumber); int markerLineNumber() const { return m_markerLineNumber; } - bool isSetByFunction() const { return !funcName.isEmpty(); } - bool isSetByFileAndLine() const { return !fileName.isEmpty(); } + bool isWatchpoint() const { return type == Watchpoint; } + bool isBreakpoint() const { return type != Watchpoint; } // Enough for now. Q_DECLARE_TR_FUNCTIONS(BreakHandler) // TODO: move those to breakhandler +private: // Taken from either user input or gdb responses. QString m_markerFileName; // Used to locate the marker. int m_markerLineNumber; diff --git a/src/plugins/debugger/breakwindow.cpp b/src/plugins/debugger/breakwindow.cpp index d54bd821025108abde04af69c481add9df6ad1fe..e672d809778dffcc28a0ef21ae8da371b24cb1d1 100644 --- a/src/plugins/debugger/breakwindow.cpp +++ b/src/plugins/debugger/breakwindow.cpp @@ -81,7 +81,8 @@ BreakpointDialog::BreakpointDialog(QWidget *parent) : QDialog(parent) comboBoxType->insertItem(3, tr("Address")); pathChooserFileName->setExpectedKind(Utils::PathChooser::File); connect(comboBoxType, SIGNAL(activated(int)), SLOT(typeChanged(int))); - lineEditIgnoreCount->setValidator(new QIntValidator(0, 2147483647, lineEditIgnoreCount)); + lineEditIgnoreCount->setValidator( + new QIntValidator(0, 2147483647, lineEditIgnoreCount)); } bool BreakpointDialog::showDialog(BreakpointData *data) diff --git a/src/plugins/debugger/cdb/cdbbreakpoint.cpp b/src/plugins/debugger/cdb/cdbbreakpoint.cpp index f9eaca6bcb4fe0d5567a33df6978dc976f03a69d..154fd37c6f3986c642726ab51635c2c005ae2edd 100644 --- a/src/plugins/debugger/cdb/cdbbreakpoint.cpp +++ b/src/plugins/debugger/cdb/cdbbreakpoint.cpp @@ -38,11 +38,12 @@ namespace Internal { enum { debugBP = 0 }; // Convert breakpoint structs -CdbCore::BreakPoint breakPointFromBreakPointData(const Debugger::Internal::BreakpointData &bpd) +CdbCore::BreakPoint breakPointFromBreakPointData(const BreakpointData &bpd) { CdbCore::BreakPoint rc; - rc.type = bpd.type == Debugger::Internal::BreakpointData::BreakpointType ? - CdbCore::BreakPoint::Code : CdbCore::BreakPoint::Data; + rc.type = bpd.type == Watchpoint ? + CdbCore::BreakPoint::Data : + CdbCore::BreakPoint::Code ; rc.address = bpd.address; if (!bpd.threadSpec.isEmpty()) { diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 9ca120bf4890307074395110d7af4d3d973c930b..93ac1aa6eece03c9e7df8084b7c09ee69a6d2627 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -2114,10 +2114,11 @@ void GdbEngine::setBreakpointDataFromOutput(BreakpointData *data, const GdbMi &b } else if (child.hasName("thread")) { data->bpThreadSpec = child.data(); } else if (child.hasName("type")) { - if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint" - data->type = BreakpointData::BreakpointType; - else // FIXME: Incomplete list of cases. - data->type = BreakpointData::WatchpointType; + // FIXME: This should not change the type. + //if (child.data().contains("reakpoint")) // "breakpoint", "hw breakpoint" + // ; // data->type = BreakpointData::BreakpointType; + //else // FIXME: Incomplete list of cases. + // data->type = Watchpoint; } // This field is not present. Contents needs to be parsed from // the plain "ignore" response. @@ -2179,7 +2180,7 @@ void GdbEngine::sendInsertBreakpoint(int index) const BreakpointData *data = breakHandler()->at(index); // Set up fallback in case of pending breakpoints which aren't handled // by the MI interface. - if (data->type == BreakpointData::WatchpointType) { + if (data->type == Watchpoint) { postCommand("watch " + bpAddressSpec(data->address), NeedsStop | RebuildBreakpointModel, CB(handleWatchInsert), index); diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index cae06f00c89edf4812117fb42ee338ac3c24c40c..464de7e5834a1feaa0482a81954d6577b657a876 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -84,6 +84,36 @@ enum { namespace Debugger { namespace Internal { +struct JSAgentBreakpointData +{ + QByteArray functionName; + QByteArray fileName; + qint32 lineNumber; +}; + +uint qHash(const JSAgentBreakpointData &b) +{ + return b.lineNumber ^ qHash(b.fileName); +} + +QDataStream &operator<<(QDataStream &s, const JSAgentBreakpointData &data) +{ + return s << data.functionName << data.fileName << data.lineNumber; +} + +QDataStream &operator>>(QDataStream &s, JSAgentBreakpointData &data) +{ + return s >> data.functionName >> data.fileName >> data.lineNumber; +} + +bool operator==(const JSAgentBreakpointData &b1, const JSAgentBreakpointData &b2) +{ + return b1.lineNumber == b2.lineNumber && b1.fileName == b2.fileName; +} + +typedef QSet<JSAgentBreakpointData> JSAgentBreakpoints; + + QDataStream &operator>>(QDataStream &s, WatchData &data) { data = WatchData(); @@ -466,27 +496,31 @@ void QmlEngine::attemptBreakpointSynchronization() { Internal::BreakHandler *handler = breakHandler(); //bool updateNeeded = false; - QSet< QPair<QString, qint32> > breakList; + Internal::JSAgentBreakpoints breakpoints; for (int index = 0; index != handler->size(); ++index) { Internal::BreakpointData *data = handler->at(index); QString processedFilename = data->fileName; if (isShadowBuildProject()) processedFilename = toShadowBuildFilename(data->fileName); - breakList << qMakePair(processedFilename, data->lineNumber); + Internal::JSAgentBreakpointData bp; + bp.fileName = processedFilename.toUtf8(); + bp.lineNumber = data->lineNumber; + bp.functionName = data->funcName.toUtf8(); + breakpoints.insert(bp); } QByteArray reply; QDataStream rs(&reply, QIODevice::WriteOnly); rs << QByteArray("BREAKPOINTS"); - rs << breakList; - //qDebug() << Q_FUNC_INFO << breakList; + rs << breakpoints; + //qDebug() << Q_FUNC_INFO << breakpoints; sendMessage(reply); } bool QmlEngine::acceptsBreakpoint(const Internal::BreakpointData *br) { - return br->fileName.endsWith(QLatin1String("qml")) - || br->fileName.endsWith(QLatin1String("js")); + return br->fileName.endsWith(QLatin1String(".qml")) + || br->fileName.endsWith(QLatin1String(".js")); } void QmlEngine::loadSymbols(const QString &moduleName) @@ -624,11 +658,12 @@ void QmlEngine::messageReceived(const QByteArray &message) QByteArray command; stream >> command; - showMessage(QLatin1String("RECEIVED RESPONSE: ") + Internal::quoteUnprintableLatin1(message)); + showMessage(QLatin1String("RECEIVED RESPONSE: ") + + Internal::quoteUnprintableLatin1(message)); + if (command == "STOPPED") { - if (state() == InferiorRunOk) { + if (state() == InferiorRunOk) notifyInferiorSpontaneousStop(); - } Internal::StackFrames stackFrames; QList<Internal::WatchData> watches; @@ -684,11 +719,13 @@ void QmlEngine::messageReceived(const QByteArray &message) // Make breakpoint non-pending // QString file; + QString function; int line = -1; if (!stackFrames.isEmpty()) { file = stackFrames.at(0).file; line = stackFrames.at(0).line; + function = stackFrames.at(0).function; if (isShadowBuildProject()) { file = fromShadowBuildFilename(file); @@ -700,11 +737,11 @@ void QmlEngine::messageReceived(const QByteArray &message) Internal::BreakpointData *data = handler->at(index); QString processedFilename = data->fileName; - if (processedFilename == file - && data->lineNumber == line) { + if (processedFilename == file && data->lineNumber == line) { data->pending = false; data->bpFileName = file; data->bpLineNumber = line; + data->bpFuncName = function; handler->updateMarker(data); } } diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 00dd7c3a4b7c6697b21d1444381e7d9a05b2dce8..8bdb23c50867a9cfd51eccc0f394f052c6751be6 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -835,7 +835,7 @@ bool WatchModel::setData(const QModelIndex &index, const QVariant &value, int ro const int index = handler->findWatchPointIndexByAddress(address); if (index == -1) { BreakpointData *data = new BreakpointData; - data->type = BreakpointData::WatchpointType; + data->type = Watchpoint; data->address = address; handler->appendBreakpoint(data); } else {