From 3b7e30349f638125fc5bfda2376e12969ee64859 Mon Sep 17 00:00:00 2001 From: Andrii Semkiv Date: Wed, 15 Jan 2025 14:08:25 +0100 Subject: [PATCH] Debugger: Add a visualizer for QMultiHash ...and a very primitive test. Note that the visualization of `QMultiHash::iterator` does not work (this is a common problem for other containers too). I am not convinced that making effort to make it work now is worth it. Fixes: QTCREATORBUG-32313 Change-Id: If68cf17c8aa6d63da752aef07072725131bdbf52 Reviewed-by: hjk --- share/qtcreator/debugger/qttypes.py | 41 +++++++++++++++++++++++++++++ tests/auto/debugger/tst_dumpers.cpp | 26 ++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index 3108214b17c..c26f0bd52ad 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -928,6 +928,13 @@ def qform__QHash(): def qdump__QHash(d, value): qdumpHelper_QHash(d, value, value.type[0], value.type[1]) +def qdump__QMultiHash(d, value): + key_type = value.type[0] + value_type = value.type[1] + if d.qtVersionAtLeast(0x060000): + qdumpHelper_QMultiHash_6(d, value, key_type, value_type) + else: + qdumpHelper_QHash_5(d, value, key_type, value_type) def qdump__QVariantHash(d, value): qdumpHelper_QHash(d, value, d.createType('@QString'), d.createType('@QVariant')) @@ -1033,6 +1040,40 @@ def qdumpHelper_QHash_6(d, value, keyType, valueType): # d.putValue('total: %s item size: %s' % (count, entry_size)) +def qdumpHelper_QMultiHash_6(d, value, key_type, value_type): + dptr, size = d.split('pq', value) + if dptr == 0: + d.putItemCount(0) + return + + ref, _pad, _d_size, buckets, _seed, spans = d.split('i@qqqp', dptr) + + d.check(0 <= size and size <= 100 * 1000 * 1000) + d.check(-1 <= ref and ref < 100000) + d.putItemCount(size) + + if d.isExpanded(): + type_code = f'{{{key_type.name}}}@p' + _pp, entry_size, _fields = d.describeStruct(type_code) + with Children(d, size): + span_size = 128 + 2 * d.ptrSize() # Including tail padding. + nspans = int((buckets + 127) / 128) + count = 0 + for b in range(nspans): + span = spans + b * span_size + offsets, entries, _allocated, _next_free = d.split('128spbb', span) + for i in range(128): + offset = offsets[i] + if offset != 255: # Entry is used + entry = entries + offset * entry_size + key, _pad, chain = d.split(type_code, entry) + next = chain + while next != 0: + val, _pad, next = d.split(f'{{{value_type.name}}}@p', next) + d.putPairItem(count, (key, val), 'key', 'value') + count += 1 + + def qform__QHashNode(): return [DisplayFormat.CompactMap] diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 0e842f248bb..cb45fb6574e 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -2538,6 +2538,32 @@ void tst_Dumpers::dumper_data() + Check5("it3.key", "33", "int") + Check5("it3.value", FloatValue("33"), "float"); + // clang-format off + QTest::newRow("QMultiHash") + << Data("#include ", + + R"(const QMultiHash empty; + QMultiHash mh; + mh.insert(1, 1); + mh.insert(2, 2); + mh.insert(1, 3); + mh.insert(2, 4); + mh.insert(1, 5);)", + + "&empty, &mh") + + + CoreProfile() + + + Check("empty", "<0 items>", "QMultiHash") + + Check("mh", "<5 items>", "QMultiHash") + // due to unordered nature of the container, checking specific item values + // is not possible + + Check("mh.0.key", ValuePattern("[1,2]"), "int") + + Check("mh.0.value", ValuePattern("[1-5]"), "int") + + Check("mh.4.key", ValuePattern("[1,2]"), "int") + + Check("mh.4.value", ValuePattern("[1-5]"), "int"); + // clang-format on + QTest::newRow("QHostAddress") << Data("#include \n",