xref: /freebsd-src/contrib/llvm-project/lldb/source/Interpreter/OptionValueProperties.cpp (revision 06c3fb2749bda94cb5201f81ffdb8fa6c3161b2e)
15ffd83dbSDimitry Andric //===-- OptionValueProperties.cpp -----------------------------------------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValueProperties.h"
100b57cec5SDimitry Andric 
110b57cec5SDimitry Andric #include "lldb/Utility/Flags.h"
120b57cec5SDimitry Andric 
130b57cec5SDimitry Andric #include "lldb/Core/UserSettingsController.h"
140b57cec5SDimitry Andric #include "lldb/Interpreter/OptionValues.h"
150b57cec5SDimitry Andric #include "lldb/Interpreter/Property.h"
160b57cec5SDimitry Andric #include "lldb/Utility/Args.h"
170b57cec5SDimitry Andric #include "lldb/Utility/Stream.h"
180b57cec5SDimitry Andric #include "lldb/Utility/StringList.h"
190b57cec5SDimitry Andric 
200b57cec5SDimitry Andric using namespace lldb;
210b57cec5SDimitry Andric using namespace lldb_private;
220b57cec5SDimitry Andric 
OptionValueProperties(llvm::StringRef name)23*06c3fb27SDimitry Andric OptionValueProperties::OptionValueProperties(llvm::StringRef name)
24*06c3fb27SDimitry Andric     : m_name(name.str()) {}
250b57cec5SDimitry Andric 
Initialize(const PropertyDefinitions & defs)260b57cec5SDimitry Andric void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {
270b57cec5SDimitry Andric   for (const auto &definition : defs) {
280b57cec5SDimitry Andric     Property property(definition);
290b57cec5SDimitry Andric     assert(property.IsValid());
30*06c3fb27SDimitry Andric     m_name_to_index.insert({property.GetName(), m_properties.size()});
310b57cec5SDimitry Andric     property.GetValue()->SetParent(shared_from_this());
320b57cec5SDimitry Andric     m_properties.push_back(property);
330b57cec5SDimitry Andric   }
340b57cec5SDimitry Andric }
350b57cec5SDimitry Andric 
SetValueChangedCallback(size_t property_idx,std::function<void ()> callback)360b57cec5SDimitry Andric void OptionValueProperties::SetValueChangedCallback(
37*06c3fb27SDimitry Andric     size_t property_idx, std::function<void()> callback) {
380b57cec5SDimitry Andric   Property *property = ProtectedGetPropertyAtIndex(property_idx);
390b57cec5SDimitry Andric   if (property)
40480093f4SDimitry Andric     property->SetValueChangedCallback(std::move(callback));
410b57cec5SDimitry Andric }
420b57cec5SDimitry Andric 
AppendProperty(llvm::StringRef name,llvm::StringRef desc,bool is_global,const OptionValueSP & value_sp)43*06c3fb27SDimitry Andric void OptionValueProperties::AppendProperty(llvm::StringRef name,
44*06c3fb27SDimitry Andric                                            llvm::StringRef desc, bool is_global,
450b57cec5SDimitry Andric                                            const OptionValueSP &value_sp) {
46*06c3fb27SDimitry Andric   Property property(name, desc, is_global, value_sp);
47*06c3fb27SDimitry Andric   m_name_to_index.insert({name, m_properties.size()});
480b57cec5SDimitry Andric   m_properties.push_back(property);
490b57cec5SDimitry Andric   value_sp->SetParent(shared_from_this());
500b57cec5SDimitry Andric }
510b57cec5SDimitry Andric 
520b57cec5SDimitry Andric lldb::OptionValueSP
GetValueForKey(const ExecutionContext * exe_ctx,llvm::StringRef key) const530b57cec5SDimitry Andric OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,
54*06c3fb27SDimitry Andric                                       llvm::StringRef key) const {
55*06c3fb27SDimitry Andric   auto iter = m_name_to_index.find(key);
56*06c3fb27SDimitry Andric   if (iter == m_name_to_index.end())
57*06c3fb27SDimitry Andric     return OptionValueSP();
58*06c3fb27SDimitry Andric   const size_t idx = iter->second;
59*06c3fb27SDimitry Andric   if (idx >= m_properties.size())
60*06c3fb27SDimitry Andric     return OptionValueSP();
61*06c3fb27SDimitry Andric   return GetPropertyAtIndex(idx, exe_ctx)->GetValue();
620b57cec5SDimitry Andric }
630b57cec5SDimitry Andric 
640b57cec5SDimitry Andric lldb::OptionValueSP
GetSubValue(const ExecutionContext * exe_ctx,llvm::StringRef name,Status & error) const650b57cec5SDimitry Andric OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,
66*06c3fb27SDimitry Andric                                    llvm::StringRef name, Status &error) const {
670b57cec5SDimitry Andric   lldb::OptionValueSP value_sp;
680b57cec5SDimitry Andric   if (name.empty())
690b57cec5SDimitry Andric     return OptionValueSP();
700b57cec5SDimitry Andric 
710b57cec5SDimitry Andric   llvm::StringRef sub_name;
72*06c3fb27SDimitry Andric   llvm::StringRef key;
730b57cec5SDimitry Andric   size_t key_len = name.find_first_of(".[{");
740b57cec5SDimitry Andric   if (key_len != llvm::StringRef::npos) {
75*06c3fb27SDimitry Andric     key = name.take_front(key_len);
760b57cec5SDimitry Andric     sub_name = name.drop_front(key_len);
770b57cec5SDimitry Andric   } else
78*06c3fb27SDimitry Andric     key = name;
790b57cec5SDimitry Andric 
80*06c3fb27SDimitry Andric   value_sp = GetValueForKey(exe_ctx, key);
810b57cec5SDimitry Andric   if (sub_name.empty() || !value_sp)
820b57cec5SDimitry Andric     return value_sp;
830b57cec5SDimitry Andric 
840b57cec5SDimitry Andric   switch (sub_name[0]) {
850b57cec5SDimitry Andric   case '.': {
860b57cec5SDimitry Andric     lldb::OptionValueSP return_val_sp;
870b57cec5SDimitry Andric     return_val_sp =
88*06c3fb27SDimitry Andric         value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), error);
890b57cec5SDimitry Andric     if (!return_val_sp) {
900b57cec5SDimitry Andric       if (Properties::IsSettingExperimental(sub_name.drop_front())) {
91*06c3fb27SDimitry Andric         const size_t experimental_len =
92*06c3fb27SDimitry Andric             Properties::GetExperimentalSettingsName().size();
930b57cec5SDimitry Andric         if (sub_name[experimental_len + 1] == '.')
940b57cec5SDimitry Andric           return_val_sp = value_sp->GetSubValue(
95*06c3fb27SDimitry Andric               exe_ctx, sub_name.drop_front(experimental_len + 2), error);
960b57cec5SDimitry Andric         // It isn't an error if an experimental setting is not present.
970b57cec5SDimitry Andric         if (!return_val_sp)
980b57cec5SDimitry Andric           error.Clear();
990b57cec5SDimitry Andric       }
1000b57cec5SDimitry Andric     }
1010b57cec5SDimitry Andric     return return_val_sp;
1020b57cec5SDimitry Andric   }
1030b57cec5SDimitry Andric   case '[':
1040b57cec5SDimitry Andric     // Array or dictionary access for subvalues like: "[12]"       -- access
1050b57cec5SDimitry Andric     // 12th array element "['hello']"  -- dictionary access of key named hello
106*06c3fb27SDimitry Andric     return value_sp->GetSubValue(exe_ctx, sub_name, error);
1070b57cec5SDimitry Andric 
1080b57cec5SDimitry Andric   default:
1090b57cec5SDimitry Andric     value_sp.reset();
1100b57cec5SDimitry Andric     break;
1110b57cec5SDimitry Andric   }
1120b57cec5SDimitry Andric   return value_sp;
1130b57cec5SDimitry Andric }
1140b57cec5SDimitry Andric 
SetSubValue(const ExecutionContext * exe_ctx,VarSetOperationType op,llvm::StringRef name,llvm::StringRef value)1150b57cec5SDimitry Andric Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,
1160b57cec5SDimitry Andric                                           VarSetOperationType op,
1170b57cec5SDimitry Andric                                           llvm::StringRef name,
1180b57cec5SDimitry Andric                                           llvm::StringRef value) {
1190b57cec5SDimitry Andric   Status error;
1200b57cec5SDimitry Andric   llvm::SmallVector<llvm::StringRef, 8> components;
1210b57cec5SDimitry Andric   name.split(components, '.');
1220b57cec5SDimitry Andric   bool name_contains_experimental = false;
1230b57cec5SDimitry Andric   for (const auto &part : components)
1240b57cec5SDimitry Andric     if (Properties::IsSettingExperimental(part))
1250b57cec5SDimitry Andric       name_contains_experimental = true;
1260b57cec5SDimitry Andric 
127*06c3fb27SDimitry Andric   lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, error));
1280b57cec5SDimitry Andric   if (value_sp)
1290b57cec5SDimitry Andric     error = value_sp->SetValueFromString(value, op);
1300b57cec5SDimitry Andric   else {
1310b57cec5SDimitry Andric     // Don't set an error if the path contained .experimental. - those are
1320b57cec5SDimitry Andric     // allowed to be missing and should silently fail.
1330b57cec5SDimitry Andric     if (!name_contains_experimental && error.AsCString() == nullptr) {
134*06c3fb27SDimitry Andric       error.SetErrorStringWithFormat("invalid value path '%s'",
135*06c3fb27SDimitry Andric                                      name.str().c_str());
1360b57cec5SDimitry Andric     }
1370b57cec5SDimitry Andric   }
1380b57cec5SDimitry Andric   return error;
1390b57cec5SDimitry Andric }
1400b57cec5SDimitry Andric 
GetPropertyIndex(llvm::StringRef name) const141*06c3fb27SDimitry Andric size_t OptionValueProperties::GetPropertyIndex(llvm::StringRef name) const {
142*06c3fb27SDimitry Andric   auto iter = m_name_to_index.find(name);
143*06c3fb27SDimitry Andric   if (iter == m_name_to_index.end())
144*06c3fb27SDimitry Andric     return SIZE_MAX;
145*06c3fb27SDimitry Andric   return iter->second;
1460b57cec5SDimitry Andric }
1470b57cec5SDimitry Andric 
1480b57cec5SDimitry Andric const Property *
GetProperty(llvm::StringRef name,const ExecutionContext * exe_ctx) const149*06c3fb27SDimitry Andric OptionValueProperties::GetProperty(llvm::StringRef name,
150*06c3fb27SDimitry Andric                                    const ExecutionContext *exe_ctx) const {
151*06c3fb27SDimitry Andric   auto iter = m_name_to_index.find(name);
152*06c3fb27SDimitry Andric   if (iter == m_name_to_index.end())
153*06c3fb27SDimitry Andric     return nullptr;
154*06c3fb27SDimitry Andric   return GetPropertyAtIndex(iter->second, exe_ctx);
1550b57cec5SDimitry Andric }
1560b57cec5SDimitry Andric 
GetPropertyValueAtIndex(size_t idx,const ExecutionContext * exe_ctx) const1570b57cec5SDimitry Andric lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(
158*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
159*06c3fb27SDimitry Andric   const Property *setting = GetPropertyAtIndex(idx, exe_ctx);
1600b57cec5SDimitry Andric   if (setting)
1610b57cec5SDimitry Andric     return setting->GetValue();
1620b57cec5SDimitry Andric   return OptionValueSP();
1630b57cec5SDimitry Andric }
1640b57cec5SDimitry Andric 
1650b57cec5SDimitry Andric OptionValuePathMappings *
GetPropertyAtIndexAsOptionValuePathMappings(size_t idx,const ExecutionContext * exe_ctx) const1660b57cec5SDimitry Andric OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(
167*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
168*06c3fb27SDimitry Andric   OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
1690b57cec5SDimitry Andric   if (value_sp)
1700b57cec5SDimitry Andric     return value_sp->GetAsPathMappings();
1710b57cec5SDimitry Andric   return nullptr;
1720b57cec5SDimitry Andric }
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric OptionValueFileSpecList *
GetPropertyAtIndexAsOptionValueFileSpecList(size_t idx,const ExecutionContext * exe_ctx) const1750b57cec5SDimitry Andric OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(
176*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
177*06c3fb27SDimitry Andric   OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
1780b57cec5SDimitry Andric   if (value_sp)
1790b57cec5SDimitry Andric     return value_sp->GetAsFileSpecList();
1800b57cec5SDimitry Andric   return nullptr;
1810b57cec5SDimitry Andric }
1820b57cec5SDimitry Andric 
GetPropertyAtIndexAsArgs(size_t idx,Args & args,const ExecutionContext * exe_ctx) const1830b57cec5SDimitry Andric bool OptionValueProperties::GetPropertyAtIndexAsArgs(
184*06c3fb27SDimitry Andric     size_t idx, Args &args, const ExecutionContext *exe_ctx) const {
185*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
186fe6060f1SDimitry Andric   if (!property)
187fe6060f1SDimitry Andric     return false;
188fe6060f1SDimitry Andric 
1890b57cec5SDimitry Andric   OptionValue *value = property->GetValue().get();
190fe6060f1SDimitry Andric   if (!value)
191fe6060f1SDimitry Andric     return false;
192fe6060f1SDimitry Andric 
193fe6060f1SDimitry Andric   const OptionValueArgs *arguments = value->GetAsArgs();
194bdd1243dSDimitry Andric   if (arguments) {
195bdd1243dSDimitry Andric     arguments->GetArgs(args);
196bdd1243dSDimitry Andric     return true;
197bdd1243dSDimitry Andric   }
198fe6060f1SDimitry Andric 
1990b57cec5SDimitry Andric   const OptionValueArray *array = value->GetAsArray();
200bdd1243dSDimitry Andric   if (array) {
201bdd1243dSDimitry Andric     array->GetArgs(args);
202bdd1243dSDimitry Andric     return true;
203bdd1243dSDimitry Andric   }
204fe6060f1SDimitry Andric 
2050b57cec5SDimitry Andric   const OptionValueDictionary *dict = value->GetAsDictionary();
206bdd1243dSDimitry Andric   if (dict) {
207bdd1243dSDimitry Andric     dict->GetArgs(args);
208bdd1243dSDimitry Andric     return true;
209bdd1243dSDimitry Andric   }
210fe6060f1SDimitry Andric 
2110b57cec5SDimitry Andric   return false;
2120b57cec5SDimitry Andric }
2130b57cec5SDimitry Andric 
SetPropertyAtIndexFromArgs(size_t idx,const Args & args,const ExecutionContext * exe_ctx)2140b57cec5SDimitry Andric bool OptionValueProperties::SetPropertyAtIndexFromArgs(
215*06c3fb27SDimitry Andric     size_t idx, const Args &args, const ExecutionContext *exe_ctx) {
216*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
217fe6060f1SDimitry Andric   if (!property)
218fe6060f1SDimitry Andric     return false;
219fe6060f1SDimitry Andric 
2200b57cec5SDimitry Andric   OptionValue *value = property->GetValue().get();
221fe6060f1SDimitry Andric   if (!value)
222fe6060f1SDimitry Andric     return false;
223fe6060f1SDimitry Andric 
224fe6060f1SDimitry Andric   OptionValueArgs *arguments = value->GetAsArgs();
225fe6060f1SDimitry Andric   if (arguments)
226fe6060f1SDimitry Andric     return arguments->SetArgs(args, eVarSetOperationAssign).Success();
227fe6060f1SDimitry Andric 
2280b57cec5SDimitry Andric   OptionValueArray *array = value->GetAsArray();
2290b57cec5SDimitry Andric   if (array)
2300b57cec5SDimitry Andric     return array->SetArgs(args, eVarSetOperationAssign).Success();
231fe6060f1SDimitry Andric 
2320b57cec5SDimitry Andric   OptionValueDictionary *dict = value->GetAsDictionary();
2330b57cec5SDimitry Andric   if (dict)
2340b57cec5SDimitry Andric     return dict->SetArgs(args, eVarSetOperationAssign).Success();
235fe6060f1SDimitry Andric 
2360b57cec5SDimitry Andric   return false;
2370b57cec5SDimitry Andric }
2380b57cec5SDimitry Andric 
2390b57cec5SDimitry Andric OptionValueDictionary *
GetPropertyAtIndexAsOptionValueDictionary(size_t idx,const ExecutionContext * exe_ctx) const2400b57cec5SDimitry Andric OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(
241*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
242*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
2430b57cec5SDimitry Andric   if (property)
2440b57cec5SDimitry Andric     return property->GetValue()->GetAsDictionary();
2450b57cec5SDimitry Andric   return nullptr;
2460b57cec5SDimitry Andric }
2470b57cec5SDimitry Andric 
2480b57cec5SDimitry Andric OptionValueFileSpec *
GetPropertyAtIndexAsOptionValueFileSpec(size_t idx,const ExecutionContext * exe_ctx) const2490b57cec5SDimitry Andric OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(
250*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
251*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
2520b57cec5SDimitry Andric   if (property) {
2530b57cec5SDimitry Andric     OptionValue *value = property->GetValue().get();
2540b57cec5SDimitry Andric     if (value)
2550b57cec5SDimitry Andric       return value->GetAsFileSpec();
2560b57cec5SDimitry Andric   }
2570b57cec5SDimitry Andric   return nullptr;
2580b57cec5SDimitry Andric }
2590b57cec5SDimitry Andric 
GetPropertyAtIndexAsOptionValueSInt64(size_t idx,const ExecutionContext * exe_ctx) const2600b57cec5SDimitry Andric OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(
261*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
262*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
2630b57cec5SDimitry Andric   if (property) {
2640b57cec5SDimitry Andric     OptionValue *value = property->GetValue().get();
2650b57cec5SDimitry Andric     if (value)
2660b57cec5SDimitry Andric       return value->GetAsSInt64();
2670b57cec5SDimitry Andric   }
2680b57cec5SDimitry Andric   return nullptr;
2690b57cec5SDimitry Andric }
2700b57cec5SDimitry Andric 
GetPropertyAtIndexAsOptionValueUInt64(size_t idx,const ExecutionContext * exe_ctx) const27181ad6265SDimitry Andric OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(
272*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
273*06c3fb27SDimitry Andric   const Property *property = GetPropertyAtIndex(idx, exe_ctx);
27481ad6265SDimitry Andric   if (property) {
27581ad6265SDimitry Andric     OptionValue *value = property->GetValue().get();
27681ad6265SDimitry Andric     if (value)
27781ad6265SDimitry Andric       return value->GetAsUInt64();
27881ad6265SDimitry Andric   }
27981ad6265SDimitry Andric   return nullptr;
28081ad6265SDimitry Andric }
28181ad6265SDimitry Andric 
GetPropertyAtIndexAsOptionValueString(size_t idx,const ExecutionContext * exe_ctx) const2820b57cec5SDimitry Andric OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(
283*06c3fb27SDimitry Andric     size_t idx, const ExecutionContext *exe_ctx) const {
284*06c3fb27SDimitry Andric   OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));
2850b57cec5SDimitry Andric   if (value_sp)
2860b57cec5SDimitry Andric     return value_sp->GetAsString();
2870b57cec5SDimitry Andric   return nullptr;
2880b57cec5SDimitry Andric }
2890b57cec5SDimitry Andric 
Clear()290e8d8bef9SDimitry Andric void OptionValueProperties::Clear() {
2910b57cec5SDimitry Andric   const size_t num_properties = m_properties.size();
2920b57cec5SDimitry Andric   for (size_t i = 0; i < num_properties; ++i)
2930b57cec5SDimitry Andric     m_properties[i].GetValue()->Clear();
2940b57cec5SDimitry Andric }
2950b57cec5SDimitry Andric 
SetValueFromString(llvm::StringRef value,VarSetOperationType op)2960b57cec5SDimitry Andric Status OptionValueProperties::SetValueFromString(llvm::StringRef value,
2970b57cec5SDimitry Andric                                                  VarSetOperationType op) {
2980b57cec5SDimitry Andric   Status error;
2990b57cec5SDimitry Andric 
3000b57cec5SDimitry Andric   //    Args args(value_cstr);
3010b57cec5SDimitry Andric   //    const size_t argc = args.GetArgumentCount();
3020b57cec5SDimitry Andric   switch (op) {
3030b57cec5SDimitry Andric   case eVarSetOperationClear:
3040b57cec5SDimitry Andric     Clear();
3050b57cec5SDimitry Andric     break;
3060b57cec5SDimitry Andric 
3070b57cec5SDimitry Andric   case eVarSetOperationReplace:
3080b57cec5SDimitry Andric   case eVarSetOperationAssign:
3090b57cec5SDimitry Andric   case eVarSetOperationRemove:
3100b57cec5SDimitry Andric   case eVarSetOperationInsertBefore:
3110b57cec5SDimitry Andric   case eVarSetOperationInsertAfter:
3120b57cec5SDimitry Andric   case eVarSetOperationAppend:
3130b57cec5SDimitry Andric   case eVarSetOperationInvalid:
3140b57cec5SDimitry Andric     error = OptionValue::SetValueFromString(value, op);
3150b57cec5SDimitry Andric     break;
3160b57cec5SDimitry Andric   }
3170b57cec5SDimitry Andric 
3180b57cec5SDimitry Andric   return error;
3190b57cec5SDimitry Andric }
3200b57cec5SDimitry Andric 
DumpValue(const ExecutionContext * exe_ctx,Stream & strm,uint32_t dump_mask)3210b57cec5SDimitry Andric void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,
3220b57cec5SDimitry Andric                                       Stream &strm, uint32_t dump_mask) {
3230b57cec5SDimitry Andric   const size_t num_properties = m_properties.size();
3240b57cec5SDimitry Andric   for (size_t i = 0; i < num_properties; ++i) {
325*06c3fb27SDimitry Andric     const Property *property = GetPropertyAtIndex(i, exe_ctx);
3260b57cec5SDimitry Andric     if (property) {
3270b57cec5SDimitry Andric       OptionValue *option_value = property->GetValue().get();
3280b57cec5SDimitry Andric       assert(option_value);
3290b57cec5SDimitry Andric       const bool transparent_value = option_value->ValueIsTransparent();
3300b57cec5SDimitry Andric       property->Dump(exe_ctx, strm, dump_mask);
3310b57cec5SDimitry Andric       if (!transparent_value)
3320b57cec5SDimitry Andric         strm.EOL();
3330b57cec5SDimitry Andric     }
3340b57cec5SDimitry Andric   }
3350b57cec5SDimitry Andric }
3360b57cec5SDimitry Andric 
337bdd1243dSDimitry Andric llvm::json::Value
ToJSON(const ExecutionContext * exe_ctx)338bdd1243dSDimitry Andric OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) {
339bdd1243dSDimitry Andric   llvm::json::Object json_properties;
340bdd1243dSDimitry Andric   const size_t num_properties = m_properties.size();
341bdd1243dSDimitry Andric   for (size_t i = 0; i < num_properties; ++i) {
342*06c3fb27SDimitry Andric     const Property *property = GetPropertyAtIndex(i, exe_ctx);
343bdd1243dSDimitry Andric     if (property) {
344bdd1243dSDimitry Andric       OptionValue *option_value = property->GetValue().get();
345bdd1243dSDimitry Andric       assert(option_value);
346bdd1243dSDimitry Andric       json_properties.try_emplace(property->GetName(),
347bdd1243dSDimitry Andric                                   option_value->ToJSON(exe_ctx));
348bdd1243dSDimitry Andric     }
349bdd1243dSDimitry Andric   }
350bdd1243dSDimitry Andric   return json_properties;
351bdd1243dSDimitry Andric }
352bdd1243dSDimitry Andric 
DumpPropertyValue(const ExecutionContext * exe_ctx,Stream & strm,llvm::StringRef property_path,uint32_t dump_mask,bool is_json)3530b57cec5SDimitry Andric Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
3540b57cec5SDimitry Andric                                                 Stream &strm,
3550b57cec5SDimitry Andric                                                 llvm::StringRef property_path,
356*06c3fb27SDimitry Andric                                                 uint32_t dump_mask,
357*06c3fb27SDimitry Andric                                                 bool is_json) {
3580b57cec5SDimitry Andric   Status error;
359*06c3fb27SDimitry Andric   lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, property_path, error));
3600b57cec5SDimitry Andric   if (value_sp) {
3610b57cec5SDimitry Andric     if (!value_sp->ValueIsTransparent()) {
3620b57cec5SDimitry Andric       if (dump_mask & eDumpOptionName)
3630b57cec5SDimitry Andric         strm.PutCString(property_path);
3640b57cec5SDimitry Andric       if (dump_mask & ~eDumpOptionName)
3650b57cec5SDimitry Andric         strm.PutChar(' ');
3660b57cec5SDimitry Andric     }
367bdd1243dSDimitry Andric     if (is_json) {
368*06c3fb27SDimitry Andric       strm.Printf(
369*06c3fb27SDimitry Andric           "%s",
370*06c3fb27SDimitry Andric           llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
371bdd1243dSDimitry Andric     } else
3720b57cec5SDimitry Andric       value_sp->DumpValue(exe_ctx, strm, dump_mask);
3730b57cec5SDimitry Andric   }
3740b57cec5SDimitry Andric   return error;
3750b57cec5SDimitry Andric }
3760b57cec5SDimitry Andric 
377fe6060f1SDimitry Andric OptionValuePropertiesSP
CreateLocalCopy(const Properties & global_properties)378fe6060f1SDimitry Andric OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {
379fe6060f1SDimitry Andric   auto global_props_sp = global_properties.GetValueProperties();
380fe6060f1SDimitry Andric   lldbassert(global_props_sp);
381fe6060f1SDimitry Andric 
382fe6060f1SDimitry Andric   auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());
383fe6060f1SDimitry Andric   return std::static_pointer_cast<OptionValueProperties>(copy_sp);
384fe6060f1SDimitry Andric }
385fe6060f1SDimitry Andric 
386fe6060f1SDimitry Andric OptionValueSP
DeepCopy(const OptionValueSP & new_parent) const387fe6060f1SDimitry Andric OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {
388fe6060f1SDimitry Andric   auto copy_sp = OptionValue::DeepCopy(new_parent);
389fe6060f1SDimitry Andric   // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived
390fe6060f1SDimitry Andric   // types that override GetType returning a different value.
391fe6060f1SDimitry Andric   auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());
392fe6060f1SDimitry Andric   lldbassert(props_value_ptr);
393fe6060f1SDimitry Andric 
394fe6060f1SDimitry Andric   for (auto &property : props_value_ptr->m_properties) {
395fe6060f1SDimitry Andric     // Duplicate any values that are not global when constructing properties
396fe6060f1SDimitry Andric     // from a global copy.
397fe6060f1SDimitry Andric     if (!property.IsGlobal()) {
398fe6060f1SDimitry Andric       auto value_sp = property.GetValue()->DeepCopy(copy_sp);
399fe6060f1SDimitry Andric       property.SetOptionValue(value_sp);
400fe6060f1SDimitry Andric     }
401fe6060f1SDimitry Andric   }
402fe6060f1SDimitry Andric   return copy_sp;
4030b57cec5SDimitry Andric }
4040b57cec5SDimitry Andric 
405*06c3fb27SDimitry Andric const Property *
GetPropertyAtPath(const ExecutionContext * exe_ctx,llvm::StringRef name) const406*06c3fb27SDimitry Andric OptionValueProperties::GetPropertyAtPath(const ExecutionContext *exe_ctx,
407*06c3fb27SDimitry Andric                                          llvm::StringRef name) const {
4080b57cec5SDimitry Andric   if (name.empty())
4090b57cec5SDimitry Andric     return nullptr;
410*06c3fb27SDimitry Andric 
411*06c3fb27SDimitry Andric   const Property *property = nullptr;
4120b57cec5SDimitry Andric   llvm::StringRef sub_name;
413*06c3fb27SDimitry Andric   llvm::StringRef key;
4140b57cec5SDimitry Andric   size_t key_len = name.find_first_of(".[{");
4150b57cec5SDimitry Andric 
4160b57cec5SDimitry Andric   if (key_len != llvm::StringRef::npos) {
417*06c3fb27SDimitry Andric     key = name.take_front(key_len);
4180b57cec5SDimitry Andric     sub_name = name.drop_front(key_len);
4190b57cec5SDimitry Andric   } else
420*06c3fb27SDimitry Andric     key = name;
4210b57cec5SDimitry Andric 
422*06c3fb27SDimitry Andric   property = GetProperty(key, exe_ctx);
4230b57cec5SDimitry Andric   if (sub_name.empty() || !property)
4240b57cec5SDimitry Andric     return property;
4250b57cec5SDimitry Andric 
4260b57cec5SDimitry Andric   if (sub_name[0] == '.') {
4270b57cec5SDimitry Andric     OptionValueProperties *sub_properties =
4280b57cec5SDimitry Andric         property->GetValue()->GetAsProperties();
4290b57cec5SDimitry Andric     if (sub_properties)
430*06c3fb27SDimitry Andric       return sub_properties->GetPropertyAtPath(exe_ctx, sub_name.drop_front());
4310b57cec5SDimitry Andric   }
4320b57cec5SDimitry Andric   return nullptr;
4330b57cec5SDimitry Andric }
4340b57cec5SDimitry Andric 
DumpAllDescriptions(CommandInterpreter & interpreter,Stream & strm) const4350b57cec5SDimitry Andric void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,
4360b57cec5SDimitry Andric                                                 Stream &strm) const {
4370b57cec5SDimitry Andric   size_t max_name_len = 0;
4380b57cec5SDimitry Andric   const size_t num_properties = m_properties.size();
4390b57cec5SDimitry Andric   for (size_t i = 0; i < num_properties; ++i) {
4400b57cec5SDimitry Andric     const Property *property = ProtectedGetPropertyAtIndex(i);
4410b57cec5SDimitry Andric     if (property)
4420b57cec5SDimitry Andric       max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);
4430b57cec5SDimitry Andric   }
4440b57cec5SDimitry Andric   for (size_t i = 0; i < num_properties; ++i) {
4450b57cec5SDimitry Andric     const Property *property = ProtectedGetPropertyAtIndex(i);
4460b57cec5SDimitry Andric     if (property)
4470b57cec5SDimitry Andric       property->DumpDescription(interpreter, strm, max_name_len, false);
4480b57cec5SDimitry Andric   }
4490b57cec5SDimitry Andric }
4500b57cec5SDimitry Andric 
Apropos(llvm::StringRef keyword,std::vector<const Property * > & matching_properties) const4510b57cec5SDimitry Andric void OptionValueProperties::Apropos(
4520b57cec5SDimitry Andric     llvm::StringRef keyword,
4530b57cec5SDimitry Andric     std::vector<const Property *> &matching_properties) const {
4540b57cec5SDimitry Andric   const size_t num_properties = m_properties.size();
4550b57cec5SDimitry Andric   StreamString strm;
4560b57cec5SDimitry Andric   for (size_t i = 0; i < num_properties; ++i) {
4570b57cec5SDimitry Andric     const Property *property = ProtectedGetPropertyAtIndex(i);
4580b57cec5SDimitry Andric     if (property) {
4590b57cec5SDimitry Andric       const OptionValueProperties *properties =
4600b57cec5SDimitry Andric           property->GetValue()->GetAsProperties();
4610b57cec5SDimitry Andric       if (properties) {
4620b57cec5SDimitry Andric         properties->Apropos(keyword, matching_properties);
4630b57cec5SDimitry Andric       } else {
4640b57cec5SDimitry Andric         bool match = false;
4650b57cec5SDimitry Andric         llvm::StringRef name = property->GetName();
466fe6060f1SDimitry Andric         if (name.contains_insensitive(keyword))
4670b57cec5SDimitry Andric           match = true;
4680b57cec5SDimitry Andric         else {
4690b57cec5SDimitry Andric           llvm::StringRef desc = property->GetDescription();
470fe6060f1SDimitry Andric           if (desc.contains_insensitive(keyword))
4710b57cec5SDimitry Andric             match = true;
4720b57cec5SDimitry Andric         }
4730b57cec5SDimitry Andric         if (match) {
4740b57cec5SDimitry Andric           matching_properties.push_back(property);
4750b57cec5SDimitry Andric         }
4760b57cec5SDimitry Andric       }
4770b57cec5SDimitry Andric     }
4780b57cec5SDimitry Andric   }
4790b57cec5SDimitry Andric }
4800b57cec5SDimitry Andric 
4810b57cec5SDimitry Andric lldb::OptionValuePropertiesSP
GetSubProperty(const ExecutionContext * exe_ctx,llvm::StringRef name)4820b57cec5SDimitry Andric OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,
483*06c3fb27SDimitry Andric                                       llvm::StringRef name) {
484*06c3fb27SDimitry Andric   lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name));
4850b57cec5SDimitry Andric   if (option_value_sp) {
4860b57cec5SDimitry Andric     OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();
4870b57cec5SDimitry Andric     if (ov_properties)
4880b57cec5SDimitry Andric       return ov_properties->shared_from_this();
4890b57cec5SDimitry Andric   }
4900b57cec5SDimitry Andric   return lldb::OptionValuePropertiesSP();
4910b57cec5SDimitry Andric }
492