xref: /llvm-project/lldb/examples/synthetic/recognizer_function/example.py (revision 2238dcc39358353cac21df75c3c3286ab20b8f53)
1# Formatters for classes that derive from Message.
2#
3# Usage:
4#   command script import ./example.py
5#   type summary add --expand --recognizer-function --python-function example.message_summary example.is_message_type
6#   type synth add --recognizer-function --python-class example.MessageChildProvider example.is_message_type
7
8import sys
9
10
11def is_message_type(t, internal_dict):
12    for base in t.get_bases_array():
13        if base.GetName() == "Message":
14            return True
15    return False
16
17
18def message_summary(value, internal_dict):
19    # Could have used a summary string as well. All the work is done by the child
20    # provider.
21    return "Message"
22
23
24class MessageChildProvider:
25    def __init__(self, value, internal_dict):
26        self.value = value
27        self.synthetic_children = self._analyze_children(value)
28
29    def has_children(self):
30        return self.num_children() > 0
31
32    def num_children(self):
33        return len(self.synthetic_children)
34
35    def get_child_index(self, name):
36        for index, child in enumerate(self.synthetic_children):
37            if child.GetName() == name:
38                return index
39        return None
40
41    def get_child_at_index(self, index):
42        return self.synthetic_children[index]
43
44    def _rename_sbvalue(self, value):
45        # We want to display the field with its original name without a trailing
46        # underscore. So we create a new SBValue with the same type and address but
47        # a different name.
48        name = value.GetName()
49        assert name.endswith("_")
50        new_name = name[:-1]
51        return value.CreateValueFromAddress(
52            new_name, value.GetLoadAddress(), value.GetType()
53        )
54
55    def _analyze_children(self, value):
56        result = []
57        for i in range(value.GetNumChildren()):
58            child = value.GetChildAtIndex(i)
59            child_name = child.GetName()
60            if child_name.startswith("_"):
61                continue  # Internal field, skip
62            # Normal field. Check presence bit.
63            presence_bit = value.GetChildMemberWithName("_has_" + child_name)
64            if presence_bit.GetValueAsUnsigned() != 0:
65                result.append(self._rename_sbvalue(child))
66        return result
67