forked from qt-creator/qt-creator
Added dumpers for `tl::expected` and `Utils::Result` utility classes. Added a basic test. Useless `enum` prefix from CDB enum types (e.g. `enum MyEnum`) will be discarded in tests (credits to @hjk). Note that the include path for the newly added test executable is based on `__FILE__` macro value so it might easily break if the sources are reorganized. Also creating a test for `Utils::Result` is practically impossible within current setup as it is not a header only class, so the test binary must actually link against the correct version of Utils library target. Fixes: QTCREATORBUG-31795 Change-Id: I7f9ccb92d0c59333a2dca4ba928ac991f1e5238b Reviewed-by: hjk <hjk@qt.io>
NOTE: While the primary intention of this pretty printing implementation is to provide what Qt Creator needs, it can sometimes be used in plain GDB and LLDB sessions, too. This features is provided as-is. There is no guarantee this works in any way outside Qt Creator, this setup is not officially supported. Bugreports or (better!) patches are welcome. With python import sys python sys.path.insert(1, '<path/to/qtcreator>/share/qtcreator/debugger/') python from gdbbridge import * in .gdbinit there is a new "GDB command", called "pp". With code like int main(int argc, char *argv[]) { QString ss = "Hello"; QApplication app(argc, argv); app.setObjectName(ss); // break here } the "pp" command can be used as follows: (gdb) pp app app = [ <QGuiApplication> = {"Hello"} staticMetaObject = <QMetaObject> = {""} [parent] = <QObject *> = {"0x0"} [children] = <QObjectList> = {"<3 items>"} [properties] = "<>0 items>" [methods] = "<6 items>" [signals] = "<1 items>" ],<QApplication> = {"Hello"} (gdb) pp app [properties],[children] app = [ <QGuiApplication> = {"Hello"} staticMetaObject = <QMetaObject> = {""} [parent] = <QObject *> = {"0x0"} [children] = [ <QObject> = {""} <QObject> = {""} <QObject> = {"fusion"} ],<QObjectList> = {"<3 items>"} [properties] = [ windowIcon = <QVariant (QIcon)> = {""} cursorFlashTime = <QVariant (int)> = {"1000"} doubleClickInterval = <QVariant (int)> = {"400"} keyboardInputInterval = <QVariant (int)> = {"400"} wheelScrollLines = <QVariant (int)> = {"3"} globalStrut = <QVariant (QSize)> = {"(0, 0)"} startDragTime = <QVariant (int)> = {"500"} startDragDistance = <QVariant (int)> = {"10"} styleSheet = <QVariant (QString)> = {""} autoSipEnabled = <QVariant (bool)> = {"true"} ],"<10 items>" [methods] = "<6 items>" [signals] = "<1 items>" ],<QApplication> = {"Hello"} (gdb) pp ss ss = <QString> = {"Hello"} Or for LLDB (.lldbinit or directly in the LLDB interpreter): command script import <path/to/qtcreator>/share/qtcreator/debugger/lldbbridge.py This will add LLDB summary providers for all the Qt types in a new type category named 'Qt'. In order to hook a new debugger backend into this "common pretty printing system", the backend should expose a Python API containing at least the following: class Value: name() -> string # Name of this thing or None type() -> Type # Type of this value asBytes() -> bytes # Memory contents of this object, or None address() -> int # Address of this object, or None dereference() -> Value # Dereference if value is pointer, # remove reference if value is reference. hasChildren() -> bool # Whether this object has subobjects. expand() -> bool # Make sure that children are accessible. nativeDebuggerValue() -> string # Dumper value returned from the debugger childFromName(string name) -> Value # (optional) childFromField(Field field) -> Value # (optional) childFromIndex(int position) -> Value # (optional) class Type: name() -> string # Full name of this type bitsize() -> int # Size of type in bits code() -> TypeCodeTypedef | TypeCodeStruct | TypeCodeVoid | TypeCodeIntegral | TypeCodeFloat | TypeCodeEnum | TypeCodePointer | TypeCodeArray | TypeCodeComplex | TypeCodeReference | TypeCodeFunction | TypeCodeMemberPointer | TypeCodeUnresolvable unqualified() -> Type # Type without const/volatile target() -> Type # Type dereferenced if it is a pointer type, element if array etc stripTypedef() -> Type # Type with typedefs removed fields() -> [ Fields ] # List of fields (member and base classes) of this type templateArgument(int pos, bool numeric) -> Type or int # (optional) class Field: name() -> string # Name of member, None for anonymous items isBaseClass() -> bool # Whether this is a base class or normal member type() -> Type # Type of this member parentType() -> Type # Type of class this member belongs to bitsize() -> int # Size of member in bits bitpos() -> int # Offset of member in parent type in bits parseAndEvaluate(string: expr) -> Value # or None if not possible. lookupType(string: name) -> Type # or None if not possible. listOfLocals() -> [ Value ] # List of items currently in scope. readRawMemory(ULONG64 address, ULONG size) -> bytes # Read a block of data from the virtual address space