brintos

brintos / llvm-project-archived public Read only

0
0
Text · 15.8 KiB · cb71bff Raw
492 lines · cpp
1//===-- OptionValueProperties.cpp -----------------------------------------===//2//3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.4// See https://llvm.org/LICENSE.txt for license information.5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception6//7//===----------------------------------------------------------------------===//8 9#include "lldb/Interpreter/OptionValueProperties.h"10 11#include "lldb/Utility/Flags.h"12 13#include "lldb/Core/UserSettingsController.h"14#include "lldb/Interpreter/OptionValues.h"15#include "lldb/Interpreter/Property.h"16#include "lldb/Utility/Args.h"17#include "lldb/Utility/Stream.h"18#include "lldb/Utility/StringList.h"19 20using namespace lldb;21using namespace lldb_private;22 23OptionValueProperties::OptionValueProperties(llvm::StringRef name)24    : m_name(name.str()) {}25 26void OptionValueProperties::Initialize(const PropertyDefinitions &defs) {27  for (const auto &definition : defs) {28    Property property(definition);29    assert(property.IsValid());30    m_name_to_index.insert({property.GetName(), m_properties.size()});31    property.GetValue()->SetParent(shared_from_this());32    m_properties.push_back(property);33  }34}35 36void OptionValueProperties::SetValueChangedCallback(37    size_t property_idx, std::function<void()> callback) {38  Property *property = ProtectedGetPropertyAtIndex(property_idx);39  if (property)40    property->SetValueChangedCallback(std::move(callback));41}42 43void OptionValueProperties::AppendProperty(llvm::StringRef name,44                                           llvm::StringRef desc, bool is_global,45                                           const OptionValueSP &value_sp) {46  Property property(name, desc, is_global, value_sp);47  m_name_to_index.insert({name, m_properties.size()});48  m_properties.push_back(property);49  value_sp->SetParent(shared_from_this());50}51 52lldb::OptionValueSP53OptionValueProperties::GetValueForKey(const ExecutionContext *exe_ctx,54                                      llvm::StringRef key) const {55  auto iter = m_name_to_index.find(key);56  if (iter == m_name_to_index.end())57    return OptionValueSP();58  const size_t idx = iter->second;59  if (idx >= m_properties.size())60    return OptionValueSP();61  return GetPropertyAtIndex(idx, exe_ctx)->GetValue();62}63 64lldb::OptionValueSP65OptionValueProperties::GetSubValue(const ExecutionContext *exe_ctx,66                                   llvm::StringRef name, Status &error) const {67  lldb::OptionValueSP value_sp;68  if (name.empty())69    return OptionValueSP();70 71  llvm::StringRef sub_name;72  llvm::StringRef key;73  size_t key_len = name.find_first_of(".[{");74  if (key_len != llvm::StringRef::npos) {75    key = name.take_front(key_len);76    sub_name = name.drop_front(key_len);77  } else78    key = name;79 80  value_sp = GetValueForKey(exe_ctx, key);81  if (sub_name.empty() || !value_sp)82    return value_sp;83 84  switch (sub_name[0]) {85  case '.': {86    lldb::OptionValueSP return_val_sp;87    return_val_sp =88        value_sp->GetSubValue(exe_ctx, sub_name.drop_front(), error);89    if (!return_val_sp) {90      if (Properties::IsSettingExperimental(sub_name.drop_front())) {91        const size_t experimental_len =92            Properties::GetExperimentalSettingsName().size();93        if (sub_name[experimental_len + 1] == '.')94          return_val_sp = value_sp->GetSubValue(95              exe_ctx, sub_name.drop_front(experimental_len + 2), error);96        // It isn't an error if an experimental setting is not present.97        if (!return_val_sp)98          error.Clear();99      }100    }101    return return_val_sp;102  }103  case '[':104    // Array or dictionary access for subvalues like: "[12]"       -- access105    // 12th array element "['hello']"  -- dictionary access of key named hello106    return value_sp->GetSubValue(exe_ctx, sub_name, error);107 108  default:109    value_sp.reset();110    break;111  }112  return value_sp;113}114 115Status OptionValueProperties::SetSubValue(const ExecutionContext *exe_ctx,116                                          VarSetOperationType op,117                                          llvm::StringRef name,118                                          llvm::StringRef value) {119  Status error;120  llvm::SmallVector<llvm::StringRef, 8> components;121  name.split(components, '.');122  bool name_contains_experimental = false;123  for (const auto &part : components)124    if (Properties::IsSettingExperimental(part))125      name_contains_experimental = true;126 127  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, name, error));128  if (value_sp)129    error = value_sp->SetValueFromString(value, op);130  else {131    // Don't set an error if the path contained .experimental. - those are132    // allowed to be missing and should silently fail.133    if (!name_contains_experimental && error.AsCString() == nullptr) {134      error = Status::FromErrorStringWithFormat("invalid value path '%s'",135                                                name.str().c_str());136    }137  }138  return error;139}140 141size_t OptionValueProperties::GetPropertyIndex(llvm::StringRef name) const {142  auto iter = m_name_to_index.find(name);143  if (iter == m_name_to_index.end())144    return SIZE_MAX;145  return iter->second;146}147 148const Property *149OptionValueProperties::GetProperty(llvm::StringRef name,150                                   const ExecutionContext *exe_ctx) const {151  auto iter = m_name_to_index.find(name);152  if (iter == m_name_to_index.end())153    return nullptr;154  return GetPropertyAtIndex(iter->second, exe_ctx);155}156 157lldb::OptionValueSP OptionValueProperties::GetPropertyValueAtIndex(158    size_t idx, const ExecutionContext *exe_ctx) const {159  const Property *setting = GetPropertyAtIndex(idx, exe_ctx);160  if (setting)161    return setting->GetValue();162  return OptionValueSP();163}164 165OptionValuePathMappings *166OptionValueProperties::GetPropertyAtIndexAsOptionValuePathMappings(167    size_t idx, const ExecutionContext *exe_ctx) const {168  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));169  if (value_sp)170    return value_sp->GetAsPathMappings();171  return nullptr;172}173 174OptionValueFileSpecList *175OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpecList(176    size_t idx, const ExecutionContext *exe_ctx) const {177  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));178  if (value_sp)179    return value_sp->GetAsFileSpecList();180  return nullptr;181}182 183bool OptionValueProperties::GetPropertyAtIndexAsArgs(184    size_t idx, Args &args, const ExecutionContext *exe_ctx) const {185  const Property *property = GetPropertyAtIndex(idx, exe_ctx);186  if (!property)187    return false;188 189  OptionValue *value = property->GetValue().get();190  if (!value)191    return false;192 193  const OptionValueArgs *arguments = value->GetAsArgs();194  if (arguments) {195    arguments->GetArgs(args);196    return true;197  }198 199  const OptionValueArray *array = value->GetAsArray();200  if (array) {201    array->GetArgs(args);202    return true;203  }204 205  const OptionValueDictionary *dict = value->GetAsDictionary();206  if (dict) {207    dict->GetArgs(args);208    return true;209  }210 211  return false;212}213 214bool OptionValueProperties::SetPropertyAtIndexFromArgs(215    size_t idx, const Args &args, const ExecutionContext *exe_ctx) {216  const Property *property = GetPropertyAtIndex(idx, exe_ctx);217  if (!property)218    return false;219 220  OptionValue *value = property->GetValue().get();221  if (!value)222    return false;223 224  OptionValueArgs *arguments = value->GetAsArgs();225  if (arguments)226    return arguments->SetArgs(args, eVarSetOperationAssign).Success();227 228  OptionValueArray *array = value->GetAsArray();229  if (array)230    return array->SetArgs(args, eVarSetOperationAssign).Success();231 232  OptionValueDictionary *dict = value->GetAsDictionary();233  if (dict)234    return dict->SetArgs(args, eVarSetOperationAssign).Success();235 236  return false;237}238 239OptionValueDictionary *240OptionValueProperties::GetPropertyAtIndexAsOptionValueDictionary(241    size_t idx, const ExecutionContext *exe_ctx) const {242  const Property *property = GetPropertyAtIndex(idx, exe_ctx);243  if (property)244    return property->GetValue()->GetAsDictionary();245  return nullptr;246}247 248OptionValueFileSpec *249OptionValueProperties::GetPropertyAtIndexAsOptionValueFileSpec(250    size_t idx, const ExecutionContext *exe_ctx) const {251  const Property *property = GetPropertyAtIndex(idx, exe_ctx);252  if (property) {253    OptionValue *value = property->GetValue().get();254    if (value)255      return value->GetAsFileSpec();256  }257  return nullptr;258}259 260OptionValueSInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueSInt64(261    size_t idx, const ExecutionContext *exe_ctx) const {262  const Property *property = GetPropertyAtIndex(idx, exe_ctx);263  if (property) {264    OptionValue *value = property->GetValue().get();265    if (value)266      return value->GetAsSInt64();267  }268  return nullptr;269}270 271OptionValueUInt64 *OptionValueProperties::GetPropertyAtIndexAsOptionValueUInt64(272    size_t idx, const ExecutionContext *exe_ctx) const {273  const Property *property = GetPropertyAtIndex(idx, exe_ctx);274  if (property) {275    OptionValue *value = property->GetValue().get();276    if (value)277      return value->GetAsUInt64();278  }279  return nullptr;280}281 282OptionValueString *OptionValueProperties::GetPropertyAtIndexAsOptionValueString(283    size_t idx, const ExecutionContext *exe_ctx) const {284  OptionValueSP value_sp(GetPropertyValueAtIndex(idx, exe_ctx));285  if (value_sp)286    return value_sp->GetAsString();287  return nullptr;288}289 290void OptionValueProperties::Clear() {291  const size_t num_properties = m_properties.size();292  for (size_t i = 0; i < num_properties; ++i)293    m_properties[i].GetValue()->Clear();294}295 296Status OptionValueProperties::SetValueFromString(llvm::StringRef value,297                                                 VarSetOperationType op) {298  Status error;299 300  //    Args args(value_cstr);301  //    const size_t argc = args.GetArgumentCount();302  switch (op) {303  case eVarSetOperationClear:304    Clear();305    break;306 307  case eVarSetOperationReplace:308  case eVarSetOperationAssign:309  case eVarSetOperationRemove:310  case eVarSetOperationInsertBefore:311  case eVarSetOperationInsertAfter:312  case eVarSetOperationAppend:313  case eVarSetOperationInvalid:314    error = OptionValue::SetValueFromString(value, op);315    break;316  }317 318  return error;319}320 321void OptionValueProperties::DumpValue(const ExecutionContext *exe_ctx,322                                      Stream &strm, uint32_t dump_mask) {323  const size_t num_properties = m_properties.size();324  for (size_t i = 0; i < num_properties; ++i) {325    const Property *property = GetPropertyAtIndex(i, exe_ctx);326    if (property) {327      OptionValue *option_value = property->GetValue().get();328      assert(option_value);329      const bool transparent_value = option_value->ValueIsTransparent();330      property->Dump(exe_ctx, strm, dump_mask);331      if (!transparent_value)332        strm.EOL();333    }334  }335}336 337llvm::json::Value338OptionValueProperties::ToJSON(const ExecutionContext *exe_ctx) const {339  llvm::json::Object json_properties;340  const size_t num_properties = m_properties.size();341  for (size_t i = 0; i < num_properties; ++i) {342    const Property *property = GetPropertyAtIndex(i, exe_ctx);343    if (property) {344      OptionValue *option_value = property->GetValue().get();345      assert(option_value);346      json_properties.try_emplace(property->GetName(),347                                  option_value->ToJSON(exe_ctx));348    }349  }350  return json_properties;351}352 353Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,354                                                Stream &strm,355                                                llvm::StringRef property_path,356                                                uint32_t dump_mask,357                                                bool is_json) {358  Status error;359  lldb::OptionValueSP value_sp(GetSubValue(exe_ctx, property_path, error));360  if (value_sp) {361    if (!value_sp->ValueIsTransparent()) {362      if (dump_mask & eDumpOptionName)363        strm.PutCString(property_path);364      if (dump_mask & ~eDumpOptionName)365        strm.PutChar(' ');366    }367    if (is_json) {368      strm.Printf(369          "%s",370          llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());371    } else372      value_sp->DumpValue(exe_ctx, strm, dump_mask);373  }374  return error;375}376 377OptionValuePropertiesSP378OptionValueProperties::CreateLocalCopy(const Properties &global_properties) {379  auto global_props_sp = global_properties.GetValueProperties();380  lldbassert(global_props_sp);381 382  auto copy_sp = global_props_sp->DeepCopy(global_props_sp->GetParent());383  return std::static_pointer_cast<OptionValueProperties>(copy_sp);384}385 386OptionValueSP387OptionValueProperties::DeepCopy(const OptionValueSP &new_parent) const {388  auto copy_sp = OptionValue::DeepCopy(new_parent);389  // copy_sp->GetAsProperties cannot be used here as it doesn't work for derived390  // types that override GetType returning a different value.391  auto *props_value_ptr = static_cast<OptionValueProperties *>(copy_sp.get());392  lldbassert(props_value_ptr);393 394  for (auto &property : props_value_ptr->m_properties) {395    // Duplicate any values that are not global when constructing properties396    // from a global copy.397    if (!property.IsGlobal()) {398      auto value_sp = property.GetValue()->DeepCopy(copy_sp);399      property.SetOptionValue(value_sp);400    }401  }402  return copy_sp;403}404 405const Property *406OptionValueProperties::GetPropertyAtPath(const ExecutionContext *exe_ctx,407                                         llvm::StringRef name) const {408  if (name.empty())409    return nullptr;410 411  const Property *property = nullptr;412  llvm::StringRef sub_name;413  llvm::StringRef key;414  size_t key_len = name.find_first_of(".[{");415 416  if (key_len != llvm::StringRef::npos) {417    key = name.take_front(key_len);418    sub_name = name.drop_front(key_len);419  } else420    key = name;421 422  property = GetProperty(key, exe_ctx);423  if (sub_name.empty() || !property)424    return property;425 426  if (sub_name[0] == '.') {427    OptionValueProperties *sub_properties =428        property->GetValue()->GetAsProperties();429    if (sub_properties)430      return sub_properties->GetPropertyAtPath(exe_ctx, sub_name.drop_front());431  }432  return nullptr;433}434 435void OptionValueProperties::DumpAllDescriptions(CommandInterpreter &interpreter,436                                                Stream &strm) const {437  size_t max_name_len = 0;438  const size_t num_properties = m_properties.size();439  for (size_t i = 0; i < num_properties; ++i) {440    const Property *property = ProtectedGetPropertyAtIndex(i);441    if (property)442      max_name_len = std::max<size_t>(property->GetName().size(), max_name_len);443  }444  for (size_t i = 0; i < num_properties; ++i) {445    const Property *property = ProtectedGetPropertyAtIndex(i);446    if (property)447      property->DumpDescription(interpreter, strm, max_name_len, false);448  }449}450 451void OptionValueProperties::Apropos(452    llvm::StringRef keyword,453    std::vector<const Property *> &matching_properties) const {454  const size_t num_properties = m_properties.size();455  StreamString strm;456  for (size_t i = 0; i < num_properties; ++i) {457    const Property *property = ProtectedGetPropertyAtIndex(i);458    if (property) {459      const OptionValueProperties *properties =460          property->GetValue()->GetAsProperties();461      if (properties) {462        properties->Apropos(keyword, matching_properties);463      } else {464        bool match = false;465        llvm::StringRef name = property->GetName();466        if (name.contains_insensitive(keyword))467          match = true;468        else {469          llvm::StringRef desc = property->GetDescription();470          if (desc.contains_insensitive(keyword))471            match = true;472        }473        if (match) {474          matching_properties.push_back(property);475        }476      }477    }478  }479}480 481lldb::OptionValuePropertiesSP482OptionValueProperties::GetSubProperty(const ExecutionContext *exe_ctx,483                                      llvm::StringRef name) {484  lldb::OptionValueSP option_value_sp(GetValueForKey(exe_ctx, name));485  if (option_value_sp) {486    OptionValueProperties *ov_properties = option_value_sp->GetAsProperties();487    if (ov_properties)488      return ov_properties->shared_from_this();489  }490  return lldb::OptionValuePropertiesSP();491}492