1"""
2LLDB AppKit formatters
3
4Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
5See https://llvm.org/LICENSE.txt for license information.
6SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7"""
8# example summary provider for NSNotification
9# the real summary is now C++ code built into LLDB
10import lldb.runtime.objc.objc_runtime
11import lldb.formatters.metrics
12import CFString
13import lldb
14import lldb.formatters.Logger
15
16statistics = lldb.formatters.metrics.Metrics()
17statistics.add_metric('invalid_isa')
18statistics.add_metric('invalid_pointer')
19statistics.add_metric('unknown_class')
20statistics.add_metric('code_notrun')
21
22
23class NSConcreteNotification_SummaryProvider:
24
25    def adjust_for_architecture(self):
26        pass
27
28    def __init__(self, valobj, params):
29        logger = lldb.formatters.Logger.Logger()
30        self.valobj = valobj
31        self.sys_params = params
32        if not (self.sys_params.types_cache.id):
33            self.sys_params.types_cache.id = self.valobj.GetType(
34            ).GetBasicType(lldb.eBasicTypeObjCID)
35        self.update()
36
37    def update(self):
38        logger = lldb.formatters.Logger.Logger()
39        self.adjust_for_architecture()
40
41    # skip the ISA and go to the name pointer
42    def offset(self):
43        logger = lldb.formatters.Logger.Logger()
44        return self.sys_params.pointer_size
45
46    def name(self):
47        logger = lldb.formatters.Logger.Logger()
48        string_ptr = self.valobj.CreateChildAtOffset(
49            "name", self.offset(), self.sys_params.types_cache.id)
50        return CFString.CFString_SummaryProvider(string_ptr, None)
51
52
53class NSNotificationUnknown_SummaryProvider:
54
55    def adjust_for_architecture(self):
56        pass
57
58    def __init__(self, valobj, params):
59        logger = lldb.formatters.Logger.Logger()
60        self.valobj = valobj
61        self.sys_params = params
62        self.update()
63
64    def update(self):
65        logger = lldb.formatters.Logger.Logger()
66        self.adjust_for_architecture()
67
68    def name(self):
69        logger = lldb.formatters.Logger.Logger()
70        stream = lldb.SBStream()
71        self.valobj.GetExpressionPath(stream)
72        name_vo = self.valobj.CreateValueFromExpression(
73            "name", "(NSString*)[" + stream.GetData() + " name]")
74        if name_vo.IsValid():
75            return CFString.CFString_SummaryProvider(name_vo, None)
76        return '<variable is not NSNotification>'
77
78
79def GetSummary_Impl(valobj):
80    logger = lldb.formatters.Logger.Logger()
81    global statistics
82    class_data, wrapper = lldb.runtime.objc.objc_runtime.Utilities.prepare_class_detection(
83        valobj, statistics)
84    if wrapper:
85        return wrapper
86
87    name_string = class_data.class_name()
88    logger >> "class name is: " + str(name_string)
89
90    if name_string == 'NSConcreteNotification':
91        wrapper = NSConcreteNotification_SummaryProvider(
92            valobj, class_data.sys_params)
93        statistics.metric_hit('code_notrun', valobj)
94    else:
95        wrapper = NSNotificationUnknown_SummaryProvider(
96            valobj, class_data.sys_params)
97        statistics.metric_hit(
98            'unknown_class',
99            valobj.GetName() +
100            " seen as " +
101            name_string)
102    return wrapper
103
104
105def NSNotification_SummaryProvider(valobj, dict):
106    logger = lldb.formatters.Logger.Logger()
107    provider = GetSummary_Impl(valobj)
108    if provider is not None:
109        if isinstance(
110                provider,
111                lldb.runtime.objc.objc_runtime.SpecialSituation_Description):
112            return provider.message()
113        try:
114            summary = provider.name()
115        except:
116            summary = None
117        logger >> "got summary " + str(summary)
118        if summary is None:
119            summary = '<variable is not NSNotification>'
120        return str(summary)
121    return 'Summary Unavailable'
122
123
124def __lldb_init_module(debugger, dict):
125    debugger.HandleCommand(
126        "type summary add -F NSNotification.NSNotification_SummaryProvider NSNotification")
127