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:
hjk
2015-01-28 15:14:15 +01:00
parent c1c1221a0d
commit 39ab4b3783
5 changed files with 126 additions and 40 deletions

View File

@@ -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

View File

@@ -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);

View File

@@ -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,

View File

@@ -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

View File

@@ -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;