From d37e890a1de14e2d730027f7163edaaf46f7fdb6 Mon Sep 17 00:00:00 2001 From: hjk <hjk121@nokiamail.com> Date: Tue, 28 Jan 2014 23:23:01 +0100 Subject: [PATCH] Debugger: Show name also for QObject subclasses without Q_OBJECT macro Change-Id: Ifabf3cc68751a06c15fc1a5a05cad5e5a64c8775 Reviewed-by: hjk <hjk121@nokiamail.com> --- share/qtcreator/debugger/dumper.py | 8 ++-- share/qtcreator/debugger/gdbbridge.py | 61 +++++++++++++++++---------- share/qtcreator/debugger/qttypes.py | 2 +- tests/auto/debugger/tst_dumpers.cpp | 2 +- 4 files changed, 43 insertions(+), 30 deletions(-) diff --git a/share/qtcreator/debugger/dumper.py b/share/qtcreator/debugger/dumper.py index cd57ad04332..d78a535ccee 100644 --- a/share/qtcreator/debugger/dumper.py +++ b/share/qtcreator/debugger/dumper.py @@ -312,8 +312,9 @@ class DumperBase: # This keeps canonical forms of the typenames, without array indices etc. self.cachedFormats = {} - self.knownQObjectTypes = set() - self.knownNonQObjectTypes = set() + # Maps type names to static metaobjects. If a type is known + # to not be QObject derived, it contains a 0 value. + self.knownStaticMetaObjects = {} def stripForFormat(self, typeName): @@ -854,8 +855,6 @@ class DumperBase: self.putItem(value.dereference()) def putQObjectNameValue(self, value): - if str(value.type) in self.knownNonQObjectTypes: - return try: intSize = self.intSize() ptrSize = self.ptrSize() @@ -910,7 +909,6 @@ class DumperBase: except: #warn("NO QOBJECT: %s" % value.type) - #self.knownNonQObjectTypes.add(str(value.type)) pass diff --git a/share/qtcreator/debugger/gdbbridge.py b/share/qtcreator/debugger/gdbbridge.py index 41795ab32ef..a0b1d21753d 100644 --- a/share/qtcreator/debugger/gdbbridge.py +++ b/share/qtcreator/debugger/gdbbridge.py @@ -970,32 +970,48 @@ class Dumper(DumperBase): def dereferenceValue(self, value): return toInteger(value.cast(self.voidPtrType())) - def isQObject(self, value): - typeName = str(value.type) - if typeName in self.knownQObjectTypes: - return True - if typeName in self.knownNonQObjectTypes: - return False + def extractStaticMetaObjectHelper(self, typeobj): + """ + Checks whether type has a Q_OBJECT macro. + Returns the staticMetaObject, or 0. + """ + typeName = str(typeobj) + result = self.knownStaticMetaObjects.get(typeName, None) + if result is not None: # Is 0 or the static metaobject. + return result - smo = typeName + "::staticMetaObject" + staticMetaObjectName = typeName + "::staticMetaObject" try: - result = gdb.lookup_global_symbol(smo) - if result: - self.knownQObjectTypes.add(typeName) - else: - self.knownNonQObjectTypes.add(typeName) + result = gdb.lookup_global_symbol(staticMetaObjectName) + result = result.value() if result else 0 + self.knownStaticMetaObjects[typeName] = result return result except: pass # Older GDB... try: - gdb.parse_and_eval(smo) - self.knownQObjectTypes.add(typeName) - return True + result = gdb.parse_and_eval(staticMetaObjectName) + self.knownStaticMetaObjects[typeName] = result + return result except: - self.knownNonQObjectTypes.add(typeName) - return False + self.knownStaticMetaObjects[typeName] = 0 + return 0 + + def extractStaticMetaObject(self, typeobj): + """ + Checks recursively whether a type derives from QObject. + """ + result = self.extractStaticMetaObjectHelper(typeobj) + if result: + return result + fields = typeobj.fields() + if not len(fields): + return 0 + if not fields[0].is_base_class: + return 0 + return self.extractStaticMetaObject(fields[0].type) + def put(self, value): self.output.append(value) @@ -1401,9 +1417,9 @@ class Dumper(DumperBase): #warn("INAME: %s " % self.currentIName) #warn("INAMES: %s " % self.expandedINames) #warn("EXPANDED: %s " % (self.currentIName in self.expandedINames)) - isQObject = self.isQObject(value) - if isQObject: - self.putQObjectNameValue(value) # Is this too expensive? + staticMetaObject = self.extractStaticMetaObject(value.type) + if staticMetaObject: + self.putQObjectNameValue(value) self.putType(typeName) self.putEmptyValue() self.putNumChild(len(type.fields())) @@ -1412,9 +1428,8 @@ class Dumper(DumperBase): innerType = None with Children(self, 1, childType=innerType): self.putFields(value) - if isQObject: - smo = value["staticMetaObject"] - self.putQObjectGuts(value, smo) + if staticMetaObject: + self.putQObjectGuts(value, staticMetaObject) def putPlainChildren(self, value): diff --git a/share/qtcreator/debugger/qttypes.py b/share/qtcreator/debugger/qttypes.py index d8148ab9cb9..7bb6256e660 100644 --- a/share/qtcreator/debugger/qttypes.py +++ b/share/qtcreator/debugger/qttypes.py @@ -1136,7 +1136,7 @@ def qdump__QMetaObject(d, value): d.putIntItem("flags", d.extractInt(data + 48)) d.putIntItem("signalCount", d.extractInt(data + 52)) -def qdump__QObject(d, value): +def _qdump__QObject(d, value): d.putQObjectNameValue(value) ns = d.qtNamespace() diff --git a/tests/auto/debugger/tst_dumpers.cpp b/tests/auto/debugger/tst_dumpers.cpp index 926d4acdde3..c0cf5a45b29 100644 --- a/tests/auto/debugger/tst_dumpers.cpp +++ b/tests/auto/debugger/tst_dumpers.cpp @@ -5048,7 +5048,7 @@ void tst_Dumpers::dumper_data() "file.setObjectName(\"A file\");\n") % CoreProfile() % QtVersion(50000) - % Check("file", "", "MyFile") + % Check("file", "\"A file\"", "MyFile") % Check("file.@1", "[@QFile]", "\"/tmp/tt\"", "@QFile"); // FIXME: The classname in the iname is sub-optimal. //% Check("file.@1.[QFileDevice]", "[@QFileDevice]", "\"A file\"", "@QFileDevice"); -- GitLab