forked from qt-creator/qt-creator
Debugger: Implement dumper for std::unordered_{set,map}
Task-number: QTCREATORBUG-9855 Change-Id: I985745530d93e1c191442431a7a9449a1c4c059a Reviewed-by: hjk <hjk121@nokiamail.com> Reviewed-by: David Schulz <david.schulz@digia.com>
This commit is contained in:
@@ -2508,6 +2508,58 @@ def qdump__std____1__unique_ptr(d, value):
|
|||||||
d.putSubItem("data", i.dereference())
|
d.putSubItem("data", i.dereference())
|
||||||
|
|
||||||
|
|
||||||
|
def qform__std__unordered_map():
|
||||||
|
return mapForms()
|
||||||
|
|
||||||
|
def qdump__std__unordered_map(d, value):
|
||||||
|
try:
|
||||||
|
size = value["_M_element_count"]
|
||||||
|
start = value["_M_before_begin"]["_M_nxt"]
|
||||||
|
except:
|
||||||
|
size = value["_M_h"]["_M_element_count"]
|
||||||
|
start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"]
|
||||||
|
d.putItemCount(size)
|
||||||
|
d.putNumChild(size)
|
||||||
|
if d.isExpanded():
|
||||||
|
p = pointerValue(start)
|
||||||
|
keyType = d.templateArgument(value.type, 0)
|
||||||
|
valueType = d.templateArgument(value.type, 1)
|
||||||
|
allocatorType = d.templateArgument(value.type, 4)
|
||||||
|
pairType = d.templateArgument(allocatorType, 0)
|
||||||
|
ptrSize = d.ptrSize()
|
||||||
|
if d.isMapCompact(keyType, valueType):
|
||||||
|
with Children(d, size, childType=valueType):
|
||||||
|
for i in d.childRange():
|
||||||
|
pair = d.createValue(p + ptrSize, pairType)
|
||||||
|
with SubItem(d, i):
|
||||||
|
d.putField("iname", d.currentIName)
|
||||||
|
d.putName("[%s] %s" % (i, pair["first"]))
|
||||||
|
d.putValue(pair["second"])
|
||||||
|
p = d.dereference(p)
|
||||||
|
else:
|
||||||
|
with Children(d, size, childType=pairType):
|
||||||
|
for i in d.childRange():
|
||||||
|
d.putSubItem(i, d.createValue(p + ptrSize, pairType))
|
||||||
|
p = d.dereference(p)
|
||||||
|
|
||||||
|
def qdump__std__unordered_set(d, value):
|
||||||
|
try:
|
||||||
|
size = value["_M_element_count"]
|
||||||
|
start = value["_M_before_begin"]["_M_nxt"]
|
||||||
|
except:
|
||||||
|
size = value["_M_h"]["_M_element_count"]
|
||||||
|
start = value["_M_h"]["_M_bbegin"]["_M_node"]["_M_nxt"]
|
||||||
|
d.putItemCount(size)
|
||||||
|
d.putNumChild(size)
|
||||||
|
if d.isExpanded():
|
||||||
|
p = pointerValue(start)
|
||||||
|
valueType = d.templateArgument(value.type, 0)
|
||||||
|
with Children(d, size, childType=valueType):
|
||||||
|
ptrSize = d.ptrSize()
|
||||||
|
for i in d.childRange():
|
||||||
|
d.putSubItem(i, d.createValue(p + ptrSize, valueType))
|
||||||
|
p = d.dereference(p)
|
||||||
|
|
||||||
|
|
||||||
def qedit__std__vector(expr, value):
|
def qedit__std__vector(expr, value):
|
||||||
values = value.split(',')
|
values = value.split(',')
|
||||||
|
@@ -586,6 +586,14 @@ CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn)
|
|||||||
if (setRE.indexIn(type) != -1)
|
if (setRE.indexIn(type) != -1)
|
||||||
type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
|
type.replace(setRE.cap(0), QString::fromLatin1("set<%1>").arg(inner));
|
||||||
|
|
||||||
|
// std::unordered_set
|
||||||
|
QRegExp unorderedSetRE(QString::fromLatin1("unordered_set<%1, ?std::hash<%2>, ?std::equal_to<%3>, ?%4\\s*>")
|
||||||
|
.arg(innerEsc, innerEsc, innerEsc, allocEsc));
|
||||||
|
unorderedSetRE.setMinimal(true);
|
||||||
|
QTC_ASSERT(unorderedSetRE.isValid(), return typeIn);
|
||||||
|
if (unorderedSetRE.indexIn(type) != -1)
|
||||||
|
type.replace(unorderedSetRE.cap(0), QString::fromLatin1("unordered_set<%1>").arg(inner));
|
||||||
|
|
||||||
// std::map
|
// std::map
|
||||||
if (inner.startsWith(QLatin1String("std::pair<"))) {
|
if (inner.startsWith(QLatin1String("std::pair<"))) {
|
||||||
// search for outermost ',', split key and value
|
// search for outermost ',', split key and value
|
||||||
@@ -621,6 +629,35 @@ CPLUSPLUS_EXPORT QString simplifySTLType(const QString &typeIn)
|
|||||||
type.replace(mapRE2.cap(0), QString::fromLatin1("map<const %1, %2>").arg(key, value));
|
type.replace(mapRE2.cap(0), QString::fromLatin1("map<const %1, %2>").arg(key, value));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// std::unordered_map
|
||||||
|
if (inner.startsWith(QLatin1String("std::pair<"))) {
|
||||||
|
// search for outermost ',', split key and value
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
const QString key = chopConst(inner.mid(10, pos - 10));
|
||||||
|
const QString keyEsc = QRegExp::escape(key);
|
||||||
|
// Get value: MSVC: 'pair<a const ,b>', gcc: 'pair<const a, b>'
|
||||||
|
if (inner.at(++pos) == QLatin1Char(' '))
|
||||||
|
pos++;
|
||||||
|
const QString value = inner.mid(pos, inner.size() - pos - 1).trimmed();
|
||||||
|
const QString valueEsc = QRegExp::escape(value);
|
||||||
|
QRegExp mapRE1(QString::fromLatin1("unordered_map<%1, ?%2, ?std::hash<%3 ?>, ?std::equal_to<%4 ?>, ?%5\\s*>")
|
||||||
|
.arg(keyEsc, valueEsc, keyEsc, keyEsc, allocEsc));
|
||||||
|
mapRE1.setMinimal(true);
|
||||||
|
QTC_ASSERT(mapRE1.isValid(), return typeIn);
|
||||||
|
if (mapRE1.indexIn(type) != -1)
|
||||||
|
type.replace(mapRE1.cap(0), QString::fromLatin1("unordered_map<%1, %2>").arg(key, value));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
type.replace(QLatin1Char('@'), QLatin1Char('*'));
|
type.replace(QLatin1Char('@'), QLatin1Char('*'));
|
||||||
type.replace(QLatin1String(" >"), QLatin1String(">"));
|
type.replace(QLatin1String(" >"), QLatin1String(">"));
|
||||||
|
@@ -42,6 +42,8 @@ const char *description[] =
|
|||||||
"g++_stringset",
|
"g++_stringset",
|
||||||
"g++_stringvector",
|
"g++_stringvector",
|
||||||
"g++_wstringvector",
|
"g++_wstringvector",
|
||||||
|
"g++_unordered_set",
|
||||||
|
"g++_unordered_map",
|
||||||
"libc++_stringvector",
|
"libc++_stringvector",
|
||||||
"msvc_stdstring",
|
"msvc_stdstring",
|
||||||
"msvc_stdwstring",
|
"msvc_stdwstring",
|
||||||
@@ -64,6 +66,10 @@ const char *input[] =
|
|||||||
"std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
|
"std::set<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::less<std::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
|
||||||
"std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
|
"std::vector<std::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::allocator<std::basic_string<char, std::char_traits<char>, std::allocator<char> > > >",
|
||||||
"std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >",
|
"std::vector<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> >, std::allocator<std::basic_string<wchar_t, std::char_traits<wchar_t>, std::allocator<wchar_t> > > >",
|
||||||
|
|
||||||
|
"std::unordered_set<int, std::hash<int>, std::equal_to<int>, std::allocator<int> >",
|
||||||
|
"std::unordered_map<int, int, std::hash<int>, std::equal_to<int>, std::allocator<std::pair<int const, int> > >",
|
||||||
|
|
||||||
// libc++
|
// libc++
|
||||||
"std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >",
|
"std::__1::vector<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >, std::__1::allocator<std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > > >",
|
||||||
// MSVC
|
// MSVC
|
||||||
@@ -88,6 +94,8 @@ const char *output[] =
|
|||||||
"std::set<std::string>",
|
"std::set<std::string>",
|
||||||
"std::vector<std::string>",
|
"std::vector<std::string>",
|
||||||
"std::vector<std::wstring>",
|
"std::vector<std::wstring>",
|
||||||
|
"std::unordered_set<int>",
|
||||||
|
"std::unordered_map<int, int>",
|
||||||
// libc++
|
// libc++
|
||||||
"std::vector<std::string>",
|
"std::vector<std::string>",
|
||||||
// MSVC
|
// MSVC
|
||||||
|
@@ -2951,6 +2951,44 @@ void tst_Dumpers::dumper_data()
|
|||||||
% Check("is", "", "std::ifstream")
|
% Check("is", "", "std::ifstream")
|
||||||
% Check("ok", "true", "bool");
|
% Check("ok", "true", "bool");
|
||||||
|
|
||||||
|
QTest::newRow("StdUnorderedMap1")
|
||||||
|
<< Data("#include <unordered_map>\n",
|
||||||
|
"std::unordered_map<unsigned int, unsigned int> map;\n"
|
||||||
|
"map[11] = 1;\n"
|
||||||
|
"map[22] = 2;\n")
|
||||||
|
% Check("map", "<2 items>", "std::unordered_map<unsigned int, unsigned int>")
|
||||||
|
% Cxx11Profile()
|
||||||
|
% Check("map.0", "[0] 22", "2", "unsigned int")
|
||||||
|
% Check("map.1", "[1] 11", "1", "unsigned int");
|
||||||
|
|
||||||
|
QTest::newRow("StdUnorderedMap2")
|
||||||
|
<< Data("#include <unordered_map>\n"
|
||||||
|
"#include <string>\n",
|
||||||
|
"std::unordered_map<std::string, float> map;\n"
|
||||||
|
"map[\"11.0\"] = 11.0;\n"
|
||||||
|
"map[\"22.0\"] = 22.0;\n")
|
||||||
|
% Cxx11Profile()
|
||||||
|
% Check("map", "<2 items>", "std::unordered_map<std::string, float>")
|
||||||
|
//% Check("map.0", "[0]", "", "std::pair<std:string const, float>")
|
||||||
|
% Check("map.0.first", "\"22.0\"", "std::string")
|
||||||
|
% Check("map.0.second", "22", "float")
|
||||||
|
//% Check("map.1", "[1]", "", "std::pair<std::string const, float>")
|
||||||
|
% Check("map.1.first", "\"11.0\"", "std::string")
|
||||||
|
% Check("map.1.second", "11", "float");
|
||||||
|
|
||||||
|
QTest::newRow("StdUnorderedSet1")
|
||||||
|
<< Data("#include <unordered_set>\n",
|
||||||
|
"std::unordered_set<int> set;\n"
|
||||||
|
"set.insert(11);\n"
|
||||||
|
"set.insert(22);\n"
|
||||||
|
"set.insert(33);\n")
|
||||||
|
% Cxx11Profile()
|
||||||
|
% Check("set", "<3 items>", "std::unordered_set<int>")
|
||||||
|
% Check("set.0", "[0]", "33", "int")
|
||||||
|
% Check("set.1", "[1]", "22", "int")
|
||||||
|
% Check("set.2", "[2]", "11", "int");
|
||||||
|
|
||||||
|
|
||||||
QTest::newRow("ItemModel")
|
QTest::newRow("ItemModel")
|
||||||
<< Data("#include <QStandardItemModel>\n",
|
<< Data("#include <QStandardItemModel>\n",
|
||||||
"QStandardItemModel m;\n"
|
"QStandardItemModel m;\n"
|
||||||
|
Reference in New Issue
Block a user