diff --git a/share/qtcreator/gdbmacros/dumper.py b/share/qtcreator/gdbmacros/dumper.py index 7e614ff75f64648378850ca4f3b4559f5fa3ec96..e2bda10df3160c232e62ca119769ecee0491c390 100644 --- a/share/qtcreator/gdbmacros/dumper.py +++ b/share/qtcreator/gdbmacros/dumper.py @@ -1047,6 +1047,7 @@ class Dumper: self.useFancy = "fancy" in options self.passExceptions = "pe" in options self.autoDerefPointers = "autoderef" in options + self.partialUpdate = "partial" in options #self.ns = qqNs self.ns = qtNamespace() @@ -1059,9 +1060,29 @@ class Dumper: # # Locals # - locals = listOfLocals(varList) - if "nolocals" in options: - locals = [] + fullUpdateNeeded = True + if self.partialUpdate and len(varList) == 1: + #warn("PARTIAL: %s" % varList) + parts = varList[0].split('.') + #warn("PARTIAL PARTS: %s" % parts) + name = parts[1] + #warn("PARTIAL VAR: %s" % name) + #fullUpdateNeeded = False + try: + frame = gdb.selected_frame() + item = Item(0, "local", name, name) + item.value = frame.read_var(name) + locals = [item] + #warn("PARTIAL LOCALS: %s" % locals) + fullUpdateNeeded = False + except: + pass + varList = [] + + if fullUpdateNeeded: + locals = listOfLocals(varList) + if "nolocals" in options: + locals = [] # Take care of the return value of the last function call. if len(resultVarName) > 0: diff --git a/src/plugins/debugger/cdb/cdbengine.cpp b/src/plugins/debugger/cdb/cdbengine.cpp index 89a655e8cf9d29d4f9ffafdce7861b010ab388b9..c755224809f4674123256ba7f1eb7b7879ad52b0 100644 --- a/src/plugins/debugger/cdb/cdbengine.cpp +++ b/src/plugins/debugger/cdb/cdbengine.cpp @@ -691,7 +691,7 @@ void CdbEngine::evaluateWatcher(WatchData *wd) wd->setHasChildren(false); } -void CdbEngine::updateWatchData(const WatchData &incomplete) +void CdbEngine::updateWatchData(const WatchData &incomplete, const WatchUpdateFlags &flags) { // Watch item was edited while running if (m_d->isDebuggeeRunning()) diff --git a/src/plugins/debugger/cdb/cdbengine.h b/src/plugins/debugger/cdb/cdbengine.h index ebb86f956ee0866453855d5e3e04f0105af3824e..8dba973dd34bddf1165d612ac7239bb359c04712 100644 --- a/src/plugins/debugger/cdb/cdbengine.h +++ b/src/plugins/debugger/cdb/cdbengine.h @@ -62,7 +62,7 @@ public: virtual void shutdownInferior(); virtual void shutdownEngine(); virtual void detachDebugger(); - virtual void updateWatchData(const WatchData &data); + virtual void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); virtual unsigned debuggerCapabilities() const; virtual void executeStep(); diff --git a/src/plugins/debugger/debuggerengine.h b/src/plugins/debugger/debuggerengine.h index b400435e8a970bb42fa03b345e50ff290c46e824..7340efcfae9b849c415757338170cd37d311239a 100644 --- a/src/plugins/debugger/debuggerengine.h +++ b/src/plugins/debugger/debuggerengine.h @@ -130,6 +130,12 @@ class WatchHandler; class DebuggerEnginePrivate; +struct WatchUpdateFlags +{ + WatchUpdateFlags() : tryIncremental(false) {} + bool tryIncremental; +}; + // FIXME: DEBUGGER_EXPORT? class DEBUGGER_EXPORT DebuggerEngine : public QObject { @@ -140,10 +146,11 @@ public: virtual ~DebuggerEngine(); virtual void setToolTipExpression(const QPoint & /* mousePos */, - TextEditor::ITextEditor * /* editor */, int /* cursorPos */) { } + TextEditor::ITextEditor * /* editor */, int /* cursorPos */) {} void initializeFromTemplate(DebuggerEngine *other); - virtual void updateWatchData(const WatchData & /* data */) { } + virtual void updateWatchData(const WatchData & /* data */, + const WatchUpdateFlags & /* flags */ = WatchUpdateFlags()) {} void startDebugger(DebuggerRunControl *runControl); virtual bool isSessionEngine() const { return false; } diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index c0ecd0086ead0d9a702dcf9397988fcbfcd00228..aa9095b2ff091c30d324294ffdf53a02b3219ac1 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -3328,7 +3328,7 @@ bool GdbEngine::hasDebuggingHelperForType(const QByteArray &type) const } -void GdbEngine::updateWatchData(const WatchData &data) +void GdbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { if (isSynchronous()) { // This should only be called for fresh expanded items, not for @@ -3358,7 +3358,22 @@ void GdbEngine::updateWatchData(const WatchData &data) } m_processedNames.insert(processedName); - updateLocals(); + // FIXME: Is this sufficient when "external" changes are + // triggered e.g. by manually entered command in the gdb console? + //qDebug() << "TRY PARTIAL: " << flags.tryIncremental + // << hasPython() + // << (m_pendingWatchRequests == 0) + // << (m_pendingBreakpointRequests == 0); + + bool tryPartial = flags.tryIncremental + && hasPython() + && m_pendingWatchRequests == 0 + && m_pendingBreakpointRequests == 0; + + if (tryPartial) + updateLocalsPython(true, data.iname); + else + updateLocals(); #endif } else { // Bump requests to avoid model rebuilding during the nested @@ -3491,7 +3506,7 @@ void GdbEngine::updateLocals(const QVariant &cookie) m_pendingWatchRequests = 0; m_pendingBreakpointRequests = 0; if (hasPython()) - updateLocalsPython(QByteArray()); + updateLocalsPython(false, QByteArray()); else updateLocalsClassic(cookie); } diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 514f3a9f4824881e65e26abc75ff76aa22d80c9c..d966f1007bafbda6431eb571708367e7d38c27d1 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -460,7 +460,7 @@ private: ////////// View & Data Stuff ////////// // FIXME: BaseClass. called to improve situation for a watch item void updateSubItemClassic(const WatchData &data); - void virtual updateWatchData(const WatchData &data); + void virtual updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); Q_SLOT void updateWatchDataHelper(const WatchData &data); void rebuildWatchModel(); bool showToolTip(); @@ -492,7 +492,7 @@ private: ////////// View & Data Stuff ////////// void updateLocals(const QVariant &cookie = QVariant()); void updateLocalsClassic(const QVariant &cookie); - void updateLocalsPython(const QByteArray &varList); + void updateLocalsPython(bool tryPartial, const QByteArray &varList); void handleStackFramePython(const GdbResponse &response); void handleStackListLocalsClassic(const GdbResponse &response); diff --git a/src/plugins/debugger/gdb/pythongdbengine.cpp b/src/plugins/debugger/gdb/pythongdbengine.cpp index a9da01c2aebb465e8f351e8fcf64008067f45479..63532e148e798f33d381ce55f15810d4a2c29c0f 100644 --- a/src/plugins/debugger/gdb/pythongdbengine.cpp +++ b/src/plugins/debugger/gdb/pythongdbengine.cpp @@ -46,12 +46,11 @@ namespace Debugger { namespace Internal { -void GdbEngine::updateLocalsPython(const QByteArray &varList) +void GdbEngine::updateLocalsPython(bool tryPartial, const QByteArray &varList) { PRECONDITION; m_processedNames.clear(); - - watchHandler()->beginCycle(); + watchHandler()->beginCycle(!tryPartial); //m_toolTipExpression.clear(); WatchHandler *handler = watchHandler(); @@ -84,6 +83,8 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList) options += "pe,"; if (options.isEmpty()) options += "defaults,"; + if (tryPartial) + options += "partial,"; options.chop(1); QByteArray resultVar; @@ -92,7 +93,7 @@ void GdbEngine::updateLocalsPython(const QByteArray &varList) postCommand("bb options:" + options + " vars:" + varList + ' ' + resultVar + expanded + " watchers:" + watchers.toHex(), - WatchUpdate, CB(handleStackFramePython)); + WatchUpdate, CB(handleStackFramePython), QVariant(tryPartial)); } void GdbEngine::handleStackListLocalsPython(const GdbResponse &response) @@ -105,7 +106,7 @@ void GdbEngine::handleStackListLocalsPython(const GdbResponse &response) varList.append(','); varList.append(child.data()); } - updateLocalsPython(varList); + updateLocalsPython(false, varList); } } @@ -113,6 +114,8 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response) { PRECONDITION; if (response.resultClass == GdbResultDone) { + bool partial = response.cookie.toBool(); + //qDebug() << "READING " << (partial ? "PARTIAL" : "FULL"); QByteArray out = response.data.findChild("consolestreamoutput").data(); while (out.endsWith(' ') || out.endsWith('\n')) out.chop(1); diff --git a/src/plugins/debugger/pdb/pdbengine.cpp b/src/plugins/debugger/pdb/pdbengine.cpp index 24b3502842a76835e2babca7e906fca2fa3fb972..5cf93fabbbfc443f827f71b4a8dca4de1b476605 100644 --- a/src/plugins/debugger/pdb/pdbengine.cpp +++ b/src/plugins/debugger/pdb/pdbengine.cpp @@ -556,7 +556,7 @@ void PdbEngine::assignValueInDebugger(const QString &expression, } -void PdbEngine::updateWatchData(const WatchData &data) +void PdbEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { Q_UNUSED(data); updateAll(); diff --git a/src/plugins/debugger/pdb/pdbengine.h b/src/plugins/debugger/pdb/pdbengine.h index bd5afb88cb5061c44ac253ed75f93aa095ffe192..879cde497ba8c506847071a357572fcb634d683c 100644 --- a/src/plugins/debugger/pdb/pdbengine.h +++ b/src/plugins/debugger/pdb/pdbengine.h @@ -103,7 +103,7 @@ private: bool supportsThreads() const { return true; } bool isSynchronous() const { return true; } - void updateWatchData(const WatchData &data); + void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); signals: void outputReady(const QByteArray &data); diff --git a/src/plugins/debugger/qml/qmlcppengine.cpp b/src/plugins/debugger/qml/qmlcppengine.cpp index 17486f657109949247407ad61b5c6088ae7a689c..54c68e3cf76d192314e3c28628a1b970820032b3 100644 --- a/src/plugins/debugger/qml/qmlcppengine.cpp +++ b/src/plugins/debugger/qml/qmlcppengine.cpp @@ -98,9 +98,9 @@ void QmlCppEngine::setToolTipExpression(const QPoint & mousePos, m_activeEngine->setToolTipExpression(mousePos, editor, cursorPos); } -void QmlCppEngine::updateWatchData(const WatchData &data) +void QmlCppEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { - m_activeEngine->updateWatchData(data); + m_activeEngine->updateWatchData(data, flags); } void QmlCppEngine::watchPoint(const QPoint &point) diff --git a/src/plugins/debugger/qml/qmlcppengine.h b/src/plugins/debugger/qml/qmlcppengine.h index d33e010528f70966b0e155edc7d38e6a827508b5..3723347d73edf9abe2ff9d8905ac67388e3bdc94 100644 --- a/src/plugins/debugger/qml/qmlcppengine.h +++ b/src/plugins/debugger/qml/qmlcppengine.h @@ -24,7 +24,7 @@ public: virtual void setToolTipExpression(const QPoint & /* mousePos */, TextEditor::ITextEditor * /* editor */, int /* cursorPos */); - virtual void updateWatchData(const WatchData & /* data */); + virtual void updateWatchData(const WatchData & /* data */, const WatchUpdateFlags &flags); virtual void watchPoint(const QPoint &); virtual void fetchMemory(MemoryViewAgent *, QObject *, diff --git a/src/plugins/debugger/qml/qmlengine.cpp b/src/plugins/debugger/qml/qmlengine.cpp index bde16e30dc540fb6edce3bced1c13f1fef503ad8..d54a934c0355ef1c14621d2f8280c392b1e28a9e 100644 --- a/src/plugins/debugger/qml/qmlengine.cpp +++ b/src/plugins/debugger/qml/qmlengine.cpp @@ -476,7 +476,7 @@ void QmlEngine::assignValueInDebugger(const QString &expression, } } -void QmlEngine::updateWatchData(const WatchData &data) +void QmlEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &) { // qDebug() << "UPDATE WATCH DATA" << data.toString(); //watchHandler()->rebuildModel(); diff --git a/src/plugins/debugger/qml/qmlengine.h b/src/plugins/debugger/qml/qmlengine.h index 31f08d027986262721adc5986345b586d2b28efd..76da03384c8cdb553ce60af8cb0508ea96f9f827 100644 --- a/src/plugins/debugger/qml/qmlengine.h +++ b/src/plugins/debugger/qml/qmlengine.h @@ -117,7 +117,7 @@ private: void reloadFullStack() {} bool supportsThreads() const { return false; } - void updateWatchData(const WatchData &data); + void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); void executeDebuggerCommand(const QString& command); unsigned int debuggerCapabilities() const; diff --git a/src/plugins/debugger/script/scriptengine.cpp b/src/plugins/debugger/script/scriptengine.cpp index 08e846b446bbe1ef95f8821d361ccc7da175657d..e17ca50580beff56d3f6920150dddf0c7ddfe0fc 100644 --- a/src/plugins/debugger/script/scriptengine.cpp +++ b/src/plugins/debugger/script/scriptengine.cpp @@ -721,7 +721,7 @@ void ScriptEngine::updateLocals() notifyInferiorRunOk(); } -void ScriptEngine::updateWatchData(const WatchData &data) +void ScriptEngine::updateWatchData(const WatchData &data, const WatchUpdateFlags &flags) { updateSubItem(data); } diff --git a/src/plugins/debugger/script/scriptengine.h b/src/plugins/debugger/script/scriptengine.h index b27ba493e647071df4d2393d5684ab5f4699e265..fe6572e025c64dccb8feed564ed96004b616365a 100644 --- a/src/plugins/debugger/script/scriptengine.h +++ b/src/plugins/debugger/script/scriptengine.h @@ -101,7 +101,7 @@ private: bool supportsThreads() const { return true; } bool checkForBreakCondition(bool byFunction); - void updateWatchData(const WatchData &data); + void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); void updateLocals(); void updateSubItem(const WatchData &data); diff --git a/src/plugins/debugger/tcf/tcfengine.cpp b/src/plugins/debugger/tcf/tcfengine.cpp index 88a2d33bbb1552b8981c058b1ff330f7318dbc7b..3e76236ecbb8b2954dfd45fab44144c35fdd263a 100644 --- a/src/plugins/debugger/tcf/tcfengine.cpp +++ b/src/plugins/debugger/tcf/tcfengine.cpp @@ -554,7 +554,7 @@ void TcfEngine::updateLocals() { } -void TcfEngine::updateWatchData(const WatchData &) +void TcfEngine::updateWatchData(const WatchData &, const WatchUpdateFlags &) { //qq->watchHandler()->rebuildModel(); showStatusMessage(tr("Stopped."), 5000); diff --git a/src/plugins/debugger/tcf/tcfengine.h b/src/plugins/debugger/tcf/tcfengine.h index 583a28734b08f5010562e387dc771900c805ba74..2ab8db8a014545aa16b99525a421157fbadfdb5a 100644 --- a/src/plugins/debugger/tcf/tcfengine.h +++ b/src/plugins/debugger/tcf/tcfengine.h @@ -106,7 +106,7 @@ private: bool supportsThreads() const { return true; } void maybeBreakNow(bool byFunction); - void updateWatchData(const WatchData &data); + void updateWatchData(const WatchData &data, const WatchUpdateFlags &flags); void updateLocals(); void updateSubItem(const WatchData &data); diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index 13bdfb288a987a35adb5af91f99d4fa1c8722475..dbfa14b899e967a8186bad4fc8d99d5abcdcdf43 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -487,7 +487,9 @@ void WatchModel::fetchMore(const QModelIndex &index) if (item->children.isEmpty()) { WatchData data = *item; data.setChildrenNeeded(); - engine()->updateWatchData(data); + WatchUpdateFlags flags; + flags.tryIncremental = true; + engine()->updateWatchData(data, flags); } } @@ -1146,16 +1148,17 @@ WatchHandler::WatchHandler(DebuggerEngine *engine) SIGNAL(triggered()), this, SLOT(emitAllChanged())); } -void WatchHandler::beginCycle() +void WatchHandler::beginCycle(bool fullCycle) { - ++generationCounter; + if (fullCycle) + ++generationCounter; m_return->beginCycle(); m_locals->beginCycle(); m_watchers->beginCycle(); m_tooltips->beginCycle(); } -void WatchHandler::endCycle() +void WatchHandler::endCycle(bool /*fullCycle*/) { m_return->endCycle(); m_locals->endCycle(); diff --git a/src/plugins/debugger/watchhandler.h b/src/plugins/debugger/watchhandler.h index 6ee27029c1aa628e7a811496f3b36867f43607ae..85e8f671bdad90b0074ad3253055f4941f0226aa 100644 --- a/src/plugins/debugger/watchhandler.h +++ b/src/plugins/debugger/watchhandler.h @@ -143,9 +143,9 @@ public: void removeWatchExpression(const QString &exp); Q_SLOT void emitAllChanged(); - void beginCycle(); // Called at begin of updateLocals() cycle + void beginCycle(bool fullCycle = true); // Called at begin of updateLocals() cycle void updateWatchers(); // Called after locals are fetched - void endCycle(); // Called after all results have been received + void endCycle(bool fullCycle = true); // Called after all results have been received void showEditValue(const WatchData &data); void insertData(const WatchData &data); diff --git a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp index 61edeb1069f73dae070a6d2934fa1d14456880c2..be858a91eaf5f4492637b9840de7fb743cf94242 100644 --- a/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp +++ b/tests/manual/gdbdebugger/simple/simple_gdbtest_app.cpp @@ -793,6 +793,7 @@ public: void testQObject(int &argc, char *argv[]) { QApplication app(argc, argv); + QString longString = QString(10000, QLatin1Char('A')); #if 1 Names::Bar::TestObject test; test.setMyProp1("HELLO");