Commit 452f108a authored by hjk's avatar hjk

debugger: fixes and improvements related to the Locals display

Split the concepts 'enabled' and 'editable' in the dumper output
Disable "<not in scope>" entries, also fix their type.
Fix glitch in type beautification for display
Find reason for failing bulk updates.
parent 7503d1bc
This diff is collapsed.
......@@ -319,9 +319,7 @@ void DebuggerManager::init()
//qRegisterMetaType<WatchData>("Debugger::Internal::WatchData");
qRegisterMetaType<WatchData>("WatchData");
connect(m_watchHandler, SIGNAL(watchDataUpdateNeeded(WatchData)),
this, SLOT(updateWatchDataAnnounce()));
connect(m_watchHandler, SIGNAL(watchDataUpdateNeeded(WatchData)),
this, SLOT(updateWatchData(WatchData)), Qt::QueuedConnection);
this, SLOT(updateWatchData(WatchData)));
m_continueAction = new QAction(this);
m_continueAction->setText(tr("Continue"));
......@@ -695,12 +693,6 @@ void DebuggerManager::updateWatchData(const WatchData &data)
m_engine->updateWatchData(data);
}
void DebuggerManager::updateWatchDataAnnounce()
{
if (m_engine)
m_engine->updateWatchDataAnnounce();
}
static inline QString msgEngineNotAvailable(const char *engine)
{
return DebuggerManager::tr("The application requires the debugger engine '%1', which is disabled.").arg(QLatin1String(engine));
......
......@@ -57,6 +57,7 @@
#include <QtCore/QDebug>
#include <QtCore/QDir>
#include <QtCore/QFileInfo>
#include <QtCore/QMetaObject>
#include <QtCore/QTime>
#include <QtCore/QTimer>
#include <QtCore/QTextStream>
......@@ -2814,12 +2815,20 @@ static void setWatchDataChildCount(WatchData &data, const GdbMi &mi)
data.setHasChildren(mi.data().toInt() > 0);
}
static void setWatchDataValueDisabled(WatchData &data, const GdbMi &mi)
static void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi)
{
if (mi.data() == "true")
data.valuedisabled = true;
data.valueEnabled = true;
else if (mi.data() == "false")
data.valuedisabled = false;
data.valueEnabled = false;
}
static void setWatchDataValueEditable(WatchData &data, const GdbMi &mi)
{
if (mi.data() == "true")
data.valueEditable = true;
else if (mi.data() == "false")
data.valueEditable = false;
}
static void setWatchDataExpression(WatchData &data, const GdbMi &mi)
......@@ -3127,20 +3136,26 @@ void GdbEngine::updateSubItem(const WatchData &data0)
QTC_ASSERT(false, return);
}
void GdbEngine::updateWatchDataAnnounce()
void GdbEngine::updateWatchData(const WatchData &data)
{
// Bump requests to avoid model rebuilding during the nested
// updateWatchModel runs.
++m_pendingRequests;
#if 1
QMetaObject::invokeMethod(this, "updateWatchDataHelper",
Qt::QueuedConnection, Q_ARG(WatchData, data));
#else
updateWatchDataHelper(data);
#endif
}
void GdbEngine::updateWatchData(const WatchData &data)
void GdbEngine::updateWatchDataHelper(const WatchData &data)
{
//m_pendingRequests = 0;
PENDING_DEBUG("UPDATE WATCH DATA");
#if DEBUG_PENDING
//qDebug() << "##############################################";
//qDebug() << "UPDATE MODEL, FOUND INCOMPLETE:";
qDebug() << "UPDATE MODEL, FOUND INCOMPLETE:";
//qDebug() << data.toString();
#endif
......@@ -3153,9 +3168,11 @@ void GdbEngine::updateWatchData(const WatchData &data)
void GdbEngine::rebuildModel()
{
static int count = 0;
++count;
m_processedNames.clear();
PENDING_DEBUG("REBUILDING MODEL");
emit gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel>"));
PENDING_DEBUG("REBUILDING MODEL" << count);
emit gdbInputAvailable(LogStatus, _("<Rebuild Watchmodel %1>").arg(count));
q->showStatusMessage(tr("Finished retrieving data."), 400);
qq->watchHandler()->endCycle();
showToolTip();
......@@ -3330,7 +3347,8 @@ void GdbEngine::handleVarCreate(const GdbResultRecord &record,
data.type = _(" ");
data.setAllUnneeded();
data.setHasChildren(false);
data.valuedisabled = true;
data.valueEnabled = false;
data.valueEditable = false;
insertData(data);
}
}
......@@ -3445,7 +3463,8 @@ void GdbEngine::handleChildren(const WatchData &data0, const GdbMi &item,
setWatchDataSAddress(data, item.findChild("saddr"));
setWatchDataValueToolTip(data, item.findChild("valuetooltip"),
item.findChild("valuetooltipencoded").data().toInt());
setWatchDataValueDisabled(data, item.findChild("valuedisabled"));
setWatchDataValueEnabled(data, item.findChild("valueenabled"));
setWatchDataValueEditable(data, item.findChild("valueeditable"));
//qDebug() << "HANDLE CHILDREN: " << data.toString();
list->append(data);
......@@ -3495,7 +3514,7 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResultRecord &record,
// << " STREAM:" << out;
if (list.isEmpty()) {
//: Value for variable
data.setValue(strNotInScope);
data.setError(strNotInScope);
data.setAllUnneeded();
insertData(data);
} else if (data.type == __("QString")
......@@ -3540,13 +3559,13 @@ void GdbEngine::handleDebuggingHelperValue3(const GdbResultRecord &record,
}
} else {
//: Value for variable
data.setValue(strNotInScope);
data.setError(strNotInScope);
data.setAllUnneeded();
insertData(data);
}
} else if (record.resultClass == GdbResultError) {
WatchData data = cookie.value<WatchData>();
data.setValue(strNotInScope);
data.setError(strNotInScope);
data.setAllUnneeded();
insertData(data);
}
......@@ -3628,6 +3647,7 @@ void GdbEngine::setLocals(const QList<GdbMi> &locals)
//qDebug() << m_varToType;
QMap<QByteArray, int> seen;
QList<WatchData> list;
foreach (const GdbMi &item, locals) {
// Local variables of inlined code are reported as
// 26^done,locals={varobj={exp="this",value="",name="var4",exp="this",
......@@ -3657,7 +3677,7 @@ void GdbEngine::setLocals(const QList<GdbMi> &locals)
//variable of the same name in a nested block
data.setType(tr("<shadowed>"));
data.setHasChildren(false);
insertData(data);
list.append(data);
} else {
seen[name] = 1;
WatchData data;
......@@ -3679,9 +3699,10 @@ void GdbEngine::setLocals(const QList<GdbMi> &locals)
qDebug() << "RE-USING" << m_varToType.value(data.framekey);
data.setType(m_varToType.value(data.framekey));
}
insertData(data);
list.append(data);
}
}
qq->watchHandler()->insertBulkData(list);
}
void GdbEngine::insertData(const WatchData &data0)
......@@ -3698,7 +3719,6 @@ void GdbEngine::insertData(const WatchData &data0)
void GdbEngine::handleVarListChildrenHelper(const GdbMi &item,
const WatchData &parent)
{
//qDebug() << "VAR_LIST_CHILDREN: PARENT 2" << parent.toString();
//qDebug() << "VAR_LIST_CHILDREN: APPENDEE" << data.toString();
QByteArray exp = item.findChild("exp").data();
QByteArray name = item.findChild("name").data();
......
......@@ -332,7 +332,7 @@ private:
void updateSubItem(const WatchData &data);
void updateWatchData(const WatchData &data);
void updateWatchDataAnnounce();
Q_SLOT void updateWatchDataHelper(const WatchData &data);
void rebuildModel();
void insertData(const WatchData &data);
......
......@@ -63,7 +63,6 @@ public:
virtual bool startDebugger(const QSharedPointer<DebuggerStartParameters> &startParameters) = 0;
virtual void exitDebugger() = 0;
virtual void detachDebugger() {}
virtual void updateWatchDataAnnounce() {}
virtual void updateWatchData(const WatchData &data) = 0;
virtual void stepExec() = 0;
......
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>
#include <QtCore/QProcess>
#if defined(Q_OS_LINUX)
#include <stdio.h>
#include <signal.h>
#include <execinfo.h>
#endif
namespace Debugger {
namespace Internal {
void dumpBacktrace(int maxdepth)
{
if (maxdepth == -1)
maxdepth = 200;
#if defined(Q_OS_LINUX)
void *bt[200] = {0};
qDebug() << "BACKTRACE:";
int size = backtrace(bt, sizeof(bt) / sizeof(bt[0]));
for (int i = 0; i < qMin(size, maxdepth); i++)
qDebug() << "0x" + QByteArray::number(quintptr(bt[i]), 16);
QProcess proc;
QStringList args;
args.append("-e");
args.append(QCoreApplication::arguments().at(0));
proc.start("addr2line", args);
proc.waitForStarted();
for (int i = 0; i < qMin(size, maxdepth); i++)
proc.write("0x" + QByteArray::number(quintptr(bt[i]), 16) + "\n");
proc.closeWriteChannel();
QByteArray out = proc.readAllStandardOutput();
qDebug() << QCoreApplication::arguments().at(0);
qDebug() << out;
proc.waitForFinished();
out = proc.readAllStandardOutput();
qDebug() << out;
#endif
}
/*
void installSignalHandlers()
{
#if defined(Q_OS_LINUX)
struct sigaction SignalAction;
SignalAction.sa_sigaction = handler;
sigemptyset(&SignalAction.sa_mask);
SignalAction.sa_flags = SA_SIGINFO;
sigaction(SIGSEGV, &SignalAction, NULL);
sigaction(SIGABRT, &SignalAction, NULL);
#endif
}
*/
} // namespace Internal
} // namespace Debugger
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef DEBUGGER_BACKTRACE_H
#define DEBUGGER_BACKTRACE_H
#include <QtCore/qglobal.h>
namespace Debugger {
namespace Internal {
void dumpBacktrace(int maxdepth = -1);
} // namespace Internal
} // namespace Debugger
#endif // DEBUGGER_BACKTRACE_H
SOURCES += $$PWD/backtrace.cpp
HEADERS += $$PWD/backtrace.h
win32 {
INCLUDEPATH+=$$PWD
......
This diff is collapsed.
......@@ -111,6 +111,8 @@ public:
bool isLocal() const { return iname.startsWith(QLatin1String("local.")); }
bool isWatcher() const { return iname.startsWith(QLatin1String("watch.")); }
bool isValid() const { return !iname.isEmpty(); }
bool isEqual(const WatchData &other) const;
public:
QString iname; // internal name sth like 'local.baz.public.a'
......@@ -128,7 +130,8 @@ public:
QScriptValue scriptValue; // if needed...
bool hasChildren;
int generation; // when updated?
bool valuedisabled; // value will be greyed out
bool valueEnabled; // value will be greyed out or not
bool valueEditable; // value will be editable
private:
......@@ -204,8 +207,16 @@ private:
void emitDataChanged(int column,
const QModelIndex &parentIndex = QModelIndex());
void beginCycle(); // called at begin of updateLocals() cycle
void endCycle(); // called after all results have been received
friend QDebug operator<<(QDebug d, const WatchModel &m);
void dump();
void dumpHelper(WatchItem *item);
signals:
void enableUpdates(bool);
private:
WatchHandler *m_handler;
WatchType m_type;
......
......@@ -491,7 +491,7 @@ QtDumperResult::Child::Child() :
keyEncoded(0),
valueEncoded(0),
childCount(-1),
valuedisabled(false),
valueEnabled(true),
valueEncountered(false)
{
}
......@@ -499,7 +499,7 @@ QtDumperResult::Child::Child() :
QtDumperResult::QtDumperResult() :
valueEncountered(false),
valueEncoded(0),
valuedisabled(false),
valueEnabled(true),
childCount(-1),
internal(false),
childChildCount(-1)
......@@ -516,7 +516,8 @@ void QtDumperResult::clear()
extra.clear();
displayedType.clear();
valueEncoded = 0;
valueEncountered = valuedisabled = false;
valueEncountered = false;
valueEnabled = false;
childCount = -1;
internal = false;
childType.clear();
......@@ -535,7 +536,7 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
root.exp = root.name = lastDotIndex == -1 ? iname : iname.mid(lastDotIndex + 1);
if (valueEncountered) {
root.setValue(decodeData(value, valueEncoded));
root.valuedisabled = valuedisabled;
root.valueEnabled = valueEnabled;
}
root.setType(type);
if (!displayedType.isEmpty())
......@@ -575,7 +576,7 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
wchild.iname += iname;
wchild.exp = dchild.exp;
if (dchild.valueEncountered) {
wchild.valuedisabled = dchild.valuedisabled;
wchild.valueEnabled = dchild.valueEnabled;
wchild.setValue(decodeData(dchild.value, dchild.valueEncoded));
}
wchild.setAddress(dchild.address);
......@@ -611,14 +612,15 @@ QList<WatchData> QtDumperResult::toWatchData(int source) const
QDebug operator<<(QDebug in, const QtDumperResult &d)
{
QDebug nospace = in.nospace();
nospace << " iname=" << d.iname << " type=" << d.type << " displayed=" << d.displayedType
nospace << " iname=" << d.iname << " type=" << d.type
<< " displayed=" << d.displayedType
<< " address=" << d.address;
if (!d.addressInfo.isEmpty())
nospace << " addressInfo=" << d.addressInfo;
if (d.valueEncountered) {
nospace << " encoded=" << d.valueEncoded
<< " value=" << d.value
<< " disabled=" << d.valuedisabled;
<< " enabled=" << d.valueEnabled;
} else {
nospace << " <no value>";
}
......@@ -633,7 +635,7 @@ QDebug operator<<(QDebug in, const QtDumperResult &d)
for (int i = 0; i < realChildCount; i++) {
const QtDumperResult::Child &c = d.children.at(i);
nospace << " #" << i << " addr=" << c.address
<< " disabled=" << c.valuedisabled
<< " enabled=" << c.valueEnabled
<< " type=" << c.type << " exp=" << c.exp
<< " name=" << c.name;
if (!c.key.isEmpty())
......@@ -1518,7 +1520,7 @@ protected:
private:
enum Mode { None, ExpectingIName, ExpectingAddress, ExpectingValue,
ExpectingType, ExpectingDisplayedType, ExpectingInternal,
ExpectingValueDisabled, ExpectingValueEncoded,
ExpectingValueEnabled, ExpectingValueEncoded,
ExpectingCommonChildType, ExpectingChildCount,
ExpectingChildChildOverrideCount,
ExpectingExtra,
......@@ -1529,7 +1531,7 @@ private:
ExpectingChildDisplayedType,
ExpectingChildKey, ExpectingChildKeyEncoded,
ExpectingChildValue, ExpectingChildValueEncoded,
ExpectingChildValueDisabled, ExpectingChildChildCount,
ExpectingChildValueEnabled, ExpectingChildChildCount,
IgnoreNextChildMode
};
......@@ -1593,8 +1595,8 @@ ValueDumperParser::Mode ValueDumperParser::nextMode(Mode in, const char *keyword
return in > ChildModeStart ? ExpectingChildValueEncoded : ExpectingValueEncoded;
break;
case 13:
if (!qstrncmp(keyword, "valuedisabled", size))
return in > ChildModeStart ? ExpectingChildValueDisabled : ExpectingValueDisabled;
if (!qstrncmp(keyword, "valueenabled", size))
return in > ChildModeStart ? ExpectingChildValueEnabled : ExpectingValueEnabled;
if (!qstrncmp(keyword, "displayedtype", size))
return in > ChildModeStart ? ExpectingChildDisplayedType : ExpectingDisplayedType;
if (!qstrncmp(keyword, "childnumchild", size))
......@@ -1642,8 +1644,8 @@ bool ValueDumperParser::handleValue(const char *k, int size)
m_result.valueEncountered = true;
m_result.value = valueBA;
break;
case ExpectingValueDisabled:
m_result.valuedisabled = valueBA == "true";
case ExpectingValueEnabled:
m_result.valueEnabled = valueBA == "true";
break;
case ExpectingValueEncoded:
m_result.valueEncoded = QString::fromLatin1(valueBA).toInt();
......@@ -1695,8 +1697,8 @@ bool ValueDumperParser::handleValue(const char *k, int size)
case ExpectingChildValueEncoded:
m_result.children.back().valueEncoded = QString::fromLatin1(valueBA).toInt();
break;
case ExpectingChildValueDisabled:
m_result.children.back().valuedisabled = valueBA == "true";
case ExpectingChildValueEnabled:
m_result.children.back().valueEnabled = valueBA == "true";
break;
case ExpectingChildType:
m_result.children.back().type = QString::fromLatin1(valueBA);
......
......@@ -97,7 +97,7 @@ struct QtDumperResult
int keyEncoded;
int valueEncoded;
int childCount;
bool valuedisabled;
bool valueEnabled;
QString name;
QString address;
QString exp;
......@@ -121,7 +121,7 @@ struct QtDumperResult
bool valueEncountered;
QByteArray value;
int valueEncoded;
bool valuedisabled;
bool valueEnabled;
int childCount;
bool internal;
QString childType;
......
......@@ -353,7 +353,16 @@ void WatchWindow::setModel(QAbstractItemModel *model)
if (m_type != LocalsType)
header()->hide();
connect(model, SIGNAL(layoutChanged()), this, SLOT(resetHelper()));
connect(model, SIGNAL(layoutChanged()),
this, SLOT(resetHelper()));
connect(model, SIGNAL(enableUpdates(bool)),
this, SLOT(setUpdatesEnabled(bool)));
}
void WatchWindow::setUpdatesEnabled(bool enable)
{
//qDebug() << "ENABLING UPDATES: " << enable;
QTreeView::setUpdatesEnabled(enable);
}
void WatchWindow::resetHelper()
......
......@@ -64,6 +64,7 @@ private:
Q_SLOT void resetHelper();
Q_SLOT void expandNode(const QModelIndex &idx);
Q_SLOT void collapseNode(const QModelIndex &idx);
Q_SLOT void setUpdatesEnabled(bool enable);
void keyPressEvent(QKeyEvent *ev);
void contextMenuEvent(QContextMenuEvent *ev);
......
......@@ -90,6 +90,20 @@ public:
int t = 2;
b = 2 + s + t;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
a += 1;
}
~Foo()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment