[ValueObjectSynthetic and ValueObjectDynamicValue] Override GetDeclaration
[lldb.git] / lldb / source / Core / ValueObjectSyntheticFilter.cpp
1 //===-- ValueObjectSyntheticFilter.cpp -----------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "lldb/Core/ValueObjectSyntheticFilter.h"
11
12 // C Includes
13 // C++ Includes
14 // Other libraries and framework includes
15 // Project includes
16 #include "lldb/Core/ValueObject.h"
17 #include "lldb/DataFormatters/TypeSynthetic.h"
18
19 using namespace lldb_private;
20
21 class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
22 {
23 public:
24     DummySyntheticFrontEnd(ValueObject &backend) :
25     SyntheticChildrenFrontEnd(backend)
26     {}
27
28     size_t
29     CalculateNumChildren()
30     {
31         return m_backend.GetNumChildren();
32     }
33     
34     lldb::ValueObjectSP
35     GetChildAtIndex (size_t idx)
36     {
37         return m_backend.GetChildAtIndex(idx, true);
38     }
39     
40     size_t
41     GetIndexOfChildWithName (const ConstString &name)
42     {
43         return m_backend.GetIndexOfChildWithName(name);
44     }
45     
46     bool
47     MightHaveChildren ()
48     {
49         return true;
50     }
51     
52     bool
53     Update()
54     {
55         return false;
56     }
57
58 };
59
60 ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
61     ValueObject(parent),
62     m_synth_sp(filter),
63     m_children_byindex(),
64     m_name_toindex(),
65     m_synthetic_children_count(UINT32_MAX),
66     m_parent_type_name(parent.GetTypeName()),
67     m_might_have_children(eLazyBoolCalculate),
68     m_provides_value(eLazyBoolCalculate)
69 {
70 #ifdef FOOBAR
71     std::string new_name(parent.GetName().AsCString());
72     new_name += "$$__synth__";
73     SetName (ConstString(new_name.c_str()));
74 #else
75     SetName(parent.GetName());
76 #endif
77     CopyValueData(m_parent);
78     CreateSynthFilter();
79 }
80
81 ValueObjectSynthetic::~ValueObjectSynthetic()
82 {
83 }
84
85 CompilerType
86 ValueObjectSynthetic::GetClangTypeImpl ()
87 {
88     return m_parent->GetClangType();
89 }
90
91 ConstString
92 ValueObjectSynthetic::GetTypeName()
93 {
94     return m_parent->GetTypeName();
95 }
96
97 ConstString
98 ValueObjectSynthetic::GetQualifiedTypeName()
99 {
100     return m_parent->GetQualifiedTypeName();
101 }
102
103 ConstString
104 ValueObjectSynthetic::GetDisplayTypeName()
105 {
106     return m_parent->GetDisplayTypeName();
107 }
108
109 size_t
110 ValueObjectSynthetic::CalculateNumChildren()
111 {
112     UpdateValueIfNeeded();
113     if (m_synthetic_children_count < UINT32_MAX)
114         return m_synthetic_children_count;
115     return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
116 }
117
118 lldb::ValueObjectSP
119 ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
120 {
121     if (!m_parent)
122         return lldb::ValueObjectSP();
123     if (IsDynamic() && GetDynamicValueType() == valueType)
124         return GetSP();
125     return m_parent->GetDynamicValue(valueType);
126 }
127
128 bool
129 ValueObjectSynthetic::MightHaveChildren()
130 {
131     if (m_might_have_children == eLazyBoolCalculate)
132         m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
133     return (m_might_have_children == eLazyBoolNo ? false : true);
134 }
135
136 uint64_t
137 ValueObjectSynthetic::GetByteSize()
138 {
139     return m_parent->GetByteSize();
140 }
141
142 lldb::ValueType
143 ValueObjectSynthetic::GetValueType() const
144 {
145     return m_parent->GetValueType();
146 }
147
148 void
149 ValueObjectSynthetic::CreateSynthFilter ()
150 {
151     m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
152     if (!m_synth_filter_ap.get())
153         m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
154 }
155
156 bool
157 ValueObjectSynthetic::UpdateValue ()
158 {
159     SetValueIsValid (false);
160     m_error.Clear();
161
162     if (!m_parent->UpdateValueIfNeeded(false))
163     {
164         // our parent could not update.. as we are meaningless without a parent, just stop
165         if (m_parent->GetError().Fail())
166             m_error = m_parent->GetError();
167         return false;
168     }
169     
170     // regenerate the synthetic filter if our typename changes
171     // <rdar://problem/12424824>
172     ConstString new_parent_type_name = m_parent->GetTypeName();
173     if (new_parent_type_name != m_parent_type_name)
174     {
175         m_parent_type_name = new_parent_type_name;
176         CreateSynthFilter();
177     }
178
179     // let our backend do its update
180     if (m_synth_filter_ap->Update() == false)
181     {
182         // filter said that cached values are stale
183         m_children_byindex.Clear();
184         m_name_toindex.Clear();
185         // usually, an object's value can change but this does not alter its children count
186         // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
187         // that they need to come back to us asking for children
188         m_children_count_valid = false;
189         m_synthetic_children_count = UINT32_MAX;
190         m_might_have_children = eLazyBoolCalculate;
191     }
192     
193     m_provides_value = eLazyBoolCalculate;
194     
195     lldb::ValueObjectSP synth_val(m_synth_filter_ap->GetSyntheticValue());
196     
197     if (synth_val && synth_val->CanProvideValue())
198     {
199         m_provides_value = eLazyBoolYes;
200         CopyValueData(synth_val.get());
201     }
202     else
203     {
204         m_provides_value = eLazyBoolNo;
205         CopyValueData(m_parent);
206     }
207     
208     SetValueIsValid(true);
209     return true;
210 }
211
212 lldb::ValueObjectSP
213 ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
214 {
215     UpdateValueIfNeeded();
216     
217     ValueObject *valobj;
218     if (m_children_byindex.GetValueForKey(idx, valobj) == false)
219     {
220         if (can_create && m_synth_filter_ap.get() != NULL)
221         {
222             lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
223             if (!synth_guy)
224                 return synth_guy;
225             m_children_byindex.SetValueForKey(idx, synth_guy.get());
226             return synth_guy;
227         }
228         else
229             return lldb::ValueObjectSP();
230     }
231     else
232         return valobj->GetSP();
233 }
234
235 lldb::ValueObjectSP
236 ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
237 {
238     UpdateValueIfNeeded();
239
240     uint32_t index = GetIndexOfChildWithName(name);
241     
242     if (index == UINT32_MAX)
243         return lldb::ValueObjectSP();
244     
245     return GetChildAtIndex(index, can_create);
246 }
247
248 size_t
249 ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
250 {
251     UpdateValueIfNeeded();
252     
253     uint32_t found_index = UINT32_MAX;
254     bool did_find = m_name_toindex.GetValueForKey(name.GetCString(), found_index);
255     
256     if (!did_find && m_synth_filter_ap.get() != NULL)
257     {
258         uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
259         if (index == UINT32_MAX)
260             return index;
261         m_name_toindex.SetValueForKey(name.GetCString(), index);
262         return index;
263     }
264     else if (!did_find && m_synth_filter_ap.get() == NULL)
265         return UINT32_MAX;
266     else /*if (iter != m_name_toindex.end())*/
267         return found_index;
268 }
269
270 bool
271 ValueObjectSynthetic::IsInScope ()
272 {
273     return m_parent->IsInScope();
274 }
275
276 lldb::ValueObjectSP
277 ValueObjectSynthetic::GetNonSyntheticValue ()
278 {
279     return m_parent->GetSP();
280 }
281
282 void
283 ValueObjectSynthetic::CopyValueData (ValueObject *source)
284 {
285     m_value = (source->UpdateValueIfNeeded(), source->GetValue());
286     ExecutionContext exe_ctx (GetExecutionContextRef());
287     m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
288 }
289
290 bool
291 ValueObjectSynthetic::CanProvideValue ()
292 {
293     if (!UpdateValueIfNeeded())
294         return false;
295     if (m_provides_value == eLazyBoolYes)
296         return true;
297     return m_parent->CanProvideValue();
298 }
299
300 bool
301 ValueObjectSynthetic::SetValueFromCString (const char *value_str, Error& error)
302 {
303     return m_parent->SetValueFromCString(value_str, error);
304 }
305
306 void
307 ValueObjectSynthetic::SetFormat (lldb::Format format)
308 {
309     if (m_parent)
310     {
311         m_parent->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
312         m_parent->SetFormat(format);
313     }
314     this->ValueObject::SetFormat(format);
315     this->ClearUserVisibleData(eClearUserVisibleDataItemsAll);
316 }
317
318 bool
319 ValueObjectSynthetic::GetDeclaration (Declaration &decl)
320 {
321     if (m_parent)
322         return m_parent->GetDeclaration(decl);
323
324     return ValueObject::GetDeclaration(decl);
325 }