LLDB mainline
ScriptedSyntheticChildrenPythonInterface.cpp
Go to the documentation of this file.
1//===----------------------------------------------------------------------===//
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-exception
6//
7//===----------------------------------------------------------------------===//
8
9#include "../lldb-python.h"
10
15
16#include "../SWIGPythonBridge.h"
19
20using namespace lldb;
21using namespace lldb_private;
22using namespace lldb_private::python;
24
30
31llvm::Expected<StructuredData::GenericSP>
33 llvm::StringRef class_name, ValueObject &backend) {
34 if (class_name.empty())
35 return llvm::createStringError("empty class name");
36
37 ValueObjectSP valobj_sp = backend.GetSP();
38 if (!valobj_sp)
39 return llvm::createStringError("invalid backing value");
40
41 Locker py_lock(&m_interpreter,
44
45 // Hand the provider's __init__ a fresh SBValue view of the backing value
46 // with synthetic children disabled, so introspecting it doesn't recursively
47 // re-enter this provider. `SetPreferSyntheticValue` lives on the SBValue's
48 // ValueImpl, so this override doesn't affect the caller's original view.
49 PythonObject val_arg =
50 SWIGBridge::ToSWIGWrapper(valobj_sp, /*use_synthetic=*/false);
51
52 ScriptedMetadata scripted_metadata(class_name,
55 scripted_metadata, /*script_obj=*/nullptr, std::move(val_arg));
56}
57
58llvm::Expected<uint32_t>
60 // This interface requires no abstract methods, so a provider that doesn't
61 // implement `num_children` simply has no children rather than being broken.
62 llvm::Expected<std::optional<StructuredData::ObjectSP>> obj_or_err =
63 DispatchToOptional("num_children", max);
64 if (!obj_or_err)
65 return obj_or_err.takeError();
66
67 StructuredData::ObjectSP obj = obj_or_err->value_or(nullptr);
68 if (!obj || !obj->IsValid())
69 return 0;
70 // Cap at max in case the provider ignores the argument (e.g. defines
71 // `num_children(self)`) and returns an unbounded count.
72 return std::min<uint32_t>(obj->GetUnsignedIntegerValue(), max);
73}
74
77 return LogAndDefault(Dispatch<lldb::ValueObjectSP>("get_child_at_index", idx),
78 LLVM_PRETTY_FUNCTION);
79}
80
81llvm::Expected<uint32_t>
83 llvm::StringRef name) {
84 // A provider without `get_child_index` has no child of that name, which is
85 // a friendlier answer than "the method is missing".
86 std::string name_dispatch_storage = name.str();
87 llvm::Expected<std::optional<StructuredData::ObjectSP>> obj_or_err =
88 DispatchToOptional("get_child_index", name_dispatch_storage.c_str());
89 if (!obj_or_err)
90 return obj_or_err.takeError();
91
92 StructuredData::ObjectSP obj = obj_or_err->value_or(nullptr);
93 if (!obj || !obj->IsValid())
94 return llvm::createStringErrorV("type has no child named '{0}'", name);
95
96 // `CreateStructuredObject` only produces a `SignedInteger` for values that
97 // don't fit as unsigned, i.e. negative ones; a non-negative index comes
98 // back as `UnsignedInteger` instead, so check the sign this way rather
99 // than via `GetSignedIntegerValue`, which would misread every valid index.
100 if (obj->GetAsSignedInteger())
101 return llvm::createStringErrorV("type has no child named '{0}'", name);
102 return static_cast<uint32_t>(obj->GetUnsignedIntegerValue());
103}
104
106 // update() is optional; a missing method means "always refetch".
108 LogAndDefault(Dispatch("update"), LLVM_PRETTY_FUNCTION);
109 if (!obj)
110 return lldb::eRefetch;
111 return obj->GetBooleanValue() ? lldb::eReuse : lldb::eRefetch;
112}
113
115 // has_children() is optional and defaults to True when missing.
117 LogAndDefault(Dispatch("has_children"), LLVM_PRETTY_FUNCTION);
118 if (!obj)
119 return true;
120 return obj->GetBooleanValue();
121}
122
128
131 LogAndDefault(Dispatch("get_type_name"), LLVM_PRETTY_FUNCTION);
132 if (!obj)
133 return {};
134
135 return ConstString(obj->GetStringValue());
136}
137
139 const std::vector<llvm::StringRef> ci_usages = {
140 "type synthetic add -l <ClassName> <TypeName>"};
141 const std::vector<llvm::StringRef> api_usages = {
142 "SBTypeSynthetic.CreateWithClassName"};
145 "Provide synthetic children for a type, used by 'type synthetic add -l'",
147 eScriptLanguagePython, {ci_usages, api_usages});
148}
149
ScriptInterpreterPythonImpl::Locker Locker
A uniqued constant string class.
Definition ConstString.h:40
static bool RegisterPlugin(llvm::StringRef name, llvm::StringRef description, ABICreateInstance create_callback)
static bool UnregisterPlugin(ABICreateInstance create_callback)
static bool CreateInstance(lldb::ScriptLanguage language, ScriptedInterfaceUsages usages)
static T LogAndDefault(llvm::Expected< T > value_or_err, llvm::StringRef caller)
Log the failure in value_or_err and fall back to a default-constructed T.
ScriptedPythonInterface(ScriptInterpreterPythonImpl &interpreter)
llvm::Expected< T > Dispatch(llvm::StringRef method_name, Args &&...args)
Call method_name on the scripted object.
llvm::Expected< std::optional< T > > DispatchToOptional(llvm::StringRef method_name, Args &&...args)
Call an optional method_name, reporting "the script doesn't implementit" as std::nullopt rather than ...
llvm::Expected< StructuredData::GenericSP > CreatePluginObject(const ScriptedMetadata &scripted_metadata, StructuredData::Generic *script_obj, Args... args)
llvm::Expected< StructuredData::GenericSP > CreatePluginObject(llvm::StringRef class_name, ValueObject &backend) override
llvm::Expected< uint32_t > GetIndexOfChildWithName(llvm::StringRef name) override
std::shared_ptr< Dictionary > DictionarySP
std::shared_ptr< Object > ObjectSP
lldb::ValueObjectSP GetSP()
static PythonObject ToSWIGWrapper(std::unique_ptr< lldb::SBValue > value_sb)
A class that represents a running process on the host machine.
@ eScriptLanguagePython
@ eScriptedExtensionScriptedSyntheticChildren
ChildCacheState
Specifies if children need to be re-computed after a call to SyntheticChildrenFrontEnd::Update.
@ eRefetch
Children need to be recomputed dynamically.
@ eReuse
Children did not change and don't need to be recomputed; re-use what we computed the last time we cal...
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP