forked from qt-creator/qt-creator
Debugger: Use direct access to WatchItems in GDB engine
Change-Id: I6b9735de1855203ce0586c4ee0c8991a13fb0bad Reviewed-by: Christian Stenger <christian.stenger@theqtcompany.com>
This commit is contained in:
@@ -4939,27 +4939,7 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
|||||||
}
|
}
|
||||||
|
|
||||||
WatchHandler *handler = watchHandler();
|
WatchHandler *handler = watchHandler();
|
||||||
QList<WatchData> list;
|
|
||||||
|
|
||||||
if (!partial) {
|
|
||||||
list.append(*handler->findData("local"));
|
|
||||||
list.append(*handler->findData("watch"));
|
|
||||||
list.append(*handler->findData("return"));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (const GdbMi &child, data.children()) {
|
|
||||||
WatchData dummy;
|
|
||||||
dummy.iname = child["iname"].data();
|
|
||||||
GdbMi wname = child["wname"];
|
|
||||||
if (wname.isValid()) {
|
|
||||||
// Happens (only) for watched expressions.
|
|
||||||
dummy.name = QString::fromUtf8(QByteArray::fromHex(wname.data()));
|
|
||||||
dummy.exp = dummy.name.toUtf8();
|
|
||||||
} else {
|
|
||||||
dummy.name = _(child["name"].data());
|
|
||||||
}
|
|
||||||
parseWatchData(handler->expandedINames(), dummy, child, &list);
|
|
||||||
}
|
|
||||||
const GdbMi typeInfo = all["typeinfo"];
|
const GdbMi typeInfo = all["typeinfo"];
|
||||||
if (typeInfo.type() == GdbMi::List) {
|
if (typeInfo.type() == GdbMi::List) {
|
||||||
foreach (const GdbMi &s, typeInfo.children()) {
|
foreach (const GdbMi &s, typeInfo.children()) {
|
||||||
@@ -4970,13 +4950,38 @@ void GdbEngine::handleStackFramePython(const GdbResponse &response)
|
|||||||
TypeInfo(size.data().toUInt()));
|
TypeInfo(size.data().toUInt()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (int i = 0; i != list.size(); ++i) {
|
|
||||||
const TypeInfo ti = m_typeInfoCache.value(list.at(i).type);
|
QSet<QByteArray> toDelete;
|
||||||
if (ti.size)
|
if (!partial) {
|
||||||
list[i].size = ti.size;
|
foreach (WatchItem *item, handler->model()->treeLevelItems<WatchItem *>(2))
|
||||||
|
toDelete.insert(item->d.iname);
|
||||||
}
|
}
|
||||||
|
|
||||||
handler->insertData(list);
|
foreach (const GdbMi &child, data.children()) {
|
||||||
|
QByteArray iname = child["iname"].data();
|
||||||
|
QString name;
|
||||||
|
|
||||||
|
GdbMi wname = child["wname"];
|
||||||
|
if (wname.isValid()) // Happens (only) for watched expressions.
|
||||||
|
name = QString::fromUtf8(QByteArray::fromHex(wname.data()));
|
||||||
|
else
|
||||||
|
name = _(child["name"].data());
|
||||||
|
|
||||||
|
WatchItem *item = new WatchItem(iname, name);
|
||||||
|
item->parseWatchData(handler->expandedINames(), child);
|
||||||
|
|
||||||
|
const TypeInfo ti = m_typeInfoCache.value(item->d.type);
|
||||||
|
if (ti.size)
|
||||||
|
item->d.size = ti.size;
|
||||||
|
|
||||||
|
if (wname.isValid())
|
||||||
|
item->d.exp = name.toUtf8();
|
||||||
|
|
||||||
|
handler->insertItem(item);
|
||||||
|
toDelete.remove(item->d.iname);
|
||||||
|
}
|
||||||
|
|
||||||
|
handler->purgeOutdatedItems(toDelete);
|
||||||
|
|
||||||
//PENDING_DEBUG("AFTER handleStackFrame()");
|
//PENDING_DEBUG("AFTER handleStackFrame()");
|
||||||
// FIXME: This should only be used when updateLocals() was
|
// FIXME: This should only be used when updateLocals() was
|
||||||
|
@@ -535,7 +535,7 @@ QString decodeItemHelper(const double &t)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template <class T>
|
template <class T>
|
||||||
void decodeArrayHelper(QList<WatchData> *list, const WatchData &tmplate,
|
void decodeArrayHelper(std::function<void(const WatchData &)> itemHandler, const WatchData &tmplate,
|
||||||
const QByteArray &rawData)
|
const QByteArray &rawData)
|
||||||
{
|
{
|
||||||
const QByteArray ba = QByteArray::fromHex(rawData);
|
const QByteArray ba = QByteArray::fromHex(rawData);
|
||||||
@@ -551,43 +551,43 @@ void decodeArrayHelper(QList<WatchData> *list, const WatchData &tmplate,
|
|||||||
data.address += i * sizeof(T);
|
data.address += i * sizeof(T);
|
||||||
data.exp = exp + QByteArray::number(data.address, 16);
|
data.exp = exp + QByteArray::number(data.address, 16);
|
||||||
data.setAllUnneeded();
|
data.setAllUnneeded();
|
||||||
list->append(data);
|
itemHandler(data);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void decodeArray(QList<WatchData> *list, const WatchData &tmplate,
|
void decodeArrayData(std::function<void(const WatchData &)> itemHandler, const WatchData &tmplate,
|
||||||
const QByteArray &rawData, int encoding)
|
const QByteArray &rawData, int encoding)
|
||||||
{
|
{
|
||||||
switch (encoding) {
|
switch (encoding) {
|
||||||
case Hex2EncodedInt1:
|
case Hex2EncodedInt1:
|
||||||
decodeArrayHelper<signed char>(list, tmplate, rawData);
|
decodeArrayHelper<signed char>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedInt2:
|
case Hex2EncodedInt2:
|
||||||
decodeArrayHelper<short>(list, tmplate, rawData);
|
decodeArrayHelper<short>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedInt4:
|
case Hex2EncodedInt4:
|
||||||
decodeArrayHelper<int>(list, tmplate, rawData);
|
decodeArrayHelper<int>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedInt8:
|
case Hex2EncodedInt8:
|
||||||
decodeArrayHelper<qint64>(list, tmplate, rawData);
|
decodeArrayHelper<qint64>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedUInt1:
|
case Hex2EncodedUInt1:
|
||||||
decodeArrayHelper<uchar>(list, tmplate, rawData);
|
decodeArrayHelper<uchar>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedUInt2:
|
case Hex2EncodedUInt2:
|
||||||
decodeArrayHelper<ushort>(list, tmplate, rawData);
|
decodeArrayHelper<ushort>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedUInt4:
|
case Hex2EncodedUInt4:
|
||||||
decodeArrayHelper<uint>(list, tmplate, rawData);
|
decodeArrayHelper<uint>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedUInt8:
|
case Hex2EncodedUInt8:
|
||||||
decodeArrayHelper<quint64>(list, tmplate, rawData);
|
decodeArrayHelper<quint64>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedFloat4:
|
case Hex2EncodedFloat4:
|
||||||
decodeArrayHelper<float>(list, tmplate, rawData);
|
decodeArrayHelper<float>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
case Hex2EncodedFloat8:
|
case Hex2EncodedFloat8:
|
||||||
decodeArrayHelper<double>(list, tmplate, rawData);
|
decodeArrayHelper<double>(itemHandler, tmplate, rawData);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
qDebug() << "ENCODING ERROR: " << encoding;
|
qDebug() << "ENCODING ERROR: " << encoding;
|
||||||
@@ -714,9 +714,9 @@ void parseWatchData(const QSet<QByteArray> &expandedINames,
|
|||||||
const WatchData &innerData, const GdbMi &innerInput) {
|
const WatchData &innerData, const GdbMi &innerInput) {
|
||||||
parseWatchData(expandedINames, innerData, innerInput, list);
|
parseWatchData(expandedINames, innerData, innerInput, list);
|
||||||
};
|
};
|
||||||
auto arrayDecoder = [list](const WatchData &childTemplate,
|
auto arrayDecoder = [itemHandler](const WatchData &childTemplate,
|
||||||
const QByteArray &encodedData, int encoding) {
|
const QByteArray &encodedData, int encoding) {
|
||||||
decodeArray(list, childTemplate, encodedData, encoding);
|
decodeArrayData(itemHandler, childTemplate, encodedData, encoding);
|
||||||
};
|
};
|
||||||
|
|
||||||
parseChildrenData(expandedINames, data0, input, itemHandler, childHandler, arrayDecoder);
|
parseChildrenData(expandedINames, data0, input, itemHandler, childHandler, arrayDecoder);
|
||||||
|
@@ -154,6 +154,11 @@ public:
|
|||||||
qint32 source; // Originated from dumper or symbol evaluation? (CDB only)
|
qint32 source; // Originated from dumper or symbol evaluation? (CDB only)
|
||||||
};
|
};
|
||||||
|
|
||||||
|
void decodeArrayData(std::function<void(const WatchData &)> itemHandler,
|
||||||
|
const WatchData &tmplate,
|
||||||
|
const QByteArray &rawData,
|
||||||
|
int encoding);
|
||||||
|
|
||||||
void parseChildrenData(const QSet<QByteArray> &expandedINames,
|
void parseChildrenData(const QSet<QByteArray> &expandedINames,
|
||||||
const WatchData &parent, const GdbMi &child,
|
const WatchData &parent, const GdbMi &child,
|
||||||
std::function<void(const WatchData &)> itemHandler,
|
std::function<void(const WatchData &)> itemHandler,
|
||||||
|
@@ -261,6 +261,8 @@ public:
|
|||||||
void checkTree(WatchItem *item, QSet<QByteArray> *inames);
|
void checkTree(WatchItem *item, QSet<QByteArray> *inames);
|
||||||
#endif
|
#endif
|
||||||
void checkIndex(const QModelIndex &index) const;
|
void checkIndex(const QModelIndex &index) const;
|
||||||
|
void insertItem(WatchItem *item);
|
||||||
|
void reexpandItems();
|
||||||
};
|
};
|
||||||
|
|
||||||
WatchModel::WatchModel(WatchHandler *handler)
|
WatchModel::WatchModel(WatchHandler *handler)
|
||||||
@@ -642,6 +644,8 @@ bool WatchItem::canFetchMore() const
|
|||||||
{
|
{
|
||||||
if (!d.hasChildren)
|
if (!d.hasChildren)
|
||||||
return false;
|
return false;
|
||||||
|
if (!watchModel())
|
||||||
|
return false;
|
||||||
if (!watchModel()->contentIsValid() && !d.isInspect())
|
if (!watchModel()->contentIsValid() && !d.isInspect())
|
||||||
return false;
|
return false;
|
||||||
return !fetchTriggered;
|
return !fetchTriggered;
|
||||||
@@ -834,6 +838,7 @@ QVariant WatchItem::data(int column, int role) const
|
|||||||
static const QVariant red(QColor(200, 0, 0));
|
static const QVariant red(QColor(200, 0, 0));
|
||||||
static const QVariant gray(QColor(140, 140, 140));
|
static const QVariant gray(QColor(140, 140, 140));
|
||||||
if (column == 1) {
|
if (column == 1) {
|
||||||
|
QTC_ASSERT(model(), break);
|
||||||
if (!d.valueEnabled)
|
if (!d.valueEnabled)
|
||||||
return gray;
|
return gray;
|
||||||
if (!watchModel()->contentIsValid() && !d.isInspect())
|
if (!watchModel()->contentIsValid() && !d.isInspect())
|
||||||
@@ -961,6 +966,7 @@ bool WatchModel::setData(const QModelIndex &idx, const QVariant &value, int role
|
|||||||
|
|
||||||
Qt::ItemFlags WatchItem::flags(int column) const
|
Qt::ItemFlags WatchItem::flags(int column) const
|
||||||
{
|
{
|
||||||
|
QTC_ASSERT(model(), return Qt::ItemFlags());
|
||||||
if (!watchModel()->contentIsValid() && !d.isInspect())
|
if (!watchModel()->contentIsValid() && !d.isInspect())
|
||||||
return Qt::ItemFlags();
|
return Qt::ItemFlags();
|
||||||
|
|
||||||
@@ -1313,6 +1319,31 @@ void WatchHandler::insertIncompleteData(const WatchData &data)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchHandler::insertItem(WatchItem *item)
|
||||||
|
{
|
||||||
|
m_model->insertItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WatchModel::insertItem(WatchItem *item)
|
||||||
|
{
|
||||||
|
WatchItem *existing = findItem(item->d.iname);
|
||||||
|
if (existing)
|
||||||
|
removeItem(existing);
|
||||||
|
|
||||||
|
WatchItem *parent = findItem(parentName(item->d.iname));
|
||||||
|
QTC_ASSERT(parent, return);
|
||||||
|
const int row = findInsertPosition(parent->children(), item);
|
||||||
|
parent->insertChild(row, item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void WatchModel::reexpandItems()
|
||||||
|
{
|
||||||
|
foreach (const QByteArray &iname, m_expandedINames) {
|
||||||
|
WatchItem *item = findItem(iname);
|
||||||
|
emit itemIsExpanded(indexFromItem(item));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void WatchHandler::insertData(const WatchData &data)
|
void WatchHandler::insertData(const WatchData &data)
|
||||||
{
|
{
|
||||||
QList<WatchData> list;
|
QList<WatchData> list;
|
||||||
@@ -1344,6 +1375,18 @@ void WatchHandler::resetValueCache()
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchHandler::purgeOutdatedItems(const QSet<QByteArray> &inames)
|
||||||
|
{
|
||||||
|
foreach (const QByteArray &iname, inames) {
|
||||||
|
WatchItem *item = findItem(iname);
|
||||||
|
m_model->removeItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_model->layoutChanged();
|
||||||
|
m_model->reexpandItems();
|
||||||
|
m_contentsValid = true;
|
||||||
|
}
|
||||||
|
|
||||||
void WatchHandler::removeData(const QByteArray &iname)
|
void WatchHandler::removeData(const QByteArray &iname)
|
||||||
{
|
{
|
||||||
WatchItem *item = m_model->findItem(iname);
|
WatchItem *item = m_model->findItem(iname);
|
||||||
@@ -1638,6 +1681,11 @@ const WatchData *WatchHandler::findData(const QByteArray &iname) const
|
|||||||
return item ? &item->d : 0;
|
return item ? &item->d : 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WatchItem *WatchHandler::findItem(const QByteArray &iname) const
|
||||||
|
{
|
||||||
|
return m_model->findItem(iname);
|
||||||
|
}
|
||||||
|
|
||||||
const WatchData *WatchHandler::findCppLocalVariable(const QString &name) const
|
const WatchData *WatchHandler::findCppLocalVariable(const QString &name) const
|
||||||
{
|
{
|
||||||
// Can this be found as a local variable?
|
// Can this be found as a local variable?
|
||||||
@@ -1880,6 +1928,30 @@ WatchModel *WatchItem::watchModel()
|
|||||||
return static_cast<WatchModel *>(model());
|
return static_cast<WatchModel *>(model());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void WatchItem::parseWatchData(const QSet<QByteArray> &expandedINames, const GdbMi &input)
|
||||||
|
{
|
||||||
|
auto itemHandler = [this](const WatchData &data) {
|
||||||
|
d = data;
|
||||||
|
};
|
||||||
|
auto childHandler = [this](const QSet<QByteArray> &expandedINames,
|
||||||
|
const WatchData &innerData, const GdbMi &innerInput) {
|
||||||
|
WatchItem *item = new WatchItem(innerData);
|
||||||
|
item->parseWatchData(expandedINames, innerInput);
|
||||||
|
appendChild(item);
|
||||||
|
};
|
||||||
|
|
||||||
|
auto itemAdder = [this](const WatchData &data) {
|
||||||
|
appendChild(new WatchItem(data));
|
||||||
|
};
|
||||||
|
|
||||||
|
auto arrayDecoder = [itemAdder](const WatchData &childTemplate,
|
||||||
|
const QByteArray &encodedData, int encoding) {
|
||||||
|
decodeArrayData(itemAdder, childTemplate, encodedData, encoding);
|
||||||
|
};
|
||||||
|
|
||||||
|
parseChildrenData(expandedINames, d, input, itemHandler, childHandler, arrayDecoder);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Internal
|
} // namespace Internal
|
||||||
} // namespace Debugger
|
} // namespace Debugger
|
||||||
|
|
||||||
|
@@ -75,6 +75,7 @@ public:
|
|||||||
void formatRequests(QByteArray *out) const;
|
void formatRequests(QByteArray *out) const;
|
||||||
void showInEditorHelper(QString *contents, int depth) const;
|
void showInEditorHelper(QString *contents, int depth) const;
|
||||||
WatchItem *findItem(const QByteArray &iname);
|
WatchItem *findItem(const QByteArray &iname);
|
||||||
|
void parseWatchData(const QSet<QByteArray> &expandedINames, const GdbMi &input);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
WatchData d;
|
WatchData d;
|
||||||
@@ -196,6 +197,7 @@ public:
|
|||||||
const WatchData *watchData(const QModelIndex &) const;
|
const WatchData *watchData(const QModelIndex &) const;
|
||||||
void fetchMore(const QByteArray &iname) const;
|
void fetchMore(const QByteArray &iname) const;
|
||||||
const WatchData *findData(const QByteArray &iname) const;
|
const WatchData *findData(const QByteArray &iname) const;
|
||||||
|
WatchItem *findItem(const QByteArray &iname) const;
|
||||||
const WatchData *findCppLocalVariable(const QString &name) const;
|
const WatchData *findCppLocalVariable(const QString &name) const;
|
||||||
bool hasItem(const QByteArray &iname) const;
|
bool hasItem(const QByteArray &iname) const;
|
||||||
|
|
||||||
@@ -234,10 +236,12 @@ public:
|
|||||||
void insertData(const WatchData &data); // Convenience.
|
void insertData(const WatchData &data); // Convenience.
|
||||||
void insertData(const QList<WatchData> &list);
|
void insertData(const QList<WatchData> &list);
|
||||||
void insertIncompleteData(const WatchData &data);
|
void insertIncompleteData(const WatchData &data);
|
||||||
|
void insertItem(WatchItem *item);
|
||||||
void removeData(const QByteArray &iname);
|
void removeData(const QByteArray &iname);
|
||||||
void removeChildren(const QByteArray &iname);
|
void removeChildren(const QByteArray &iname);
|
||||||
void removeAllData(bool includeInspectData = false);
|
void removeAllData(bool includeInspectData = false);
|
||||||
void resetValueCache();
|
void resetValueCache();
|
||||||
|
void purgeOutdatedItems(const QSet<QByteArray> &inames);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend class WatchModel;
|
friend class WatchModel;
|
||||||
|
Reference in New Issue
Block a user