diff --git a/src/plugins/debugger/gdb/classicgdbengine.cpp b/src/plugins/debugger/gdb/classicgdbengine.cpp index a04d66152bf..0de85f1525a 100644 --- a/src/plugins/debugger/gdb/classicgdbengine.cpp +++ b/src/plugins/debugger/gdb/classicgdbengine.cpp @@ -59,6 +59,11 @@ namespace Debugger { namespace Internal { +static bool isAccessSpecifier(const QByteArray &ba) +{ + return ba == "private" || ba == "protected" || ba == "public"; +} + // reads a MI-encoded item frome the consolestream static bool parseConsoleStream(const GdbResponse &response, GdbMi *contents) { @@ -310,8 +315,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) qDebug() << "UPDATE SUBITEM: VALUE"; #endif QByteArray cmd = "-var-evaluate-expression \"" + data.iname + '"'; - postCommand(cmd, WatchUpdate, CB(handleEvaluateExpression), - QVariant::fromValue(data)); + postCommand(cmd, WatchUpdate, + CB(handleEvaluateExpressionClassic), QVariant::fromValue(data)); return; } @@ -336,7 +341,8 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) if (data.isChildrenNeeded()) { QTC_ASSERT(!data.variable.isEmpty(), return); // tested above QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; - postCommand(cmd, WatchUpdate, CB(handleVarListChildren), QVariant::fromValue(data)); + postCommand(cmd, WatchUpdate, + CB(handleVarListChildrenClassic), QVariant::fromValue(data)); return; } @@ -365,7 +371,7 @@ void GdbEngine::updateSubItemClassic(const WatchData &data0) QTC_ASSERT(!data.variable.isEmpty(), return); // tested above QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; postCommand(cmd, Discardable, - CB(handleVarListChildren), QVariant::fromValue(data)); + CB(handleVarListChildrenClassic), QVariant::fromValue(data)); return; } @@ -712,5 +718,164 @@ void GdbEngine::handleQueryDebuggingHelperClassic(const GdbResponse &response) //qDebug() << m_availableSimpleDebuggingHelpers << "DATA DUMPERS AVAILABLE"; } +void GdbEngine::handleVarListChildrenHelperClassic(const GdbMi &item, + const WatchData &parent) +{ + //qDebug() << "VAR_LIST_CHILDREN: PARENT" << parent.toString(); + //qDebug() << "VAR_LIST_CHILDREN: ITEM" << item.toString(); + QByteArray exp = item.findChild("exp").data(); + QByteArray name = item.findChild("name").data(); + if (isAccessSpecifier(exp)) { + // suppress 'private'/'protected'/'public' level + WatchData data; + data.variable = name; + data.iname = parent.iname; + //data.iname = data.variable; + data.exp = parent.exp; + data.setTypeUnneeded(); + data.setValueUnneeded(); + data.setHasChildrenUnneeded(); + data.setChildrenUnneeded(); + //qDebug() << "DATA" << data.toString(); + QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; + //iname += '.' + exp; + postCommand(cmd, WatchUpdate, + CB(handleVarListChildrenClassic), QVariant::fromValue(data)); + } else if (item.findChild("numchild").data() == "0") { + // happens for structs without data, e.g. interfaces. + WatchData data; + data.name = _(exp); + data.iname = parent.iname + '.' + data.name.toLatin1(); + data.variable = name; + setWatchDataType(data, item.findChild("type")); + setWatchDataValue(data, item.findChild("value")); + setWatchDataAddress(data, item.findChild("addr")); + setWatchDataSAddress(data, item.findChild("saddr")); + data.setHasChildren(false); + insertData(data); + } else if (parent.iname.endsWith('.')) { + // Happens with anonymous unions + WatchData data; + data.iname = name; + QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; + postCommand(cmd, WatchUpdate, + CB(handleVarListChildrenClassic), QVariant::fromValue(data)); + } else if (exp == "staticMetaObject") { + // && item.findChild("type").data() == "const QMetaObject") + // FIXME: Namespaces? + // { do nothing } FIXME: make configurable? + // special "clever" hack to avoid clutter in the GUI. + // I am not sure this is a good idea... + } else { + WatchData data; + data.iname = parent.iname + '.' + exp; + data.variable = name; + setWatchDataType(data, item.findChild("type")); + setWatchDataValue(data, item.findChild("value")); + setWatchDataAddress(data, item.findChild("addr")); + setWatchDataSAddress(data, item.findChild("saddr")); + setWatchDataChildCount(data, item.findChild("numchild")); + if (!manager()->watchHandler()->isExpandedIName(data.iname)) + data.setChildrenUnneeded(); + + data.name = _(exp); + if (data.type == data.name) { + if (isPointerType(parent.type)) { + data.exp = "*(" + parent.exp + ')'; + data.name = _("*") + parent.name; + } else { + // A type we derive from? gdb crashes when creating variables here + data.exp = parent.exp; + } + } else if (exp.startsWith("*")) { + // A pointer + data.exp = "*(" + parent.exp + ')'; + } else if (startsWithDigit(data.name)) { + // An array. No variables needed? + data.name = _c('[') + data.name + _c(']'); + data.exp = parent.exp + '[' + exp + ']'; + } else if (0 && parent.name.endsWith(_c('.'))) { + // Happens with anonymous unions + data.exp = parent.exp + data.name.toLatin1(); + //data.name = ""; + } else if (exp.isEmpty()) { + // Happens with anonymous unions + data.exp = parent.exp; + data.name = tr(""); + data.iname = parent.iname + ".@"; + data.type = tr(""); + } else { + // A structure. Hope there's nothing else... + data.exp = parent.exp + '.' + data.name.toLatin1(); + } + + if (hasDebuggingHelperForType(data.type)) { + // we do not trust gdb if we have a custom dumper + data.setValueNeeded(); + data.setHasChildrenNeeded(); + } + + //qDebug() << "VAR_LIST_CHILDREN: PARENT 3" << parent.toString(); + //qDebug() << "VAR_LIST_CHILDREN: APPENDEE" << data.toString(); + insertData(data); + } +} + +void GdbEngine::handleVarListChildrenClassic(const GdbResponse &response) +{ + //WatchResultCounter dummy(this, WatchVarListChildren); + WatchData data = response.cookie.value(); + if (!data.isValid()) + return; + if (response.resultClass == GdbResultDone) { + //qDebug() << "VAR_LIST_CHILDREN: PARENT" << data.toString(); + GdbMi children = response.data.findChild("children"); + + foreach (const GdbMi &child, children.children()) + handleVarListChildrenHelperClassic(child, data); + + if (children.children().isEmpty()) { + // happens e.g. if no debug information is present or + // if the class really has no children + WatchData data1; + data1.iname = data.iname + ".child"; + //: About variable's value + data1.value = tr(""); + data1.hasChildren = false; + data1.setAllUnneeded(); + insertData(data1); + data.setAllUnneeded(); + insertData(data); + } else if (data.variable.endsWith("private") + || data.variable.endsWith("protected") + || data.variable.endsWith("public")) { + // this skips the spurious "public", "private" etc levels + // gdb produces + } else { + data.setChildrenUnneeded(); + insertData(data); + } + } else { + data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); + } +} + +void GdbEngine::handleEvaluateExpressionClassic(const GdbResponse &response) +{ + WatchData data = response.cookie.value(); + QTC_ASSERT(data.isValid(), qDebug() << "HUH?"); + if (response.resultClass == GdbResultDone) { + //if (col == 0) + // data.name = response.data.findChild("value").data(); + //else + setWatchDataValue(data, response.data.findChild("value")); + } else { + data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); + } + //qDebug() << "HANDLE EVALUATE EXPRESSION:" << data.toString(); + insertData(data); + //updateWatchModel2(); +} + } // namespace Internal } // namespace Debugger diff --git a/src/plugins/debugger/gdb/gdbengine.cpp b/src/plugins/debugger/gdb/gdbengine.cpp index 8feca0953f8..d1409ac0192 100644 --- a/src/plugins/debugger/gdb/gdbengine.cpp +++ b/src/plugins/debugger/gdb/gdbengine.cpp @@ -151,12 +151,6 @@ static int ¤tToken() return token; } -static bool isAccessSpecifier(const QByteArray &ba) -{ - return ba == "private" || ba == "protected" || ba == "public"; -} - - static QByteArray parsePlainConsoleStream(const GdbResponse &response) { GdbMi output = response.data.findChild("consolestreamoutput"); @@ -2822,8 +2816,8 @@ void GdbEngine::setToolTipExpression(const QPoint &mousePos, // ////////////////////////////////////////////////////////////////////// -static void setWatchDataValue(WatchData &data, const GdbMi &mi, - int encoding = 0) +void GdbEngine::setWatchDataValue(WatchData &data, const GdbMi &mi, + int encoding) { if (mi.isValid()) data.setValue(decodeData(mi.data(), encoding)); @@ -2831,26 +2825,26 @@ static void setWatchDataValue(WatchData &data, const GdbMi &mi, data.setValueNeeded(); } -static void setWatchDataEditValue(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataEditValue(WatchData &data, const GdbMi &mi) { if (mi.isValid()) data.editvalue = mi.data(); } -static void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi, - int encoding = 0) +void GdbEngine::setWatchDataValueToolTip(WatchData &data, const GdbMi &mi, + int encoding) { if (mi.isValid()) data.setValueToolTip(decodeData(mi.data(), encoding)); } -static void setWatchDataChildCount(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataChildCount(WatchData &data, const GdbMi &mi) { if (mi.isValid()) data.setHasChildren(mi.data().toInt() > 0); } -static void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataValueEnabled(WatchData &data, const GdbMi &mi) { if (mi.data() == "true") data.valueEnabled = true; @@ -2858,7 +2852,7 @@ static void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi) data.valueEnabled = false; } -static void setWatchDataValueEditable(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataValueEditable(WatchData &data, const GdbMi &mi) { if (mi.data() == "true") data.valueEditable = true; @@ -2866,13 +2860,13 @@ static void setWatchDataValueEditable(WatchData &data, const GdbMi &mi) data.valueEditable = false; } -static void setWatchDataExpression(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataExpression(WatchData &data, const GdbMi &mi) { if (mi.isValid()) data.exp = mi.data(); } -static void setWatchDataAddress(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataAddress(WatchData &data, const GdbMi &mi) { if (mi.isValid()) { data.addr = mi.data(); @@ -2881,7 +2875,7 @@ static void setWatchDataAddress(WatchData &data, const GdbMi &mi) } } -static void setWatchDataSAddress(WatchData &data, const GdbMi &mi) +void GdbEngine::setWatchDataSAddress(WatchData &data, const GdbMi &mi) { if (mi.isValid()) data.saddr = mi.data(); @@ -3085,23 +3079,6 @@ void GdbEngine::handleVarCreate(const GdbResponse &response) } } -void GdbEngine::handleEvaluateExpression(const GdbResponse &response) -{ - WatchData data = response.cookie.value(); - QTC_ASSERT(data.isValid(), qDebug() << "HUH?"); - if (response.resultClass == GdbResultDone) { - //if (col == 0) - // data.name = response.data.findChild("value").data(); - //else - setWatchDataValue(data, response.data.findChild("value")); - } else { - data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); - } - //qDebug() << "HANDLE EVALUATE EXPRESSION:" << data.toString(); - insertData(data); - //updateWatchModel2(); -} - void GdbEngine::handleDebuggingHelperSetup(const GdbResponse &response) { //qDebug() << "CUSTOM SETUP RESULT:" << response.toString(); @@ -3282,147 +3259,6 @@ void GdbEngine::insertData(const WatchData &data0) manager()->watchHandler()->insertData(data); } -void GdbEngine::handleVarListChildrenHelper(const GdbMi &item, - const WatchData &parent) -{ - //qDebug() << "VAR_LIST_CHILDREN: PARENT" << parent.toString(); - //qDebug() << "VAR_LIST_CHILDREN: ITEM" << item.toString(); - QByteArray exp = item.findChild("exp").data(); - QByteArray name = item.findChild("name").data(); - if (isAccessSpecifier(exp)) { - // suppress 'private'/'protected'/'public' level - WatchData data; - data.variable = name; - data.iname = parent.iname; - //data.iname = data.variable; - data.exp = parent.exp; - data.setTypeUnneeded(); - data.setValueUnneeded(); - data.setHasChildrenUnneeded(); - data.setChildrenUnneeded(); - //qDebug() << "DATA" << data.toString(); - QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; - //iname += '.' + exp; - postCommand(cmd, WatchUpdate, - CB(handleVarListChildren), QVariant::fromValue(data)); - } else if (item.findChild("numchild").data() == "0") { - // happens for structs without data, e.g. interfaces. - WatchData data; - data.name = _(exp); - data.iname = parent.iname + '.' + data.name.toLatin1(); - data.variable = name; - setWatchDataType(data, item.findChild("type")); - setWatchDataValue(data, item.findChild("value")); - setWatchDataAddress(data, item.findChild("addr")); - setWatchDataSAddress(data, item.findChild("saddr")); - data.setHasChildren(false); - insertData(data); - } else if (parent.iname.endsWith('.')) { - // Happens with anonymous unions - WatchData data; - data.iname = name; - QByteArray cmd = "-var-list-children --all-values \"" + data.variable + '"'; - postCommand(cmd, WatchUpdate, - CB(handleVarListChildren), QVariant::fromValue(data)); - } else if (exp == "staticMetaObject") { - // && item.findChild("type").data() == "const QMetaObject") - // FIXME: Namespaces? - // { do nothing } FIXME: make configurable? - // special "clever" hack to avoid clutter in the GUI. - // I am not sure this is a good idea... - } else { - WatchData data; - data.iname = parent.iname + '.' + exp; - data.variable = name; - setWatchDataType(data, item.findChild("type")); - setWatchDataValue(data, item.findChild("value")); - setWatchDataAddress(data, item.findChild("addr")); - setWatchDataSAddress(data, item.findChild("saddr")); - setWatchDataChildCount(data, item.findChild("numchild")); - if (!manager()->watchHandler()->isExpandedIName(data.iname)) - data.setChildrenUnneeded(); - - data.name = _(exp); - if (data.type == data.name) { - if (isPointerType(parent.type)) { - data.exp = "*(" + parent.exp + ')'; - data.name = _("*") + parent.name; - } else { - // A type we derive from? gdb crashes when creating variables here - data.exp = parent.exp; - } - } else if (exp.startsWith("*")) { - // A pointer - data.exp = "*(" + parent.exp + ')'; - } else if (startsWithDigit(data.name)) { - // An array. No variables needed? - data.name = _c('[') + data.name + _c(']'); - data.exp = parent.exp + '[' + exp + ']'; - } else if (0 && parent.name.endsWith(_c('.'))) { - // Happens with anonymous unions - data.exp = parent.exp + data.name.toLatin1(); - //data.name = ""; - } else if (exp.isEmpty()) { - // Happens with anonymous unions - data.exp = parent.exp; - data.name = tr(""); - data.iname = parent.iname + ".@"; - data.type = tr(""); - } else { - // A structure. Hope there's nothing else... - data.exp = parent.exp + '.' + data.name.toLatin1(); - } - - if (hasDebuggingHelperForType(data.type)) { - // we do not trust gdb if we have a custom dumper - data.setValueNeeded(); - data.setHasChildrenNeeded(); - } - - //qDebug() << "VAR_LIST_CHILDREN: PARENT 3" << parent.toString(); - //qDebug() << "VAR_LIST_CHILDREN: APPENDEE" << data.toString(); - insertData(data); - } -} - -void GdbEngine::handleVarListChildren(const GdbResponse &response) -{ - //WatchResultCounter dummy(this, WatchVarListChildren); - WatchData data = response.cookie.value(); - if (!data.isValid()) - return; - if (response.resultClass == GdbResultDone) { - //qDebug() << "VAR_LIST_CHILDREN: PARENT" << data.toString(); - GdbMi children = response.data.findChild("children"); - - foreach (const GdbMi &child, children.children()) - handleVarListChildrenHelper(child, data); - - if (children.children().isEmpty()) { - // happens e.g. if no debug information is present or - // if the class really has no children - WatchData data1; - data1.iname = data.iname + ".child"; - //: About variable's value - data1.value = tr(""); - data1.hasChildren = false; - data1.setAllUnneeded(); - insertData(data1); - data.setAllUnneeded(); - insertData(data); - } else if (data.variable.endsWith("private") - || data.variable.endsWith("protected") - || data.variable.endsWith("public")) { - // this skips the spurious "public", "private" etc levels - // gdb produces - } else { - data.setChildrenUnneeded(); - insertData(data); - } - } else { - data.setError(QString::fromLocal8Bit(response.data.findChild("msg").data())); - } -} #if 0 void GdbEngine::handleChangedItem(QStandardItem *item) diff --git a/src/plugins/debugger/gdb/gdbengine.h b/src/plugins/debugger/gdb/gdbengine.h index 09aeff5f61e..d9f44a32643 100644 --- a/src/plugins/debugger/gdb/gdbengine.h +++ b/src/plugins/debugger/gdb/gdbengine.h @@ -437,12 +437,12 @@ private: ////////// View & Data Stuff ////////// void runDirectDebuggingHelperClassic(const WatchData &data, bool dumpChildren); bool hasDebuggingHelperForType(const QString &type) const; - void handleVarListChildren(const GdbResponse &response); - void handleVarListChildrenHelper(const GdbMi &child, + void handleVarListChildrenClassic(const GdbResponse &response); + void handleVarListChildrenHelperClassic(const GdbMi &child, const WatchData &parent); void handleVarCreate(const GdbResponse &response); void handleVarAssign(const GdbResponse &response); - void handleEvaluateExpression(const GdbResponse &response); + void handleEvaluateExpressionClassic(const GdbResponse &response); //void handleToolTip(const GdbResponse &response); void handleQueryDebuggingHelperClassic(const GdbResponse &response); void handleDebuggingHelperValue2Classic(const GdbResponse &response); @@ -496,6 +496,18 @@ private: ////////// Convenience Functions ////////// static QString m_toolTipExpression; static QPoint m_toolTipPos; static QByteArray tooltipINameForExpression(const QByteArray &exp); + + static void setWatchDataValue(WatchData &data, const GdbMi &mi, + int encoding = 0); + static void setWatchDataEditValue(WatchData &data, const GdbMi &mi); + static void setWatchDataValueToolTip(WatchData &data, const GdbMi &mi, + int encoding = 0); + static void setWatchDataChildCount(WatchData &data, const GdbMi &mi); + static void setWatchDataValueEnabled(WatchData &data, const GdbMi &mi); + static void setWatchDataValueEditable(WatchData &data, const GdbMi &mi); + static void setWatchDataExpression(WatchData &data, const GdbMi &mi); + static void setWatchDataAddress(WatchData &data, const GdbMi &mi); + static void setWatchDataSAddress(WatchData &data, const GdbMi &mi); }; } // namespace Internal