blob: e9aca9d651a2a18b61899b3af829584964e4b0b6 [file] [log] [blame]
Enrico Granata3f1052b2012-03-13 21:52:00 +00001"""
2LLDB AppKit formatters
3
4part of The LLVM Compiler Infrastructure
5This file is distributed under the University of Illinois Open Source
6License. See LICENSE.TXT for details.
7"""
Enrico Granataeb4a4792012-02-23 23:10:27 +00008# synthetic children provider for NSArray
9import lldb
10import ctypes
11import objc_runtime
12import metrics
13
14statistics = metrics.Metrics()
15statistics.add_metric('invalid_isa')
16statistics.add_metric('invalid_pointer')
17statistics.add_metric('unknown_class')
18statistics.add_metric('code_notrun')
19
20# much less functional than the other two cases below
21# just runs code to get to the count and then returns
22# no children
23class NSArrayKVC_SynthProvider:
24
25 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000026 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000027
Enrico Granatacfdafa32012-03-05 19:56:33 +000028 def __init__(self, valobj, dict, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000029 self.valobj = valobj;
30 self.update()
31
32 def update(self):
33 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000034
35 def num_children(self):
36 stream = lldb.SBStream()
37 self.valobj.GetExpressionPath(stream)
38 num_children_vo = self.valobj.CreateValueFromExpression("count","(int)[" + stream.GetData() + " count]");
Enrico Granata3f1052b2012-03-13 21:52:00 +000039 if num_children_vo.IsValid():
40 return num_children_vo.GetValueAsUnsigned(0)
41 return "<variable is not NSArray>"
Enrico Granataeb4a4792012-02-23 23:10:27 +000042
Enrico Granataeb4a4792012-02-23 23:10:27 +000043# much less functional than the other two cases below
44# just runs code to get to the count and then returns
45# no children
46class NSArrayCF_SynthProvider:
47
48 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000049 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000050
Enrico Granatacfdafa32012-03-05 19:56:33 +000051 def __init__(self, valobj, dict, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000052 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000053 self.sys_params = params
54 if not (self.sys_params.types_cache.ulong):
55 self.sys_params.types_cache.ulong = self.valobj.GetType().GetBasicType(lldb.eBasicTypeUnsignedLong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000056 self.update()
57
58 def update(self):
59 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000060
61 def num_children(self):
62 num_children_vo = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +000063 self.sys_params.cfruntime_size,
64 self.sys_params.types_cache.ulong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000065 return num_children_vo.GetValueAsUnsigned(0)
66
Enrico Granataeb4a4792012-02-23 23:10:27 +000067class NSArrayI_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000068 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000069 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000070
Enrico Granatacfdafa32012-03-05 19:56:33 +000071 def __init__(self, valobj, dict, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000072 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000073 self.sys_params = params
74 if not(self.sys_params.types_cache.long):
75 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
Enrico Granataeb4a4792012-02-23 23:10:27 +000076 self.update()
77
78 def update(self):
79 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +000080
81 # skip the isa pointer and get at the size
82 def num_children(self):
Enrico Granataeb4a4792012-02-23 23:10:27 +000083 count = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +000084 self.sys_params.pointer_size,
85 self.sys_params.types_cache.long);
86 return count.GetValueAsUnsigned(0)
Enrico Granataeb4a4792012-02-23 23:10:27 +000087
88class NSArrayM_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +000089 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +000090 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +000091
Enrico Granatacfdafa32012-03-05 19:56:33 +000092 def __init__(self, valobj, dict, params):
Enrico Granataeb4a4792012-02-23 23:10:27 +000093 self.valobj = valobj;
Enrico Granatacfdafa32012-03-05 19:56:33 +000094 self.sys_params = params
95 if not(self.sys_params.types_cache.long):
96 self.sys_params.types_cache.long = self.valobj.GetType().GetBasicType(lldb.eBasicTypeLong)
97 self.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +000098
99 def update(self):
100 self.adjust_for_architecture();
Enrico Granataeb4a4792012-02-23 23:10:27 +0000101
102 # skip the isa pointer and get at the size
103 def num_children(self):
Enrico Granataeb4a4792012-02-23 23:10:27 +0000104 count = self.valobj.CreateChildAtOffset("count",
Enrico Granatacfdafa32012-03-05 19:56:33 +0000105 self.sys_params.pointer_size,
106 self.sys_params.types_cache.long);
107 return count.GetValueAsUnsigned(0)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000108
109# this is the actual synth provider, but is just a wrapper that checks
110# whether valobj is an instance of __NSArrayI or __NSArrayM and sets up an
111# appropriate backend layer to do the computations
112class NSArray_SynthProvider:
Enrico Granataeb4a4792012-02-23 23:10:27 +0000113 def adjust_for_architecture(self):
Enrico Granatacfdafa32012-03-05 19:56:33 +0000114 pass
Enrico Granataeb4a4792012-02-23 23:10:27 +0000115
116 def __init__(self, valobj, dict):
117 self.valobj = valobj;
118 self.adjust_for_architecture()
Enrico Granata3f1052b2012-03-13 21:52:00 +0000119 self.error = False
120 self.wrapper = self.make_wrapper()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000121 self.invalid = (self.wrapper == None)
122
Enrico Granataeb4a4792012-02-23 23:10:27 +0000123 def num_children(self):
124 if self.wrapper == None:
125 return 0;
126 return self.wrapper.num_children()
127
128 def update(self):
129 if self.wrapper == None:
Enrico Granatacfdafa32012-03-05 19:56:33 +0000130 return
131 self.wrapper.update()
Enrico Granataeb4a4792012-02-23 23:10:27 +0000132
133 # this code acts as our defense against NULL and unitialized
134 # NSArray pointers, which makes it much longer than it would be otherwise
Enrico Granata3f1052b2012-03-13 21:52:00 +0000135 def make_wrapper(self):
136 if self.valobj.GetValueAsUnsigned() == 0:
137 self.error = True
138 return objc_runtime.InvalidPointer_Description(True)
139 else:
140 global statistics
141 class_data,wrapper = objc_runtime.Utilities.prepare_class_detection(self.valobj,statistics)
142 if wrapper:
143 self.error = True
144 return wrapper
Enrico Granataeb4a4792012-02-23 23:10:27 +0000145
146 name_string = class_data.class_name()
147 if name_string == '__NSArrayI':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000148 wrapper = NSArrayI_SynthProvider(self.valobj, dict, class_data.sys_params)
149 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000150 elif name_string == '__NSArrayM':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000151 wrapper = NSArrayM_SynthProvider(self.valobj, dict, class_data.sys_params)
152 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000153 elif name_string == '__NSCFArray':
Enrico Granata3f1052b2012-03-13 21:52:00 +0000154 wrapper = NSArrayCF_SynthProvider(self.valobj, dict, class_data.sys_params)
155 statistics.metric_hit('code_notrun',self.valobj)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000156 else:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000157 wrapper = NSArrayKVC_SynthProvider(self.valobj, dict, class_data.sys_params)
158 statistics.metric_hit('unknown_class',str(self.valobj) + " seen as " + name_string)
Enrico Granataeb4a4792012-02-23 23:10:27 +0000159 return wrapper;
160
161def CFArray_SummaryProvider (valobj,dict):
162 provider = NSArray_SynthProvider(valobj,dict);
163 if provider.invalid == False:
Enrico Granata3f1052b2012-03-13 21:52:00 +0000164 if provider.error == True:
165 return provider.wrapper.message()
166 try:
167 summary = int(provider.num_children());
168 except:
169 summary = None
170 if summary == None:
171 summary = '<variable is not NSArray>'
172 elif isinstance(summary,basestring):
173 pass
174 else:
175 # we format it like it were a CFString to make it look the same as the summary from Xcode
176 summary = '@"' + str(summary) + (" objects" if summary != 1 else " object") + '"'
177 return summary
178 return 'Summary Unavailable'
Enrico Granataeb4a4792012-02-23 23:10:27 +0000179
180def __lldb_init_module(debugger,dict):
181 debugger.HandleCommand("type summary add -F CFArray.CFArray_SummaryProvider NSArray CFArrayRef CFMutableArrayRef")