diff --git a/share/qtcreator/gdbmacros/gdbmacros.cpp b/share/qtcreator/gdbmacros/gdbmacros.cpp index 4db45d2c0d82d79b12834286a749ce30a1a39842..204a1479ae5fe58e4af75f0f91d2302ef82cd51c 100644 --- a/share/qtcreator/gdbmacros/gdbmacros.cpp +++ b/share/qtcreator/gdbmacros/gdbmacros.cpp @@ -896,6 +896,7 @@ static void qDumpQAbstractItem(QDumper &d) d.endHash(); } } +/* d.beginHash(); P(d, "name", "DisplayRole"); P(d, "numchild", 0); @@ -903,6 +904,7 @@ static void qDumpQAbstractItem(QDumper &d) P(d, "valueencoded", 2); P(d, "type", NS"QString"); d.endHash(); +*/ d << "]"; } d.disarm(); diff --git a/src/plugins/debugger/attachcoredialog.ui b/src/plugins/debugger/attachcoredialog.ui index 5ebe87de853b89805472d890d2a665b003917676..271cfb2051e836c2c9427434443a9b1c0efd8ef4 100644 --- a/src/plugins/debugger/attachcoredialog.ui +++ b/src/plugins/debugger/attachcoredialog.ui @@ -6,8 +6,8 @@ <rect> <x>0</x> <y>0</y> - <width>425</width> - <height>127</height> + <width>567</width> + <height>126</height> </rect> </property> <property name="windowTitle"> diff --git a/src/plugins/debugger/watchhandler.cpp b/src/plugins/debugger/watchhandler.cpp index fa13e8e895404021b7f2827fd8c86cecb5384611..b8f794b4a0904d65bde7a507aca8be49fa7a54cf 100644 --- a/src/plugins/debugger/watchhandler.cpp +++ b/src/plugins/debugger/watchhandler.cpp @@ -389,88 +389,92 @@ static QString chopConst(QString type) return type; } -static QString niceType(QString type) +QString niceType(QString type) { - if (type.contains(QLatin1String("std::"))) { - // std::string - type.replace(QLatin1String("basic_string<char, std::char_traits<char>, " - "std::allocator<char> >"), QLatin1String("string")); - - // std::wstring - type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, " - "std::allocator<wchar_t> >"), QLatin1String("wstring")); - - // std::vector - static QRegExp re1(QLatin1String("vector<(.*), std::allocator<(.*)>\\s*>")); - re1.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re1.indexIn(type) == -1 || re1.cap(1) != re1.cap(2)) - break; - type.replace(re1.cap(0), QLatin1String("vector<") + re1.cap(1) + QLatin1Char('>')); - } + type.replace('*', '@'); - // std::deque - static QRegExp re5(QLatin1String("deque<(.*), std::allocator<(.*)>\\s*>")); - re5.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re5.indexIn(type) == -1 || re5.cap(1) != re5.cap(2)) - break; - type.replace(re5.cap(0), QLatin1String("deque<") + re5.cap(1) + QLatin1Char('>')); + for (int i = 0; i < 10; ++i) { + int start = type.indexOf("std::allocator<"); + if (start == -1) + break; + // search for matching '>' + int pos; + int level = 0; + for (pos = start + 12; pos < type.size(); ++pos) { + int c = type.at(pos).unicode(); + if (c == '<') { + ++level; + } else if (c == '>') { + --level; + if (level == 0) + break; + } } + QString alloc = type.mid(start, pos + 1 - start).trimmed(); + QString inner = alloc.mid(15, alloc.size() - 16).trimmed(); + + if (inner == QLatin1String("char")) + // std::string + type.replace(QLatin1String("basic_string<char, std::char_traits<char>, " + "std::allocator<char> >"), QLatin1String("string")); + else if (inner == QLatin1String("wchar_t")) + // std::wstring + type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, " + "std::allocator<wchar_t> >"), QLatin1String("wstring")); + + // std::vector, std::deque, std::list + QRegExp re1(QString("(vector|list|deque)<%1, %2\\s*>").arg(inner, alloc)); + if (re1.indexIn(type) != -1) + type.replace(re1.cap(0), QString("%1<%2>").arg(re1.cap(1), inner)); + // std::stack - static QRegExp re6(QLatin1String("stack<(.*), std::deque<(.*), std::allocator<(.*)>\\s*> >")); + QRegExp re6(QString("stack<%1, std::deque<%2> >").arg(inner, inner)); re6.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re6.indexIn(type) == -1 || re6.cap(1) != re6.cap(2) - || re6.cap(1) != re6.cap(2)) - break; - type.replace(re6.cap(0), QLatin1String("stack<") + re6.cap(1) + QLatin1Char('>')); - } + if (re6.indexIn(type) != -1) + type.replace(re6.cap(0), QString("stack<%1>").arg(inner)); + + // std::set + QRegExp re4(QString("set<%1, std::less<%2>, %3\\s*>").arg(inner, inner, alloc)); + re4.setMinimal(true); + if (re4.indexIn(type) != -1) + type.replace(re4.cap(0), QString("set<%1>").arg(inner)); - // std::list - static QRegExp re2(QLatin1String("list<(.*), std::allocator<(.*)>\\s*>")); - re2.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re2.indexIn(type) == -1 || re2.cap(1) != re2.cap(2)) - break; - type.replace(re2.cap(0), QLatin1String("list<") + re2.cap(1) + QLatin1Char('>')); - } // std::map - { - static QRegExp re(QLatin1String("map<(.*), (.*), std::less<(.*)>, " - "std::allocator<std::pair<(.*), (.*)> > >")); - re.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re.indexIn(type) == -1) - break; - QString key = chopConst(re.cap(1)); - QString value = chopConst(re.cap(2)); - QString key1 = chopConst(re.cap(3)); - QString key2 = chopConst(re.cap(4)); - QString value2 = chopConst(re.cap(5)); - if (value != value2 || key != key1 || key != key2) { - qDebug() << key << key1 << key2 << value << value2 - << (key == key1) << (key == key2) << (value == value2); + if (inner.startsWith("std::pair<")) { + // search for outermost ',' + int pos; + int level = 0; + for (pos = 10; pos < inner.size(); ++pos) { + int c = inner.at(pos).unicode(); + if (c == '<') + ++level; + else if (c == '>') + --level; + else if (c == ',' && level == 0) break; - } - type.replace(re.cap(0), QString("map<%1, %2>").arg(key).arg(value)); + } + QString ckey = inner.mid(10, pos - 10); + QString key = chopConst(ckey); + QString value = inner.mid(pos + 2, inner.size() - 3 - pos); + + QRegExp re5(QString("map<%1, %2, std::less<%3>, %4\\s*>") + .arg(key, value, key, alloc)); + re5.setMinimal(true); + if (re5.indexIn(type) != -1) + type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value)); + else { + QRegExp re7(QString("map<const %1, %2, std::less<const %3>, %4\\s*>") + .arg(key, value, key, alloc)); + re7.setMinimal(true); + if (re7.indexIn(type) != -1) + type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value)); } } - - // std::set - static QRegExp re4(QLatin1String("set<(.*), std::less<(.*)>, std::allocator<(.*)>\\s*>")); - re1.setMinimal(true); - for (int i = 0; i != 10; ++i) { - if (re4.indexIn(type) == -1 || re4.cap(1) != re4.cap(2) - || re4.cap(1) != re4.cap(3)) - break; - type.replace(re4.cap(0), QLatin1String("set<") + re4.cap(1) + QLatin1Char('>')); - } - - type.replace(QLatin1String(" >"), QString(QLatin1Char('>'))); } + type.replace('@', '*'); + type.replace(QLatin1String(" >"), QString(QLatin1Char('>'))); return type; } diff --git a/src/plugins/debugger/watchutils.h b/src/plugins/debugger/watchutils.h index a30b25bdcba03ca47701b233d2b61c25094327c3..6385354a8995e8078c8e7505175e65f4a4e5357a 100644 --- a/src/plugins/debugger/watchutils.h +++ b/src/plugins/debugger/watchutils.h @@ -225,6 +225,9 @@ private: QDebug operator<<(QDebug in, const QtDumperHelper::TypeData &d); +// remove the default template argument in std:: containers +QString removeDefaultTemplateArguments(QString type); + } // namespace Internal } // namespace Debugger diff --git a/tests/auto/debugger/debugger.pro b/tests/auto/debugger/debugger.pro index b7a84c40288e733b04b74201b2a9e49b352a21f8..a7001a24d4d5b8a382b7f963eed4375ecfdd22c0 100644 --- a/tests/auto/debugger/debugger.pro +++ b/tests/auto/debugger/debugger.pro @@ -5,8 +5,8 @@ DEBUGGERDIR = ../../../src/plugins/debugger UTILSDIR = ../../../src/libs SOURCES += \ - $$DEBUGGERDIR/gdbmi.cpp \ - $$DEBUGGERDIR/json.cpp \ + $$DEBUGGERDIR/gdb/gdbmi.cpp \ + $$DEBUGGERDIR/tcf/json.cpp \ main.cpp \ INCLUDEPATH += $$DEBUGGERDIR $$UTILSDIR diff --git a/tests/auto/debugger/main.cpp b/tests/auto/debugger/main.cpp index fd2121a8b800176d77634fc1883c8e0148963f0c..86ecf8cb03a5237b5d6f4019cb97bbc550473057 100644 --- a/tests/auto/debugger/main.cpp +++ b/tests/auto/debugger/main.cpp @@ -1,6 +1,6 @@ -#include "gdbmi.h" -#include "json.h" +#include "gdb/gdbmi.h" +#include "tcf/json.h" #include <QtCore/QObject> #include <QtCore/QProcess> @@ -95,6 +95,8 @@ private slots: void json1() { testJson(jsont1); } void infoBreak(); + void niceType(); + void niceType_data(); public slots: void runQtc(); @@ -118,7 +120,6 @@ static QByteArray stripped(QByteArray ba) return ba; } - void tst_Debugger::infoBreak() { // This tests the regular expression used in GdbEngine::extractDataFromInfoBreak @@ -153,6 +154,151 @@ void tst_Debugger::infoBreak() QCOMPARE(re.cap(4), QString("124")); } +static QString chopConst(QString type) +{ + while (1) { + if (type.startsWith("const")) + type = type.mid(5); + else if (type.startsWith(' ')) + type = type.mid(1); + else if (type.endsWith("const")) + type.chop(5); + else if (type.endsWith(' ')) + type.chop(1); + else + break; + } + return type; +} + +QString niceType(QString type) +{ + type.replace('*', '@'); + + int pos; + for (int i = 0; i < 10; ++i) { + int start = type.indexOf("std::allocator<"); + if (start == -1) + break; + // search for matching '>' + int pos; + int level = 0; + for (pos = start + 12; pos < type.size(); ++pos) { + int c = type.at(pos).unicode(); + if (c == '<') { + ++level; + } else if (c == '>') { + --level; + if (level == 0) + break; + } + } + QString alloc = type.mid(start, pos + 1 - start).trimmed(); + QString inner = alloc.mid(15, alloc.size() - 16).trimmed(); + //qDebug() << "MATCH: " << pos << alloc << inner; + + if (inner == QLatin1String("char")) + // std::string + type.replace(QLatin1String("basic_string<char, std::char_traits<char>, " + "std::allocator<char> >"), QLatin1String("string")); + else if (inner == QLatin1String("wchar_t")) + // std::wstring + type.replace(QLatin1String("basic_string<wchar_t, std::char_traits<wchar_t>, " + "std::allocator<wchar_t> >"), QLatin1String("wstring")); + + // std::vector, std::deque, std::list + QRegExp re1(QString("(vector|list|deque)<%1, %2\\s*>").arg(inner, alloc)); + if (re1.indexIn(type) != -1) + type.replace(re1.cap(0), QString("%1<%2>").arg(re1.cap(1), inner)); + + + // std::stack + QRegExp re6(QString("stack<%1, std::deque<%2> >").arg(inner, inner)); + re6.setMinimal(true); + if (re6.indexIn(type) != -1) + type.replace(re6.cap(0), QString("stack<%1>").arg(inner)); + + // std::set + QRegExp re4(QString("set<%1, std::less<%2>, %3\\s*>").arg(inner, inner, alloc)); + re4.setMinimal(true); + if (re4.indexIn(type) != -1) + type.replace(re4.cap(0), QString("set<%1>").arg(inner)); + + + // std::map + if (inner.startsWith("std::pair<")) { + // search for outermost ',' + int pos; + int level = 0; + for (pos = 10; pos < inner.size(); ++pos) { + int c = inner.at(pos).unicode(); + if (c == '<') + ++level; + else if (c == '>') + --level; + else if (c == ',' && level == 0) + break; + } + QString ckey = inner.mid(10, pos - 10); + QString key = chopConst(ckey); + QString value = inner.mid(pos + 2, inner.size() - 3 - pos); + + QRegExp re5(QString("map<%1, %2, std::less<%3>, %4\\s*>") + .arg(key, value, key, alloc)); + re5.setMinimal(true); + if (re5.indexIn(type) != -1) + type.replace(re5.cap(0), QString("map<%1, %2>").arg(key, value)); + else { + QRegExp re7(QString("map<const %1, %2, std::less<const %3>, %4\\s*>") + .arg(key, value, key, alloc)); + re7.setMinimal(true); + if (re7.indexIn(type) != -1) + type.replace(re7.cap(0), QString("map<const %1, %2>").arg(key, value)); + } + } + } + type.replace('@', '*'); + type.replace(QLatin1String(" >"), QString(QLatin1Char('>'))); + return type; +} + +void tst_Debugger::niceType() +{ + // cf. watchutils.cpp + QFETCH(QString, input); + QFETCH(QString, simplified); + QCOMPARE(::niceType(input), simplified); +} + +void tst_Debugger::niceType_data() +{ + QTest::addColumn<QString>("input"); + QTest::addColumn<QString>("simplified"); + + QTest::newRow("list") + << "std::list<int, std::allocator<int> >" + << "std::list<int>"; + + QTest::newRow("combined") + << "std::vector<std::list<int, std::allocator<int> >*, " + "std::allocator<std::list<int, std::allocator<int> >*> >" + << "std::vector<std::list<int>*>"; + + QTest::newRow("stack") + << "std::stack<int, std::deque<int, std::allocator<int> > >" + << "std::stack<int>"; + + QTest::newRow("map") + << "std::map<myns::QString, Foo, std::less<myns::QString>, " + "std::allocator<std::pair<const myns::QString, Foo> > >" + << "std::map<myns::QString, Foo>"; + + QTest::newRow("map2") + << "std::map<const char*, Foo, std::less<const char*>, " + "std::allocator<std::pair<const char* const, Foo> > >" + << "std::map<const char*, Foo>"; +} + void tst_Debugger::readStandardOutput() { qDebug() << "qtcreator-out: " << stripped(m_proc.readAllStandardOutput()); diff --git a/tests/manual/gdbdebugger/simple/app.cpp b/tests/manual/gdbdebugger/simple/app.cpp index f29c633c21048d1374d6f2ecf1aae55e66078725..d7d7f8108162d834571e625cee5ceb246434cea8 100644 --- a/tests/manual/gdbdebugger/simple/app.cpp +++ b/tests/manual/gdbdebugger/simple/app.cpp @@ -818,7 +818,7 @@ void testQStandardItemModel() << (i11 = new QStandardItem("11")) << (new QStandardItem("aa"))); int i = 1; ++i; - ++i; + +i; } void testQString() @@ -1118,8 +1118,41 @@ void testHidden() ++n; } +void testObject1() +{ + QObject parent; + parent.setObjectName("A Parent"); + QObject child(&parent); + child.setObjectName("A Child"); + child.setObjectName("A renamed Child"); +} + +void testVector1() +{ + std::vector<std::list<int> *> vector; + std::list<int> list; + vector.push_back(new std::list<int>(list)); + vector.push_back(0); + list.push_back(45); + vector.push_back(new std::list<int>(list)); + vector.push_back(0); +} + +void testQHash1() +{ + QHash<QString, QList<int> > hash; + hash.insert("Hallo", QList<int>()); + hash.insert("Welt", QList<int>() << 1); + hash.insert("!", QList<int>() << 1 << 2); + hash.insert("!", QList<int>() << 1 << 2); +} + int main(int argc, char *argv[]) { + testObject1(); + testVector1(); + testQHash1(); + QString hallo = "hallo"; QStringList list; list << "aaa" << "bbb" << "cc";