Changeset View
Changeset View
Standalone View
Standalone View
debuggers/lldb/formatters/qt.py
Show All 12 Lines | |||||
13 | # This program is distributed in the hope that it will be useful, | 13 | # This program is distributed in the hope that it will be useful, | ||
14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | 14 | # but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | 15 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
16 | # GNU General Public License for more details. | 16 | # GNU General Public License for more details. | ||
17 | # | 17 | # | ||
18 | # You should have received a copy of the GNU General Public License | 18 | # You should have received a copy of the GNU General Public License | ||
19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | 19 | # along with this program. If not, see <http://www.gnu.org/licenses/>. | ||
20 | # | 20 | # | ||
21 | from __future__ import print_function | ||||
21 | 22 | | |||
22 | import calendar | | |||
23 | import time | 23 | import time | ||
24 | import datetime as dt | 24 | import datetime as dt | ||
25 | import string | ||||
25 | from urlparse import urlsplit, urlunsplit | 26 | from urlparse import urlsplit, urlunsplit | ||
26 | 27 | | |||
27 | import locale | 28 | import locale | ||
28 | import lldb | 29 | import lldb | ||
29 | 30 | | |||
30 | from helpers import * | 31 | from helpers import (HiddenMemberProvider, quote, unquote, unichr, toSBPointer, Iterator, validAddr, | ||
32 | validPointer, invoke, rename, canonicalized_type_name) | ||||
33 | | ||||
31 | 34 | | |||
32 | def __lldb_init_module(debugger, unused): | 35 | def __lldb_init_module(debugger, unused): | ||
33 | debugger.HandleCommand('type synthetic add QString -w kdevelop-qt -l qt.QStringFormatter') | 36 | debugger.HandleCommand('type synthetic add QString -w kdevelop-qt -l qt.QStringFormatter') | ||
34 | debugger.HandleCommand('type summary add QString -w kdevelop-qt -F qt.QStringSummaryProvider') | 37 | debugger.HandleCommand('type summary add QString -w kdevelop-qt -F qt.QStringSummaryProvider') | ||
35 | 38 | | |||
36 | debugger.HandleCommand('type summary add QChar -w kdevelop-qt -F qt.QCharSummaryProvider') | 39 | debugger.HandleCommand('type summary add QChar -w kdevelop-qt -F qt.QCharSummaryProvider') | ||
37 | 40 | | |||
38 | debugger.HandleCommand('type synthetic add QByteArray -w kdevelop-qt -l qt.QByteArrayFormatter') | 41 | debugger.HandleCommand('type synthetic add QByteArray -w kdevelop-qt -l qt.QByteArrayFormatter') | ||
▲ Show 20 Lines • Show All 43 Lines • ▼ Show 20 Line(s) | |||||
82 | 85 | | |||
83 | debugger.HandleCommand('type synthetic add QTime -w kdevelop-qt -l qt.QTimeFormatter') | 86 | debugger.HandleCommand('type synthetic add QTime -w kdevelop-qt -l qt.QTimeFormatter') | ||
84 | debugger.HandleCommand('type summary add -x QTime -w kdevelop-qt -e -F qt.QTimeSummaryProvider') | 87 | debugger.HandleCommand('type summary add -x QTime -w kdevelop-qt -e -F qt.QTimeSummaryProvider') | ||
85 | 88 | | |||
86 | debugger.HandleCommand('type synthetic add QDateTime -w kdevelop-qt -l qt.QDateTimeFormatter') | 89 | debugger.HandleCommand('type synthetic add QDateTime -w kdevelop-qt -l qt.QDateTimeFormatter') | ||
87 | debugger.HandleCommand('type summary add -x QDateTime -w kdevelop-qt -e -F qt.QDateTimeSummaryProvider') | 90 | debugger.HandleCommand('type summary add -x QDateTime -w kdevelop-qt -e -F qt.QDateTimeSummaryProvider') | ||
88 | 91 | | |||
89 | debugger.HandleCommand('type synthetic add QUrl -w kdevelop-qt -l qt.QUrlFormatter') | 92 | debugger.HandleCommand('type synthetic add QUrl -w kdevelop-qt -l qt.QUrlFormatter') | ||
90 | debugger.HandleCommand('type summary add QUrl -w kdevelop-qt -e -s "${svar.(encoded)}"') | 93 | debugger.HandleCommand('type summary add QUrl -w kdevelop-qt -e -F qt.QUrlSummaryProvider') | ||
91 | 94 | | |||
92 | debugger.HandleCommand('type synthetic add QUuid -w kdevelop-qt -l qt.QUuidFormatter') | 95 | debugger.HandleCommand('type synthetic add QUuid -w kdevelop-qt -l qt.QUuidFormatter') | ||
93 | debugger.HandleCommand('type summary add QUuid -w kdevelop-qt -F qt.QUuidSummaryProvider') | 96 | debugger.HandleCommand('type summary add QUuid -w kdevelop-qt -F qt.QUuidSummaryProvider') | ||
94 | 97 | | |||
95 | debugger.HandleCommand('type category enable kdevelop-qt') | 98 | debugger.HandleCommand('type category enable kdevelop-qt') | ||
96 | 99 | | |||
97 | 100 | | |||
98 | def printableQString(valobj): | 101 | def printableQString(valobj): | ||
99 | pointer = 0 | 102 | pointer = 0 | ||
100 | length = 0 | 103 | length = 0 | ||
101 | if valobj.IsValid(): | 104 | if valobj.IsValid(): | ||
102 | d = valobj.GetChildMemberWithName('d') | 105 | d = valobj.GetChildMemberWithName('d') | ||
103 | data = d.GetChildMemberWithName('data') | 106 | data = d.GetChildMemberWithName('data') | ||
104 | offset = d.GetChildMemberWithName('offset') | 107 | offset = d.GetChildMemberWithName('offset') | ||
105 | size = d.GetChildMemberWithName('size') | 108 | size = d.GetChildMemberWithName('size') | ||
106 | 109 | | |||
107 | isQt4 = data.IsValid() | 110 | isQt4 = data.IsValid() | ||
108 | size_val = size.GetValueAsSigned(-1) | 111 | size_val = size.GetValueAsSigned(-1) | ||
109 | alloc = d.GetChildMemberWithName('alloc').GetValueAsUnsigned(0) | 112 | alloc = d.GetChildMemberWithName('alloc').GetValueAsUnsigned(0) | ||
110 | if isQt4: | 113 | if isQt4: | ||
111 | alloc += 1 | 114 | alloc += 1 | ||
112 | 115 | | |||
113 | | ||||
114 | # some sanity check to see if we are dealing with garbage | 116 | # some sanity check to see if we are dealing with garbage | ||
115 | if size_val < 0 or size_val >= alloc: | 117 | if size_val < 0 or size_val >= alloc: | ||
116 | return None, 0, 0 | 118 | return None, 0, 0 | ||
117 | 119 | | |||
118 | tooLarge = u'' | 120 | tooLarge = u'' | ||
119 | if size_val > HiddenMemberProvider._capping_size(): | 121 | if size_val > HiddenMemberProvider._capping_size(): | ||
120 | tooLarge = u'...' | 122 | tooLarge = u'...' | ||
121 | size_val = HiddenMemberProvider._capping_size() | 123 | size_val = HiddenMemberProvider._capping_size() | ||
122 | 124 | | |||
123 | | ||||
124 | if isQt4: | 125 | if isQt4: | ||
125 | pointer = data.GetValueAsUnsigned(0) | 126 | pointer = data.GetValueAsUnsigned(0) | ||
126 | elif offset.IsValid(): | 127 | elif offset.IsValid(): | ||
127 | pointer = d.GetValueAsUnsigned(0) + offset.GetValueAsUnsigned(0) | 128 | pointer = d.GetValueAsUnsigned(0) + offset.GetValueAsUnsigned(0) | ||
128 | else: | 129 | else: | ||
129 | qarraydata_t = valobj.GetTarget().FindFirstType('QArrayData') | 130 | qarraydata_t = valobj.GetTarget().FindFirstType('QArrayData') | ||
130 | if qarraydata_t.IsValid(): | 131 | if qarraydata_t.IsValid(): | ||
131 | pointer = d.GetValueAsUnsigned(0) + qarraydata_t.GetByteSize() | 132 | pointer = d.GetValueAsUnsigned(0) + qarraydata_t.GetByteSize() | ||
132 | else: | 133 | else: | ||
133 | pointer = d.GetValueAsUnsigned(0) + 24 # Fallback to hardcoded value | 134 | pointer = d.GetValueAsUnsigned(0) + 24 # Fallback to hardcoded value | ||
134 | 135 | | |||
135 | # size in the number of chars, each char is 2 bytes in UTF16 | 136 | # size in the number of chars, each char is 2 bytes in UTF16 | ||
136 | length = size_val * 2 | 137 | length = size_val * 2 | ||
137 | if length == 0: | 138 | if length == 0: | ||
138 | return u'', pointer, length | 139 | return u'', pointer, length | ||
139 | 140 | | |||
140 | try: | 141 | try: | ||
141 | error = lldb.SBError() | 142 | error = lldb.SBError() | ||
142 | string_data = valobj.process.ReadMemory(pointer, length, error) | 143 | string_data = valobj.process.ReadMemory(pointer, length, error) | ||
143 | # The QString object might be not yet initialized. In this case size is a bogus value, | 144 | # The QString object might be not yet initialized. In this case size is a bogus value, | ||
144 | # and memory access may fail | 145 | # and memory access may fail | ||
145 | if error.Success(): | 146 | if error.Success(): | ||
146 | string = string_data.decode('utf-16') | 147 | content = string_data.decode('utf-16') | ||
147 | return string + tooLarge, pointer, length | 148 | return content + tooLarge, pointer, length | ||
148 | except: | 149 | except: | ||
149 | pass | 150 | pass | ||
150 | return None, 0, 0 | 151 | return None, 0, 0 | ||
151 | 152 | | |||
152 | 153 | | |||
153 | def QStringSummaryProvider(valobj, internal_dict): | 154 | def QStringSummaryProvider(valobj, internal_dict): | ||
154 | if valobj.IsValid(): | 155 | if valobj.IsValid(): | ||
155 | content = valobj.GetChildMemberWithName('(content)') | 156 | content = valobj.GetChildMemberWithName('(content)') | ||
156 | if content.IsValid(): | 157 | if content.IsValid(): | ||
157 | return content.GetSummary() | 158 | summary = content.GetSummary() | ||
158 | else: | 159 | if summary is not None: | ||
159 | # No synthetic provider installed, get the content by ourselves | 160 | return summary | ||
160 | printable, _, _ = printableQString(valobj) | 161 | # Something wrong with synthetic provider, or | ||
161 | if printable is not None: | 162 | # no synthetic provider installed, get the content by ourselves | ||
162 | return quote(printable) | 163 | printable, _, _ = printableQString(valobj) | ||
164 | if printable is not None: | ||||
165 | return quote(printable) | ||||
163 | return '<Invalid>' | 166 | return '<Invalid>' | ||
164 | 167 | | |||
165 | 168 | | |||
166 | class QStringFormatter(HiddenMemberProvider): | 169 | class QStringFormatter(HiddenMemberProvider): | ||
167 | """A lldb synthetic provider for QString""" | 170 | """A lldb synthetic provider for QString""" | ||
168 | 171 | | |||
169 | def __init__(self, valobj, internal_dict): | 172 | def __init__(self, valobj, internal_dict): | ||
170 | super(QStringFormatter, self).__init__(valobj, internal_dict) | 173 | super(QStringFormatter, self).__init__(valobj, internal_dict) | ||
Show All 13 Lines | 183 | for idx in range(0, strLength): | |||
184 | self._addChild(var) | 187 | self._addChild(var) | ||
185 | quoted_printable_expr = quote(printable) | 188 | quoted_printable_expr = quote(printable) | ||
186 | self._addChild(('(content)', quoted_printable_expr), hidden=True) | 189 | self._addChild(('(content)', quoted_printable_expr), hidden=True) | ||
187 | 190 | | |||
188 | 191 | | |||
189 | def QCharSummaryProvider(valobj, internal_dict): | 192 | def QCharSummaryProvider(valobj, internal_dict): | ||
190 | if valobj.IsValid(): | 193 | if valobj.IsValid(): | ||
191 | ucs = valobj.GetChildMemberWithName('ucs').GetValueAsUnsigned(0) | 194 | ucs = valobj.GetChildMemberWithName('ucs').GetValueAsUnsigned(0) | ||
192 | return unichr(ucs).__repr__().lstrip('u') | 195 | if ucs == 39: | ||
196 | # for '\'', python returns "'" rather than '\'' | ||||
197 | return u"'\\''" | ||||
198 | else: | ||||
199 | return unichr(ucs).__repr__()[1:] | ||||
193 | return None | 200 | return None | ||
194 | 201 | | |||
195 | 202 | | |||
196 | def printableQByteArray(valobj): | 203 | def printableQByteArray(valobj): | ||
197 | if valobj.IsValid(): | 204 | if valobj.IsValid(): | ||
198 | d = valobj.GetChildMemberWithName('d') | 205 | d = valobj.GetChildMemberWithName('d') | ||
199 | data = d.GetChildMemberWithName('data') | 206 | data = d.GetChildMemberWithName('data') | ||
200 | offset = d.GetChildMemberWithName('offset') | 207 | offset = d.GetChildMemberWithName('offset') | ||
Show All 28 Lines | |||||
229 | try: | 236 | try: | ||
230 | error = lldb.SBError() | 237 | error = lldb.SBError() | ||
231 | string_data = valobj.process.ReadMemory(pointer, length, error) | 238 | string_data = valobj.process.ReadMemory(pointer, length, error) | ||
232 | # The object might be not yet initialized. In this case size is a bogus value, | 239 | # The object might be not yet initialized. In this case size is a bogus value, | ||
233 | # and memory access may fail | 240 | # and memory access may fail | ||
234 | if error.Success(): | 241 | if error.Success(): | ||
235 | # replace non-ascii byte with a space and get a printable version | 242 | # replace non-ascii byte with a space and get a printable version | ||
236 | ls = list(string_data) | 243 | ls = list(string_data) | ||
237 | for idx in range(0, length): | 244 | for idx in range(length): | ||
238 | byte = ord(ls[idx]) | 245 | if ls[idx] in string.printable: | ||
239 | if byte >= 128 or byte < 0: | 246 | if ls[idx] != "'": | ||
240 | ls[idx] = hex(byte).replace('0', '\\', 1) | 247 | # convert tab, nl, ..., and '\\' to r'\\' | ||
241 | elif byte == 0: # specical handle for 0, as hex(0) returns '\\x0' | 248 | ls[idx] = ls[idx].__repr__()[1:-1] | ||
242 | ls[idx] = '\\x00' | 249 | else: | ||
243 | string = u''.join(ls) | 250 | ls[idx] = r'\x{:02x}'.format(ord(ls[idx])) | ||
244 | return string + tooLarge, pointer, length | 251 | content = u''.join(ls) | ||
252 | return content + tooLarge, pointer, length | ||||
245 | except: | 253 | except: | ||
246 | pass | 254 | pass | ||
247 | return None, 0, 0 | 255 | return None, 0, 0 | ||
248 | 256 | | |||
249 | 257 | | |||
250 | def QByteArraySummaryProvider(valobj, internal_dict): | 258 | def QByteArraySummaryProvider(valobj, internal_dict): | ||
251 | if valobj.IsValid(): | 259 | if valobj.IsValid(): | ||
252 | content = valobj.GetChildMemberWithName('(content)') | 260 | content = valobj.GetChildMemberWithName('(content)') | ||
253 | if content.IsValid(): | 261 | if content.IsValid(): | ||
254 | return content.GetSummary() | 262 | summary = content.GetSummary() | ||
255 | else: | 263 | if summary is not None: | ||
256 | # Our synthetic provider is not installed, get the content by ourselves | 264 | # unlike QString, we quoted the (content) twice to preserve our own quotation, | ||
257 | printable, _, _ = printableQByteArray(valobj) | 265 | # must undo the quotation done by GetSummary | ||
258 | if printable is not None: | 266 | return 'b' + unquote(summary) | ||
259 | return quote(printable) | 267 | # Something wrong with our synthetic provider, get the content by ourselves | ||
268 | printable, _, _ = printableQByteArray(valobj) | ||||
269 | if printable is not None: | ||||
270 | # first replace " to \", and suround by "", no need to escape other things which | ||||
271 | # are handled in printableQByteArray. | ||||
272 | return 'b"{}"'.format(printable.replace('"', '\\"')) | ||||
260 | return '<Invalid>' | 273 | return '<Invalid>' | ||
261 | 274 | | |||
262 | 275 | | |||
263 | class QByteArrayFormatter(HiddenMemberProvider): | 276 | class QByteArrayFormatter(HiddenMemberProvider): | ||
264 | """A lldb synthetic provider for QByteArray""" | 277 | """A lldb synthetic provider for QByteArray""" | ||
265 | 278 | | |||
266 | def __init__(self, valobj, internal_dict): | 279 | def __init__(self, valobj, internal_dict): | ||
267 | super(QByteArrayFormatter, self).__init__(valobj, internal_dict) | 280 | super(QByteArrayFormatter, self).__init__(valobj, internal_dict) | ||
268 | self._char_type = valobj.GetType().GetBasicType(lldb.eBasicTypeChar) | 281 | self._char_type = valobj.GetType().GetBasicType(lldb.eBasicTypeChar) | ||
269 | self._char_size = self._char_type.GetByteSize() | 282 | self._char_size = self._char_type.GetByteSize() | ||
270 | 283 | | |||
271 | def _update(self): | 284 | def _update(self): | ||
272 | printable, dataPointer, byteLength = printableQByteArray(self.valobj) | 285 | printable, dataPointer, byteLength = printableQByteArray(self.valobj) | ||
273 | self._num_children = byteLength | 286 | self._num_children = byteLength | ||
274 | 287 | | |||
275 | if printable is not None: | 288 | if printable is not None: | ||
276 | for idx in range(0, self._num_children): | 289 | for idx in range(0, self._num_children): | ||
277 | var = self.valobj.CreateValueFromAddress('[{}]'.format(idx), | 290 | var = self.valobj.CreateValueFromAddress('[{}]'.format(idx), | ||
278 | dataPointer + idx * self._char_size, | 291 | dataPointer + idx * self._char_size, | ||
279 | self._char_type) | 292 | self._char_type) | ||
280 | self._addChild(var) | 293 | self._addChild(var) | ||
294 | | ||||
295 | # first replace " to \", and suround by "", no need to escape other things which | ||||
296 | # are handled in printableQByteArray. | ||||
297 | printable = '"{}"'.format(printable.replace('"', '\\"')) | ||||
298 | # then we need to quote again, as the quoted_printable_expr is parsed by the lldb to | ||||
299 | # produce the final content, which removes one level of quotation | ||||
281 | quoted_printable_expr = quote(printable) | 300 | quoted_printable_expr = quote(printable) | ||
282 | self._addChild(('(content)', quoted_printable_expr), hidden=True) | 301 | self._addChild(('(content)', quoted_printable_expr), hidden=True) | ||
283 | 302 | | |||
284 | 303 | | |||
285 | class BasicListFormatter(HiddenMemberProvider): | 304 | class BasicListFormatter(HiddenMemberProvider): | ||
286 | """A lldb synthetic provider for QList like types""" | 305 | """A lldb synthetic provider for QList like types""" | ||
287 | 306 | | |||
288 | def __init__(self, valobj, internal_dict, item_typename): | 307 | def __init__(self, valobj, internal_dict, item_typename): | ||
289 | super(BasicListFormatter, self).__init__(valobj, internal_dict) | 308 | super(BasicListFormatter, self).__init__(valobj, internal_dict) | ||
290 | if item_typename is None: | 309 | if item_typename is None: | ||
291 | self._item_type = valobj.GetType().GetTemplateArgumentType(0) | 310 | self._item_type = valobj.GetType().GetTemplateArgumentType(0) | ||
292 | else: | 311 | else: | ||
293 | self._item_type = valobj.GetTarget().FindFirstType(item_typename) | 312 | self._item_type = valobj.GetTarget().FindFirstType(item_typename) | ||
294 | pvoid_type = valobj.GetTarget().GetBasicType(lldb.eBasicTypeVoid).GetPointerType() | 313 | pvoid_type = valobj.GetTarget().GetBasicType(lldb.eBasicTypeVoid).GetPointerType() | ||
295 | self._pvoid_size = pvoid_type.GetByteSize() | 314 | self._pvoid_size = pvoid_type.GetByteSize() | ||
296 | 315 | | |||
297 | #from QTypeInfo::isLarge | 316 | # from QTypeInfo::isLarge | ||
298 | isLarge = self._item_type.GetByteSize() > self._pvoid_size | 317 | isLarge = self._item_type.GetByteSize() > self._pvoid_size | ||
299 | 318 | | |||
300 | #unfortunately we can't use QTypeInfo<T>::isStatic as it's all inlined, so use | 319 | # unfortunately we can't use QTypeInfo<T>::isStatic as it's all inlined, so use | ||
301 | #this list of types that use Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE) | 320 | # this list of types that use Q_DECLARE_TYPEINFO(T, Q_MOVABLE_TYPE) | ||
302 | #(obviously it won't work for custom types) | 321 | # (obviously it won't work for custom types) | ||
303 | movableTypes = ['QRect', 'QRectF', 'QString', 'QMargins', 'QLocale', 'QChar', 'QDate', | 322 | movableTypes = ['QRect', 'QRectF', 'QString', 'QMargins', 'QLocale', 'QChar', 'QDate', | ||
304 | 'QTime', 'QDateTime', 'QVector', 'QRegExpr', 'QPoint', 'QPointF', 'QByteArray', | 323 | 'QTime', 'QDateTime', 'QVector', 'QRegExpr', 'QPoint', 'QPointF', 'QByteArray', | ||
305 | 'QSize', 'QSizeF', 'QBitArray', 'QLine', 'QLineF', 'QModelIndex', | 324 | 'QSize', 'QSizeF', 'QBitArray', 'QLine', 'QLineF', 'QModelIndex', | ||
306 | 'QPersitentModelIndex', 'QVariant', 'QFileInfo', 'QUrl', 'QXmlStreamAttribute', | 325 | 'QPersitentModelIndex', 'QVariant', 'QFileInfo', 'QUrl', 'QXmlStreamAttribute', | ||
307 | 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration', | 326 | 'QXmlStreamNamespaceDeclaration', 'QXmlStreamNotationDeclaration', | ||
308 | 'QXmlStreamEntityDeclaration', 'QPair<int, int>'] | 327 | 'QXmlStreamEntityDeclaration', 'QPair<int, int>'] | ||
309 | movableTypes = [valobj.GetTarget().FindFirstType(t) for t in movableTypes] | 328 | movableTypes = [valobj.GetTarget().FindFirstType(t) for t in movableTypes] | ||
310 | #this list of types that use Q_DECLARE_TYPEINFO(T, Q_PRIMITIVE_TYPE) (from qglobal.h) | 329 | # this list of types that use Q_DECLARE_TYPEINFO(T, Q_PRIMITIVE_TYPE) (from qglobal.h) | ||
311 | primitiveTypes = ['bool', 'char', 'signed char', 'unsigned char', 'short', 'unsigned short', | 330 | primitiveTypes = ['bool', 'char', 'signed char', 'unsigned char', 'short', 'unsigned short', | ||
312 | 'int', 'unsigned int', 'long', 'unsigned long', 'long long', | 331 | 'int', 'unsigned int', 'long', 'unsigned long', 'long long', | ||
313 | 'unsigned long long', 'float', 'double'] | 332 | 'unsigned long long', 'float', 'double'] | ||
314 | primitiveTypes = [valobj.GetTarget().FindFirstType(t) for t in primitiveTypes] | 333 | primitiveTypes = [valobj.GetTarget().FindFirstType(t) for t in primitiveTypes] | ||
315 | 334 | | |||
316 | if self._item_type in movableTypes or self._item_type in primitiveTypes: | 335 | if self._item_type in movableTypes or self._item_type in primitiveTypes: | ||
317 | isStatic = False | 336 | isStatic = False | ||
318 | else: | 337 | else: | ||
319 | isStatic = not self._item_type.IsPointerType() | 338 | isStatic = not self._item_type.IsPointerType() | ||
320 | 339 | | |||
321 | #see QList::Node::t() | 340 | # see QList::Node::t() | ||
322 | self._externalStorage = isLarge or isStatic | 341 | self._externalStorage = isLarge or isStatic | ||
323 | # If is external storage, then the node (a void*) is a pointer to item | 342 | # If is external storage, then the node (a void*) is a pointer to item | ||
324 | # else the item is stored inside the node | 343 | # else the item is stored inside the node | ||
325 | if self._externalStorage: | 344 | if self._externalStorage: | ||
326 | self._node_type = self._item_type.GetPointerType() | 345 | self._node_type = self._item_type.GetPointerType() | ||
327 | else: | 346 | else: | ||
328 | self._node_type = self._item_type | 347 | self._node_type = self._item_type | ||
329 | 348 | | |||
▲ Show 20 Lines • Show All 65 Lines • ▼ Show 20 Line(s) | 413 | else: | |||
395 | d = self.valobj.GetChildMemberWithName('d') | 414 | d = self.valobj.GetChildMemberWithName('d') | ||
396 | offset = d.GetChildMemberWithName('offset') | 415 | offset = d.GetChildMemberWithName('offset') | ||
397 | pArray = d.GetValueAsUnsigned(0) + offset.GetValueAsUnsigned(0) | 416 | pArray = d.GetValueAsUnsigned(0) + offset.GetValueAsUnsigned(0) | ||
398 | 417 | | |||
399 | # sanity check | 418 | # sanity check | ||
400 | if not toSBPointer(self.valobj, pArray, self._item_type).IsValid(): | 419 | if not toSBPointer(self.valobj, pArray, self._item_type).IsValid(): | ||
401 | return | 420 | return | ||
402 | 421 | | |||
403 | #self._num_children = d.GetChildMemberWithName('size').GetValueAsUnsigned(0) | 422 | # self._num_children = d.GetChildMemberWithName('size').GetValueAsUnsigned(0) | ||
404 | self._num_children = d.GetChildMemberWithName('size').GetValueAsSigned(-1) | 423 | self._num_children = d.GetChildMemberWithName('size').GetValueAsSigned(-1) | ||
405 | if self._num_children < 0: | 424 | if self._num_children < 0: | ||
406 | return | 425 | return | ||
407 | 426 | | |||
408 | if self._num_children > self._capping_size(): | 427 | if self._num_children > self._capping_size(): | ||
409 | self._num_children = self._capping_size() | 428 | self._num_children = self._capping_size() | ||
410 | 429 | | |||
411 | for idx in range(0, self._num_children): | 430 | for idx in range(0, self._num_children): | ||
▲ Show 20 Lines • Show All 89 Lines • ▼ Show 20 Line(s) | |||||
501 | 520 | | |||
502 | 521 | | |||
503 | def KeyValueSummaryProvider(valobj, internal_dict): | 522 | def KeyValueSummaryProvider(valobj, internal_dict): | ||
504 | if not valobj.IsValid(): | 523 | if not valobj.IsValid(): | ||
505 | return None | 524 | return None | ||
506 | 525 | | |||
507 | key = valobj.GetChildMemberWithName('key') | 526 | key = valobj.GetChildMemberWithName('key') | ||
508 | value = valobj.GetChildMemberWithName('value') | 527 | value = valobj.GetChildMemberWithName('value') | ||
509 | return '({}, {})'.format(key.GetSummary(), value.GetValue()) | 528 | key_summary = key.GetSummary() or key.GetValue() # show value if summary is empty or None | ||
529 | val_summary = value.GetSummary() or value.GetValue() # show value if summary is empty or None | ||||
530 | return '({}, {})'.format(key_summary, val_summary) | ||||
510 | 531 | | |||
511 | 532 | | |||
512 | class BasicMapFormatter(HiddenMemberProvider): | 533 | class BasicMapFormatter(HiddenMemberProvider): | ||
513 | """A lldb synthetic provider for QMap like types""" | 534 | """A lldb synthetic provider for QMap like types""" | ||
514 | 535 | | |||
515 | def __init__(self, valobj, internal_dict): | 536 | def __init__(self, valobj, internal_dict): | ||
516 | super(BasicMapFormatter, self).__init__(valobj, internal_dict) | 537 | super(BasicMapFormatter, self).__init__(valobj, internal_dict) | ||
517 | self_type = valobj.GetType() | 538 | self_type = valobj.GetType() | ||
518 | key_type = self_type.GetTemplateArgumentType(0) | 539 | key_type = self_type.GetTemplateArgumentType(0) | ||
519 | val_type = self_type.GetTemplateArgumentType(1) | 540 | val_type = self_type.GetTemplateArgumentType(1) | ||
520 | # the ' ' between two template arguments is significant, | 541 | # the ' ' between two template arguments is significant, | ||
521 | # otherwise FindFirstType returns None | 542 | # otherwise FindFirstType returns None | ||
522 | node_typename = 'QMapNode<{}, {}>'.format(key_type.GetName(), val_type.GetName()) | 543 | node_typename = 'QMapNode<{}, {}>'.format(key_type.GetName(), val_type.GetName()) | ||
544 | node_typename = canonicalized_type_name(node_typename) | ||||
523 | self._node_type = valobj.GetTarget().FindFirstType(node_typename) | 545 | self._node_type = valobj.GetTarget().FindFirstType(node_typename) | ||
524 | 546 | | |||
525 | e = self.valobj.GetChildMemberWithName('e') | 547 | e = self.valobj.GetChildMemberWithName('e') | ||
526 | self.isQt4 = e.IsValid() | 548 | self.isQt4 = e.IsValid() | ||
527 | if self.isQt4: | 549 | if self.isQt4: | ||
528 | self._payload_size = self._qt4_calc_payload(key_type, val_type) | 550 | self._payload_size = self._qt4_calc_payload(key_type, val_type) | ||
529 | 551 | | |||
530 | def _qt4_calc_payload(self, key_type, val_type): | 552 | def _qt4_calc_payload(self, key_type, val_type): | ||
▲ Show 20 Lines • Show All 161 Lines • ▼ Show 20 Line(s) | |||||
692 | class BasicHashFormatter(HiddenMemberProvider): | 714 | class BasicHashFormatter(HiddenMemberProvider): | ||
693 | """A lldb synthetic provider for QHash like types""" | 715 | """A lldb synthetic provider for QHash like types""" | ||
694 | 716 | | |||
695 | def __init__(self, valobj, internal_dict): | 717 | def __init__(self, valobj, internal_dict): | ||
696 | super(BasicHashFormatter, self).__init__(valobj, internal_dict) | 718 | super(BasicHashFormatter, self).__init__(valobj, internal_dict) | ||
697 | self_type = valobj.GetType() | 719 | self_type = valobj.GetType() | ||
698 | self._key_type = self_type.GetTemplateArgumentType(0) | 720 | self._key_type = self_type.GetTemplateArgumentType(0) | ||
699 | self._val_type = self_type.GetTemplateArgumentType(1) | 721 | self._val_type = self_type.GetTemplateArgumentType(1) | ||
700 | # the ' ' between two template arguments is significant, | | |||
701 | # otherwise FindFirstType returns None | | |||
702 | node_typename = 'QHashNode<{}, {}>'.format(self._key_type.GetName(), | 722 | node_typename = 'QHashNode<{}, {}>'.format(self._key_type.GetName(), | ||
703 | self._val_type.GetName()) | 723 | self._val_type.GetName()) | ||
724 | node_typename = canonicalized_type_name(node_typename) | ||||
725 | | ||||
704 | self._node_type = valobj.GetTarget().FindFirstType(node_typename) | 726 | self._node_type = valobj.GetTarget().FindFirstType(node_typename) | ||
705 | 727 | | |||
706 | class _iterator(Iterator): | 728 | class _iterator(Iterator): | ||
707 | """Hash iterator""" | 729 | """Hash iterator""" | ||
708 | def __init__(self, valobj, pnode_type): | 730 | def __init__(self, valobj, pnode_type): | ||
709 | d = valobj.GetChildMemberWithName('d') | 731 | d = valobj.GetChildMemberWithName('d') | ||
710 | self.buckets = d.GetChildMemberWithName('buckets') | 732 | self.buckets = d.GetChildMemberWithName('buckets') | ||
711 | self.null_node = valobj.GetChildMemberWithName('e') | 733 | self.null_node = valobj.GetChildMemberWithName('e') | ||
▲ Show 20 Lines • Show All 51 Lines • ▼ Show 20 Line(s) | |||||
763 | 785 | | |||
764 | def _update(self): | 786 | def _update(self): | ||
765 | self._num_children = self.valobj.GetChildMemberWithName('d').GetChildMemberWithName('size').GetValueAsSigned(-1) | 787 | self._num_children = self.valobj.GetChildMemberWithName('d').GetChildMemberWithName('size').GetValueAsSigned(-1) | ||
766 | if self._num_children < 0: | 788 | if self._num_children < 0: | ||
767 | return | 789 | return | ||
768 | 790 | | |||
769 | idx = 0 | 791 | idx = 0 | ||
770 | for pnode in self._iterator(self.valobj, self._node_type.GetPointerType()): | 792 | for pnode in self._iterator(self.valobj, self._node_type.GetPointerType()): | ||
793 | if idx >= self._num_children: | ||||
794 | self._members = [] | ||||
795 | self._num_children = 0 | ||||
796 | break | ||||
771 | # dereference node and change to a user friendly name | 797 | # dereference node and change to a user friendly name | ||
772 | name = '[{}]'.format(idx) | 798 | name = '[{}]'.format(idx) | ||
773 | idx += 1 | 799 | idx += 1 | ||
774 | var = self.valobj.CreateValueFromData(name, pnode.GetPointeeData(), | 800 | var = self.valobj.CreateValueFromData(name, pnode.GetPointeeData(), | ||
775 | self._node_type) | 801 | self._node_type) | ||
776 | self._addChild(var) | 802 | self._addChild(var) | ||
777 | if idx != self._num_children: | 803 | if idx != self._num_children: | ||
778 | self._members = [] | 804 | self._members = [] | ||
Show All 13 Lines | 815 | class QMultiHashFormatter(BasicHashFormatter): | |||
792 | def __init__(self, valobj, internal_dict): | 818 | def __init__(self, valobj, internal_dict): | ||
793 | super(QMultiHashFormatter, self).__init__(valobj.GetChildAtIndex(0), internal_dict) | 819 | super(QMultiHashFormatter, self).__init__(valobj.GetChildAtIndex(0), internal_dict) | ||
794 | self.actualobj = valobj | 820 | self.actualobj = valobj | ||
795 | 821 | | |||
796 | def update(self): | 822 | def update(self): | ||
797 | self.valobj = self.actualobj.GetChildAtIndex(0) | 823 | self.valobj = self.actualobj.GetChildAtIndex(0) | ||
798 | super(QMultiHashFormatter, self).update() | 824 | super(QMultiHashFormatter, self).update() | ||
799 | 825 | | |||
826 | | ||||
800 | class QSetFormatter(HiddenMemberProvider): | 827 | class QSetFormatter(HiddenMemberProvider): | ||
801 | """lldb synthetic provider for QSet""" | 828 | """lldb synthetic provider for QSet""" | ||
802 | 829 | | |||
803 | def __init__(self, valobj, internal_dict): | 830 | def __init__(self, valobj, internal_dict): | ||
804 | super(QSetFormatter, self).__init__(valobj, internal_dict) | 831 | super(QSetFormatter, self).__init__(valobj, internal_dict) | ||
805 | self._hash_formatter = QHashFormatter(valobj.GetChildMemberWithName('q_hash'), | 832 | self._hash_formatter = QHashFormatter(valobj.GetChildMemberWithName('q_hash'), | ||
806 | internal_dict) | 833 | internal_dict) | ||
807 | 834 | | |||
808 | def num_children(self): | 835 | def num_children(self): | ||
809 | return self._num_children | 836 | return self._num_children | ||
810 | pass | | |||
811 | 837 | | |||
812 | def _update(self): | 838 | def _update(self): | ||
813 | self._hash_formatter.valobj = self.valobj.GetChildMemberWithName('q_hash') | 839 | self._hash_formatter.valobj = self.valobj.GetChildMemberWithName('q_hash') | ||
814 | self._hash_formatter.update() | 840 | self._hash_formatter.update() | ||
815 | 841 | | |||
816 | self._num_children = 0 | 842 | self._num_children = 0 | ||
817 | for node in self._hash_formatter._members: | 843 | for node in self._hash_formatter._members: | ||
818 | keydata = node.GetChildMemberWithName('key').GetData() | 844 | keydata = node.GetChildMemberWithName('key').GetData() | ||
Show All 16 Lines | 851 | class QDateFormatter(HiddenMemberProvider): | |||
835 | @staticmethod | 861 | @staticmethod | ||
836 | def parse(julianDay): | 862 | def parse(julianDay): | ||
837 | """Copied from Qt srources""" | 863 | """Copied from Qt srources""" | ||
838 | if julianDay == 0: | 864 | if julianDay == 0: | ||
839 | return None | 865 | return None | ||
840 | if julianDay >= 2299161: | 866 | if julianDay >= 2299161: | ||
841 | # Gregorian calendar starting from October 15, 1582 | 867 | # Gregorian calendar starting from October 15, 1582 | ||
842 | # This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern | 868 | # This algorithm is from Henry F. Fliegel and Thomas C. Van Flandern | ||
843 | ell = julianDay + 68569; | 869 | ell = julianDay + 68569 | ||
844 | n = (4 * ell) / 146097; | 870 | n = (4 * ell) / 146097 | ||
845 | ell = ell - (146097 * n + 3) / 4; | 871 | ell = ell - (146097 * n + 3) / 4 | ||
846 | i = (4000 * (ell + 1)) / 1461001; | 872 | i = (4000 * (ell + 1)) / 1461001 | ||
847 | ell = ell - (1461 * i) / 4 + 31; | 873 | ell = ell - (1461 * i) / 4 + 31 | ||
848 | j = (80 * ell) / 2447; | 874 | j = (80 * ell) / 2447 | ||
849 | d = ell - (2447 * j) / 80; | 875 | d = ell - (2447 * j) / 80 | ||
850 | ell = j / 11; | 876 | ell = j / 11 | ||
851 | m = j + 2 - (12 * ell); | 877 | m = j + 2 - (12 * ell) | ||
852 | y = 100 * (n - 49) + i + ell; | 878 | y = 100 * (n - 49) + i + ell | ||
853 | else: | 879 | else: | ||
854 | # Julian calendar until October 4, 1582 | 880 | # Julian calendar until October 4, 1582 | ||
855 | # Algorithm from Frequently Asked Questions about Calendars by Claus Toendering | 881 | # Algorithm from Frequently Asked Questions about Calendars by Claus Toendering | ||
856 | julianDay += 32082; | 882 | julianDay += 32082 | ||
857 | dd = (4 * julianDay + 3) / 1461; | 883 | dd = (4 * julianDay + 3) / 1461 | ||
858 | ee = julianDay - (1461 * dd) / 4; | 884 | ee = julianDay - (1461 * dd) / 4 | ||
859 | mm = ((5 * ee) + 2) / 153; | 885 | mm = ((5 * ee) + 2) / 153 | ||
860 | d = ee - (153 * mm + 2) / 5 + 1; | 886 | d = ee - (153 * mm + 2) / 5 + 1 | ||
861 | m = mm + 3 - 12 * (mm / 10); | 887 | m = mm + 3 - 12 * (mm / 10) | ||
862 | y = dd - 4800 + (mm / 10); | 888 | y = dd - 4800 + (mm / 10) | ||
863 | if y <= 0: | 889 | if y <= 0: | ||
864 | return None | 890 | return None | ||
865 | return dt.date(y, m, d) | 891 | return dt.date(y, m, d) | ||
866 | 892 | | |||
867 | def _update(self): | 893 | def _update(self): | ||
868 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | 894 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | ||
869 | ## toString | 895 | # # toString | ||
870 | #res = invoke(self.valobj, 'toString', '0') | 896 | # res = invoke(self.valobj, 'toString', '0') | ||
871 | #self._addChild(rename('toString', res)) | 897 | # self._addChild(rename('toString', res)) | ||
872 | 898 | | |||
873 | # jd | 899 | # jd | ||
874 | julianDay = self.valobj.GetChildMemberWithName('jd') | 900 | julianDay = self.valobj.GetChildMemberWithName('jd') | ||
875 | self._addChild(julianDay) | 901 | self._addChild(julianDay) | ||
876 | 902 | | |||
877 | | ||||
878 | pydate = self.parse(julianDay.GetValueAsUnsigned(0)) | 903 | pydate = self.parse(julianDay.GetValueAsUnsigned(0)) | ||
879 | if pydate is None: | 904 | if pydate is None: | ||
880 | return | 905 | return | ||
881 | # (ISO) | 906 | # (ISO) | ||
882 | iso_str = pydate.isoformat().decode().__repr__().lstrip("u'").rstrip("'") | 907 | iso_str = pydate.isoformat().decode().__repr__()[2:-1] | ||
883 | self._addChild(('(ISO)', quote(iso_str))) | 908 | self._addChild(('(ISO)', quote(iso_str))) | ||
884 | 909 | | |||
885 | # (Locale) | 910 | # (Locale) | ||
886 | locale_encoding = [locale.getlocale()[1]] | 911 | locale_encoding = [locale.getlocale()[1]] | ||
887 | if locale_encoding[0] is None: | 912 | if locale_encoding[0] is None: | ||
888 | locale_encoding = [] | 913 | locale_encoding = [] | ||
889 | locale_str = pydate.strftime('%x').decode(*locale_encoding).__repr__().lstrip("u'").rstrip("'") | 914 | locale_str = pydate.strftime('%x').decode(*locale_encoding).__repr__()[2:-1] | ||
890 | self._addChild(('(Locale)', quote(locale_str))) | 915 | self._addChild(('(Locale)', quote(locale_str))) | ||
891 | 916 | | |||
892 | 917 | | |||
893 | def QDateSummaryProvider(valobj, internal_dict): | 918 | def QDateSummaryProvider(valobj, internal_dict): | ||
894 | if valobj.IsValid(): | 919 | if valobj.IsValid(): | ||
895 | content = valobj.GetChildMemberWithName('(Locale)') | 920 | content = valobj.GetChildMemberWithName('(Locale)') | ||
896 | if content.IsValid(): | 921 | if content.IsValid(): | ||
897 | return content.GetSummary() | 922 | summary = content.GetSummary() | ||
898 | else: | 923 | if summary is not None: | ||
899 | # No synthetic provider installed, get the content by ourselves | 924 | return summary | ||
900 | pydate = QDateFormatter.parse(valobj.GetChildMemberWithName('jd').GetValueAsUnsigned(0)) | 925 | # No synthetic provider installed, get the content by ourselves | ||
901 | if pydate is not None: | 926 | pydate = QDateFormatter.parse(valobj.GetChildMemberWithName('jd').GetValueAsUnsigned(0)) | ||
902 | content = pydate.isoformat().decode().__repr__().lstrip("u'").rstrip("'") | 927 | if pydate is not None: | ||
903 | return quote(content) | 928 | return pydate.isoformat().decode().__repr__()[2:-1] | ||
904 | return '<Invalid>' | 929 | return '<Invalid>' | ||
905 | 930 | | |||
906 | 931 | | |||
907 | class QTimeFormatter(HiddenMemberProvider): | 932 | class QTimeFormatter(HiddenMemberProvider): | ||
908 | """lldb synthetic provider for QTime""" | 933 | """lldb synthetic provider for QTime""" | ||
909 | def __init__(self, valobj, internal_dict): | 934 | def __init__(self, valobj, internal_dict): | ||
910 | super(QTimeFormatter, self).__init__(valobj, internal_dict) | 935 | super(QTimeFormatter, self).__init__(valobj, internal_dict) | ||
911 | self._add_original = False | 936 | self._add_original = False | ||
912 | 937 | | |||
913 | def has_children(self): | 938 | def has_children(self): | ||
914 | return True | 939 | return True | ||
915 | 940 | | |||
916 | @staticmethod | 941 | @staticmethod | ||
917 | def parse(ds): | 942 | def parse(ds): | ||
918 | if ds < 0: | 943 | if ds < 0: | ||
919 | return None | 944 | return None | ||
920 | MSECS_PER_HOUR = 3600000 | 945 | MSECS_PER_HOUR = 3600000 | ||
921 | SECS_PER_MIN = 60 | 946 | SECS_PER_MIN = 60 | ||
922 | MSECS_PER_MIN = 60000 | 947 | MSECS_PER_MIN = 60000 | ||
923 | 948 | | |||
924 | hour = ds / MSECS_PER_HOUR | 949 | hour = ds / MSECS_PER_HOUR | ||
925 | minute = (ds % MSECS_PER_HOUR) / MSECS_PER_MIN | 950 | minute = (ds % MSECS_PER_HOUR) / MSECS_PER_MIN | ||
926 | second = (ds / 1000)%SECS_PER_MIN | 951 | second = (ds / 1000) % SECS_PER_MIN | ||
927 | msec = ds % 1000 | 952 | msec = ds % 1000 | ||
928 | return dt.time(hour, minute, second, msec) | 953 | return dt.time(hour, minute, second, msec) | ||
929 | 954 | | |||
930 | def _update(self): | 955 | def _update(self): | ||
931 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | 956 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | ||
932 | ## toString | 957 | # # toString | ||
933 | #res = invoke(self.valobj, 'toString', '0') | 958 | # res = invoke(self.valobj, 'toString', '0') | ||
934 | #self._addChild(rename('toString', res)) | 959 | # self._addChild(rename('toString', res)) | ||
935 | 960 | | |||
936 | # mds | 961 | # mds | ||
937 | mds = self.valobj.GetChildMemberWithName('mds') | 962 | mds = self.valobj.GetChildMemberWithName('mds') | ||
938 | self._addChild(mds) | 963 | self._addChild(mds) | ||
939 | 964 | | |||
940 | pytime = self.parse(mds.GetValueAsUnsigned(0)) | 965 | pytime = self.parse(mds.GetValueAsUnsigned(0)) | ||
941 | if pytime is None: | 966 | if pytime is None: | ||
942 | return | 967 | return | ||
943 | # (ISO) | 968 | # (ISO) | ||
944 | iso_str = pytime.isoformat().decode().__repr__().lstrip("u'").rstrip("'") | 969 | iso_str = pytime.isoformat().decode().__repr__()[2:-1] | ||
945 | self._addChild(('(ISO)', quote(iso_str))) | 970 | self._addChild(('(ISO)', quote(iso_str))) | ||
946 | 971 | | |||
947 | # (Locale) | 972 | # (Locale) | ||
948 | locale_encoding = [locale.getlocale()[1]] | 973 | locale_encoding = [locale.getlocale()[1]] | ||
949 | if locale_encoding[0] is None: | 974 | if locale_encoding[0] is None: | ||
950 | locale_encoding = [] | 975 | locale_encoding = [] | ||
951 | locale_str = pytime.strftime('%X').decode(*locale_encoding).__repr__().lstrip("u'").rstrip("'") | 976 | locale_str = pytime.strftime('%X').decode(*locale_encoding).__repr__()[2:-1] | ||
952 | self._addChild(('(Locale)', quote(locale_str))) | 977 | self._addChild(('(Locale)', quote(locale_str))) | ||
953 | 978 | | |||
954 | 979 | | |||
955 | def QTimeSummaryProvider(valobj, internal_dict): | 980 | def QTimeSummaryProvider(valobj, internal_dict): | ||
956 | if valobj.IsValid(): | 981 | if valobj.IsValid(): | ||
957 | content = valobj.GetChildMemberWithName('(Locale)') | 982 | content = valobj.GetChildMemberWithName('(Locale)') | ||
958 | if content.IsValid(): | 983 | if content.IsValid(): | ||
959 | return content.GetSummary() | 984 | summary = content.GetSummary() | ||
960 | else: | 985 | if summary is not None: | ||
961 | # No synthetic provider installed, get the content by ourselves | 986 | return summary | ||
962 | pytime = QTimeFormatter.parse(valobj.GetChildMemberWithName('mds').GetValueAsUnsigned(0)) | 987 | # No synthetic provider installed, get the content by ourselves | ||
963 | if pytime is not None: | 988 | pytime = QTimeFormatter.parse(valobj.GetChildMemberWithName('mds').GetValueAsUnsigned(0)) | ||
964 | content = pytime.isoformat().decode().__repr__().lstrip("u'").rstrip("'") | 989 | if pytime is not None: | ||
965 | return quote(content) | 990 | return pytime.isoformat().decode().__repr__()[2:-1] | ||
966 | return None | 991 | return None | ||
967 | 992 | | |||
968 | 993 | | |||
969 | class QDateTimeFormatter(HiddenMemberProvider): | 994 | class QDateTimeFormatter(HiddenMemberProvider): | ||
970 | """lldb synthetic provider for QTime""" | 995 | """lldb synthetic provider for QTime""" | ||
971 | def __init__(self, valobj, internal_dict): | 996 | def __init__(self, valobj, internal_dict): | ||
972 | super(QDateTimeFormatter, self).__init__(valobj, internal_dict) | 997 | super(QDateTimeFormatter, self).__init__(valobj, internal_dict) | ||
973 | 998 | | |||
974 | def has_children(self): | 999 | def has_children(self): | ||
975 | return True | 1000 | return True | ||
976 | 1001 | | |||
977 | @staticmethod | 1002 | @staticmethod | ||
978 | def parse(time_t, utc=False): | 1003 | def parse(time_t, utc=False): | ||
979 | if time_t is None: | 1004 | if time_t is None: | ||
980 | return None | 1005 | return None | ||
981 | totuple = time.gmtime if utc else time.localtime | 1006 | totuple = time.gmtime if utc else time.localtime | ||
Show All 19 Lines | 1017 | def _update(self): | |||
1001 | # toTime_t | 1026 | # toTime_t | ||
1002 | self._addChild(rename('toTime_t', time_t)) | 1027 | self._addChild(rename('toTime_t', time_t)) | ||
1003 | 1028 | | |||
1004 | # time tuple in local time and utc time | 1029 | # time tuple in local time and utc time | ||
1005 | local_tt = self.parse(time_t.GetValueAsUnsigned(0)) | 1030 | local_tt = self.parse(time_t.GetValueAsUnsigned(0)) | ||
1006 | utc_tt = self.parse(time_t.GetValueAsUnsigned(0), utc=True) | 1031 | utc_tt = self.parse(time_t.GetValueAsUnsigned(0), utc=True) | ||
1007 | 1032 | | |||
1008 | # (ISO) | 1033 | # (ISO) | ||
1009 | formatted = time.strftime('%Y-%m-%d %H:%M:%S', utc_tt).decode(*locale_encoding).__repr__().lstrip("u'").rstrip("'") | 1034 | formatted = time.strftime('%Y-%m-%d %H:%M:%S', utc_tt).decode(*locale_encoding).__repr__() | ||
1035 | formatted = formatted[2:-1] | ||||
1010 | self._addChild(('(ISO)', quote(formatted))) | 1036 | self._addChild(('(ISO)', quote(formatted))) | ||
1011 | 1037 | | |||
1012 | def locale_fmt(name, tt): | 1038 | def locale_fmt(name, tt): | ||
1013 | formatted = time.strftime('%c', tt).decode(*locale_encoding).__repr__().lstrip("u'").rstrip("'") | 1039 | formatted = time.strftime('%c', tt).decode(*locale_encoding).__repr__()[2:-1] | ||
1014 | self._addChild((name, quote(formatted))) | 1040 | self._addChild((name, quote(formatted))) | ||
1015 | 1041 | | |||
1016 | # (Locale) | 1042 | # (Locale) | ||
1017 | locale_fmt('(Locale)', local_tt) | 1043 | locale_fmt('(Locale)', local_tt) | ||
1018 | 1044 | | |||
1019 | # (UTC) | 1045 | # (UTC) | ||
1020 | locale_fmt('(UTC)', utc_tt) | 1046 | locale_fmt('(UTC)', utc_tt) | ||
1021 | 1047 | | |||
1022 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | 1048 | # FIXME: Calling functions returns incorrect SBValue for complex type in lldb | ||
1023 | ## toString | 1049 | # # toString | ||
1024 | #res = invoke(self.valobj, 'toString', '0') | 1050 | # res = invoke(self.valobj, 'toString', '0') | ||
1025 | #print 'tostring', res | 1051 | # print 'tostring', res | ||
1026 | #self._addChild(rename('toString', res)) | 1052 | # self._addChild(rename('toString', res)) | ||
1027 | 1053 | | |||
1028 | ## toLocalTime | 1054 | # # toLocalTime | ||
1029 | #res = invoke(self.valobj, 'toTimeSpec', '0') # Qt::LocalTime == 0 | 1055 | # res = invoke(self.valobj, 'toTimeSpec', '0') # Qt::LocalTime == 0 | ||
1030 | #print 'tolocaltime', res | 1056 | # print 'tolocaltime', res | ||
1031 | #self._addChild(rename('toLocalTime', res)) | 1057 | # self._addChild(rename('toLocalTime', res)) | ||
1032 | 1058 | | |||
1033 | 1059 | | |||
1034 | def QDateTimeSummaryProvider(valobj, internal_dict): | 1060 | def QDateTimeSummaryProvider(valobj, internal_dict): | ||
1035 | if valobj.IsValid(): | 1061 | if valobj.IsValid(): | ||
1036 | content = valobj.GetChildMemberWithName('(Locale)') | 1062 | content = valobj.GetChildMemberWithName('(Locale)') | ||
1037 | if content.IsValid(): | 1063 | if content.IsValid(): | ||
1038 | return content.GetSummary() | 1064 | summary = content.GetSummary() | ||
1039 | else: | 1065 | if summary is not None: | ||
1040 | # No synthetic provider installed, get the content by ourselves | 1066 | return summary | ||
1041 | pytime = QDateTimeFormatter.parse(QDateTimeFormatter.getdata(valobj).GetValueAsUnsigned(0)) | 1067 | # No synthetic provider installed, get the content by ourselves | ||
1042 | if pytime is not None: | 1068 | pytime = QDateTimeFormatter.parse(QDateTimeFormatter.getdata(valobj).GetValueAsUnsigned(0)) | ||
1043 | #content = pytime.isoformat().decode().__repr__().lstrip("u'").rstrip("'") | 1069 | if pytime is not None: | ||
1044 | #return quote(content) | 1070 | return pytime.isoformat().decode().__repr__()[2:-1] | ||
1045 | pass | | |||
1046 | return None | 1071 | return None | ||
1047 | 1072 | | |||
1048 | 1073 | | |||
1049 | class QUrlFormatter(HiddenMemberProvider): | 1074 | class QUrlFormatter(HiddenMemberProvider): | ||
1050 | """docstring for QUrlFormatter""" | 1075 | """docstring for QUrlFormatter""" | ||
1051 | def __init__(self, valobj, internal_dict): | 1076 | def __init__(self, valobj, internal_dict): | ||
1052 | super(QUrlFormatter, self).__init__(valobj, internal_dict) | 1077 | super(QUrlFormatter, self).__init__(valobj, internal_dict) | ||
1053 | 1078 | | |||
1054 | target = valobj.GetTarget() | 1079 | target = valobj.GetTarget() | ||
1055 | self._int_type = target.GetBasicType(lldb.eBasicTypeInt) | 1080 | self._int_type = target.GetBasicType(lldb.eBasicTypeInt) | ||
1056 | self._pvoid_type = target.GetBasicType(lldb.eBasicTypeVoid).GetPointerType() | 1081 | self._pvoid_type = target.GetBasicType(lldb.eBasicTypeVoid).GetPointerType() | ||
1057 | self._qstring_type = target.FindFirstType('QString') | 1082 | self._qstring_type = target.FindFirstType('QString') | ||
1058 | self._qbytearray_type = target.FindFirstType('QByteArray') | 1083 | self._qbytearray_type = target.FindFirstType('QByteArray') | ||
1059 | 1084 | | |||
1060 | def parseQt5Data(self, dataobj): | 1085 | def parseQt5Data(self, dataobj): | ||
1061 | def constructEncoded(port, scheme, username, password, host, path, query, fragment): | 1086 | def constructEncoded(port, scheme, username, password, host, path, query, fragment): | ||
1062 | netloc = '' | 1087 | netloc = '' | ||
1063 | host_str = printableQString(host)[0] | 1088 | host_str = printableQString(host)[0] | ||
1064 | if host_str is not None: | 1089 | if host_str is not None: | ||
1065 | username_str = printableQString(username)[0] | 1090 | username_str = printableQString(username)[0] | ||
1066 | if username_str is not None: | 1091 | if username_str is not None: | ||
1067 | netloc += username_str | 1092 | netloc += username_str | ||
1068 | password_str = printableQString(password)[0] | 1093 | password_str = printableQString(password)[0] | ||
1069 | if password_str is not None: | 1094 | if password_str is not None: | ||
1070 | netloc += ':' + password_str | 1095 | netloc += ':' + password_str | ||
1071 | netloc += "@" + host_str | 1096 | netloc += "@" | ||
1097 | netloc += host_str | ||||
1072 | port_num = port.GetValueAsSigned(-1) | 1098 | port_num = port.GetValueAsSigned(-1) | ||
1073 | if port_num != -1: | 1099 | if port_num != -1: | ||
1074 | netloc += ":" + str(port_num) | 1100 | netloc += ":" + str(port_num) | ||
1075 | 1101 | | |||
1076 | url = urlunsplit((printableQString(scheme)[0], | 1102 | url = urlunsplit((printableQString(scheme)[0], | ||
1077 | netloc, | 1103 | netloc, | ||
1078 | printableQString(path)[0], | 1104 | printableQString(path)[0], | ||
1079 | printableQString(query)[0], | 1105 | printableQString(query)[0], | ||
▲ Show 20 Lines • Show All 84 Lines • ▼ Show 20 Line(s) | 1155 | def parseQt4Data(self, dataobj): | |||
1164 | addr += self._qbytearray_type.GetByteSize() | 1190 | addr += self._qbytearray_type.GetByteSize() | ||
1165 | # handle QByteArray encodedOriginal | 1191 | # handle QByteArray encodedOriginal | ||
1166 | encoded = dataobj.CreateValueFromAddress('(encoded)', addr, self._qbytearray_type) | 1192 | encoded = dataobj.CreateValueFromAddress('(encoded)', addr, self._qbytearray_type) | ||
1167 | 1193 | | |||
1168 | if not encoded.IsValid(): | 1194 | if not encoded.IsValid(): | ||
1169 | return (None,) * 9 | 1195 | return (None,) * 9 | ||
1170 | return parseComponents(encoded) | 1196 | return parseComponents(encoded) | ||
1171 | 1197 | | |||
1172 | def _update(self): | 1198 | def try_parse(self): | ||
1173 | dataobj = self.valobj.GetChildMemberWithName('d') | 1199 | dataobj = self.valobj.GetChildMemberWithName('d') | ||
1174 | # first try to access Qt4 data | 1200 | # first try to access Qt4 data | ||
1175 | (encoded, port, scheme, | 1201 | (encoded, port, scheme, | ||
1176 | username, password, host, path, query, fragment) = self.parseQt4Data(dataobj) | 1202 | username, password, host, path, query, fragment) = self.parseQt4Data(dataobj) | ||
1177 | if encoded is not None: | 1203 | if encoded is not None: | ||
1178 | self._addChild(port) | 1204 | return (encoded, port, scheme, username, password, host, path, query, fragment) | ||
1179 | self._addChild(scheme) | | |||
1180 | self._addChild(username) | | |||
1181 | self._addChild(password) | | |||
1182 | self._addChild(host) | | |||
1183 | self._addChild(path) | | |||
1184 | self._addChild(query) | | |||
1185 | self._addChild(fragment) | | |||
1186 | self._addChild(encoded, hidden=True) | | |||
1187 | return | | |||
1188 | 1205 | | |||
1189 | # if this fails, maybe we deal with Qt5 | 1206 | # if this fails, maybe we deal with Qt5 | ||
1190 | (encoded, port, scheme, | 1207 | (encoded, port, scheme, | ||
1191 | username, password, host, | 1208 | username, password, host, | ||
1192 | path, query, fragment) = self.parseQt5Data(dataobj) | 1209 | path, query, fragment) = self.parseQt5Data(dataobj) | ||
1193 | if encoded is not None: | 1210 | if encoded is not None: | ||
1194 | self._addChild(port) | 1211 | return (encoded, port, scheme, username, password, host, path, query, fragment) | ||
1195 | self._addChild(scheme) | | |||
1196 | self._addChild(username) | | |||
1197 | self._addChild(password) | | |||
1198 | self._addChild(host) | | |||
1199 | self._addChild(path) | | |||
1200 | self._addChild(query) | | |||
1201 | self._addChild(fragment) | | |||
1202 | self._addChild(encoded, hidden=True) | | |||
1203 | return | | |||
1204 | 1212 | | |||
1205 | # if above fails, try to print directly. | 1213 | # if above fails, try to print directly. | ||
1206 | # But this might not work, and could lead to issues | 1214 | # But this might not work, and could lead to issues | ||
1207 | # (see http://sourceware-org.1504.n7.nabble.com/help-Calling-malloc-from-a-Python-pretty-printer-td284031.html) | 1215 | # (see http://sourceware-org.1504.n7.nabble.com/help-Calling-malloc-from-a-Python-pretty-printer-td284031.html) | ||
1208 | res = invoke(self.valobj, 'toString', '(QUrl::FormattingOptions)0') # QUrl::PrettyDecoded == 0 | 1216 | res = invoke(self.valobj, 'toString', '(QUrl::FormattingOptions)0') # QUrl::PrettyDecoded == 0 | ||
1209 | if res.IsValid(): | 1217 | if res.IsValid(): | ||
1210 | self._addChild(rename('(encoded)', res)) | 1218 | return rename('(encoded)', res), None, None, None, None, None, None, None, None | ||
1219 | return None, None, None, None, None, None, None, None, None | ||||
1211 | 1220 | | |||
1221 | def _update(self): | ||||
1222 | (encoded, port, scheme, username, | ||||
1223 | password, host, path, query, fragment) = self.try_parse() | ||||
1224 | if encoded is not None: | ||||
1225 | self._addChild(encoded, hidden=True) | ||||
1226 | if port is not None: | ||||
1227 | self._addChild(port) | ||||
1228 | self._addChild(scheme) | ||||
1229 | self._addChild(username) | ||||
1230 | self._addChild(password) | ||||
1231 | self._addChild(host) | ||||
1232 | self._addChild(path) | ||||
1233 | self._addChild(query) | ||||
1234 | self._addChild(fragment) | ||||
1235 | return | ||||
1212 | # if everything fails, we have no choice but to show the original member | 1236 | # if everything fails, we have no choice but to show the original member | ||
1213 | self._add_original = False | 1237 | self._add_original = False | ||
1214 | self._addChild(self.valobj.GetChildMemberWithName('d')) | 1238 | self._addChild(self.valobj.GetChildMemberWithName('d')) | ||
1215 | 1239 | | |||
1216 | 1240 | | |||
1241 | def QUrlSummaryProvider(valobj, internal_dict): | ||||
1242 | if valobj.IsValid(): | ||||
1243 | content = valobj.GetChildMemberWithName('(encoded)') | ||||
1244 | if content.IsValid(): | ||||
1245 | summary = content.GetSummary() | ||||
1246 | if summary is not None: | ||||
1247 | return summary | ||||
1248 | # No synthetic provider installed, get the content by ourselves | ||||
1249 | encoded = QUrlFormatter(valobj, internal_dict).try_parse()[0][1] | ||||
1250 | if encoded is not None: | ||||
1251 | return encoded | ||||
1252 | return None | ||||
1253 | | ||||
1254 | | ||||
1217 | class QUuidFormatter(HiddenMemberProvider): | 1255 | class QUuidFormatter(HiddenMemberProvider): | ||
1218 | """A lldb synthetic provider for QUuid""" | 1256 | """A lldb synthetic provider for QUuid""" | ||
1219 | def __init__(self, valobj, internal_dict): | 1257 | def __init__(self, valobj, internal_dict): | ||
1220 | super(QUuidFormatter, self).__init__(valobj, internal_dict) | 1258 | super(QUuidFormatter, self).__init__(valobj, internal_dict) | ||
1221 | 1259 | | |||
1222 | def has_children(self): | 1260 | def has_children(self): | ||
1223 | return False | 1261 | return False | ||
1224 | 1262 | | |||
1225 | 1263 | | |||
1226 | def QUuidSummaryProvider(valobj, internal_dict): | 1264 | def QUuidSummaryProvider(valobj, internal_dict): | ||
1227 | data = [valobj.GetChildMemberWithName(name).GetValueAsUnsigned(0) | 1265 | data = [valobj.GetChildMemberWithName(name).GetValueAsUnsigned(0) | ||
1228 | for name in ['data1', 'data2', 'data3']] | 1266 | for name in ['data1', 'data2', 'data3']] | ||
1229 | data += [val.GetValueAsUnsigned(0) for val in valobj.GetChildMemberWithName('data4')] | 1267 | data += [val.GetValueAsUnsigned(0) for val in valobj.GetChildMemberWithName('data4')] | ||
1230 | 1268 | | |||
1231 | return 'QUuid({{{:02x}-{:02x}-{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}}})'.format(*data) | 1269 | return 'QUuid({{{:02x}-{:02x}-{:02x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}}})'.format(*data) |