ValueObjectSyntheticFilter.cpp revision 263363
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/lldb-python.h"
11
12#include "lldb/Core/ValueObjectSyntheticFilter.h"
13
14// C Includes
15// C++ Includes
16// Other libraries and framework includes
17// Project includes
18#include "lldb/Core/ValueObject.h"
19#include "lldb/DataFormatters/FormatClasses.h"
20
21using namespace lldb_private;
22
23class DummySyntheticFrontEnd : public SyntheticChildrenFrontEnd
24{
25public:
26    DummySyntheticFrontEnd(ValueObject &backend) :
27    SyntheticChildrenFrontEnd(backend)
28    {}
29
30    size_t
31    CalculateNumChildren()
32    {
33        return m_backend.GetNumChildren();
34    }
35
36    lldb::ValueObjectSP
37    GetChildAtIndex (size_t idx)
38    {
39        return m_backend.GetChildAtIndex(idx, true);
40    }
41
42    size_t
43    GetIndexOfChildWithName (const ConstString &name)
44    {
45        return m_backend.GetIndexOfChildWithName(name);
46    }
47
48    bool
49    MightHaveChildren ()
50    {
51        return true;
52    }
53
54    bool
55    Update()
56    {
57        return false;
58    }
59
60};
61
62ValueObjectSynthetic::ValueObjectSynthetic (ValueObject &parent, lldb::SyntheticChildrenSP filter) :
63    ValueObject(parent),
64    m_synth_sp(filter),
65    m_children_byindex(),
66    m_name_toindex(),
67    m_synthetic_children_count(UINT32_MAX),
68    m_parent_type_name(parent.GetTypeName()),
69    m_might_have_children(eLazyBoolCalculate)
70{
71#ifdef LLDB_CONFIGURATION_DEBUG
72    std::string new_name(parent.GetName().AsCString());
73    new_name += "$$__synth__";
74    SetName (ConstString(new_name.c_str()));
75#else
76    SetName(parent.GetName());
77#endif
78    CopyParentData();
79    CreateSynthFilter();
80}
81
82ValueObjectSynthetic::~ValueObjectSynthetic()
83{
84}
85
86ClangASTType
87ValueObjectSynthetic::GetClangTypeImpl ()
88{
89    return m_parent->GetClangType();
90}
91
92ConstString
93ValueObjectSynthetic::GetTypeName()
94{
95    return m_parent->GetTypeName();
96}
97
98ConstString
99ValueObjectSynthetic::GetQualifiedTypeName()
100{
101    return m_parent->GetQualifiedTypeName();
102}
103
104size_t
105ValueObjectSynthetic::CalculateNumChildren()
106{
107    UpdateValueIfNeeded();
108    if (m_synthetic_children_count < UINT32_MAX)
109        return m_synthetic_children_count;
110    return (m_synthetic_children_count = m_synth_filter_ap->CalculateNumChildren());
111}
112
113lldb::ValueObjectSP
114ValueObjectSynthetic::GetDynamicValue (lldb::DynamicValueType valueType)
115{
116    if (!m_parent)
117        return lldb::ValueObjectSP();
118    if (IsDynamic() && GetDynamicValueType() == valueType)
119        return GetSP();
120    return m_parent->GetDynamicValue(valueType);
121}
122
123bool
124ValueObjectSynthetic::MightHaveChildren()
125{
126    if (m_might_have_children == eLazyBoolCalculate)
127        m_might_have_children = (m_synth_filter_ap->MightHaveChildren() ? eLazyBoolYes : eLazyBoolNo);
128    return (m_might_have_children == eLazyBoolNo ? false : true);
129}
130
131uint64_t
132ValueObjectSynthetic::GetByteSize()
133{
134    return m_parent->GetByteSize();
135}
136
137lldb::ValueType
138ValueObjectSynthetic::GetValueType() const
139{
140    return m_parent->GetValueType();
141}
142
143void
144ValueObjectSynthetic::CreateSynthFilter ()
145{
146    m_synth_filter_ap = (m_synth_sp->GetFrontEnd(*m_parent));
147    if (!m_synth_filter_ap.get())
148        m_synth_filter_ap.reset(new DummySyntheticFrontEnd(*m_parent));
149}
150
151bool
152ValueObjectSynthetic::UpdateValue ()
153{
154    SetValueIsValid (false);
155    m_error.Clear();
156
157    if (!m_parent->UpdateValueIfNeeded(false))
158    {
159        // our parent could not update.. as we are meaningless without a parent, just stop
160        if (m_parent->GetError().Fail())
161            m_error = m_parent->GetError();
162        return false;
163    }
164
165    // regenerate the synthetic filter if our typename changes
166    // <rdar://problem/12424824>
167    ConstString new_parent_type_name = m_parent->GetTypeName();
168    if (new_parent_type_name != m_parent_type_name)
169    {
170        m_parent_type_name = new_parent_type_name;
171        CreateSynthFilter();
172    }
173
174    // let our backend do its update
175    if (m_synth_filter_ap->Update() == false)
176    {
177        // filter said that cached values are stale
178        m_children_byindex.clear();
179        m_name_toindex.clear();
180        // usually, an object's value can change but this does not alter its children count
181        // for a synthetic VO that might indeed happen, so we need to tell the upper echelons
182        // that they need to come back to us asking for children
183        m_children_count_valid = false;
184        m_synthetic_children_count = UINT32_MAX;
185        m_might_have_children = eLazyBoolCalculate;
186    }
187
188    CopyParentData();
189
190    SetValueIsValid(true);
191    return true;
192}
193
194lldb::ValueObjectSP
195ValueObjectSynthetic::GetChildAtIndex (size_t idx, bool can_create)
196{
197    UpdateValueIfNeeded();
198
199    ByIndexIterator iter = m_children_byindex.find(idx);
200
201    if (iter == m_children_byindex.end())
202    {
203        if (can_create && m_synth_filter_ap.get() != NULL)
204        {
205            lldb::ValueObjectSP synth_guy = m_synth_filter_ap->GetChildAtIndex (idx);
206            if (!synth_guy)
207                return synth_guy;
208            m_children_byindex[idx]= synth_guy.get();
209            return synth_guy;
210        }
211        else
212            return lldb::ValueObjectSP();
213    }
214    else
215        return iter->second->GetSP();
216}
217
218lldb::ValueObjectSP
219ValueObjectSynthetic::GetChildMemberWithName (const ConstString &name, bool can_create)
220{
221    UpdateValueIfNeeded();
222
223    uint32_t index = GetIndexOfChildWithName(name);
224
225    if (index == UINT32_MAX)
226        return lldb::ValueObjectSP();
227
228    return GetChildAtIndex(index, can_create);
229}
230
231size_t
232ValueObjectSynthetic::GetIndexOfChildWithName (const ConstString &name)
233{
234    UpdateValueIfNeeded();
235
236    NameToIndexIterator iter = m_name_toindex.find(name.GetCString());
237
238    if (iter == m_name_toindex.end() && m_synth_filter_ap.get() != NULL)
239    {
240        uint32_t index = m_synth_filter_ap->GetIndexOfChildWithName (name);
241        if (index == UINT32_MAX)
242            return index;
243        m_name_toindex[name.GetCString()] = index;
244        return index;
245    }
246    else if (iter == m_name_toindex.end() && m_synth_filter_ap.get() == NULL)
247        return UINT32_MAX;
248    else /*if (iter != m_name_toindex.end())*/
249        return iter->second;
250}
251
252bool
253ValueObjectSynthetic::IsInScope ()
254{
255    return m_parent->IsInScope();
256}
257
258lldb::ValueObjectSP
259ValueObjectSynthetic::GetNonSyntheticValue ()
260{
261    return m_parent->GetSP();
262}
263
264void
265ValueObjectSynthetic::CopyParentData ()
266{
267    m_value = m_parent->GetValue();
268    ExecutionContext exe_ctx (GetExecutionContextRef());
269    m_error = m_value.GetValueAsData (&exe_ctx, m_data, 0, GetModule().get());
270}
271