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 ConstString 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 llvm::Expected<std::optional<StructuredData::ObjectSP>> obj_or_err =
87 DispatchToOptional("get_child_index", name.GetCString());
88 if (!obj_or_err)
89 return obj_or_err.takeError();
90
91 StructuredData::ObjectSP obj = obj_or_err->value_or(nullptr);
92 if (!obj || !obj->IsValid())
93 return llvm::createStringErrorV("type has no child named '{0}'", name);
94
95 // `CreateStructuredObject` only produces a `SignedInteger` for values that
96 // don't fit as unsigned, i.e. negative ones; a non-negative index comes
97 // back as `UnsignedInteger` instead, so check the sign this way rather
98 // than via `GetSignedIntegerValue`, which would misread every valid index.
99 if (obj->GetAsSignedInteger())
100 return llvm::createStringErrorV("type has no child named '{0}'", name);
101 return static_cast<uint32_t>(obj->GetUnsignedIntegerValue());
102}
103
105 // update() is optional; a missing method means "always refetch".
107 LogAndDefault(Dispatch("update"), LLVM_PRETTY_FUNCTION);
108 if (!obj)
109 return lldb::eRefetch;
110 return obj->GetBooleanValue() ? lldb::eReuse : lldb::eRefetch;
111}
112
114 // has_children() is optional and defaults to True when missing.
116 LogAndDefault(Dispatch("has_children"), LLVM_PRETTY_FUNCTION);
117 if (!obj)
118 return true;
119 return obj->GetBooleanValue();
120}
121
127
130 LogAndDefault(Dispatch("get_type_name"), LLVM_PRETTY_FUNCTION);
131 if (!obj)
132 return {};
133
134 return ConstString(obj->GetStringValue());
135}
136
138 const std::vector<llvm::StringRef> ci_usages = {
139 "type synthetic add -l <ClassName> <TypeName>"};
140 const std::vector<llvm::StringRef> api_usages = {
141 "SBTypeSynthetic.CreateWithClassName"};
144 "Provide synthetic children for a type, used by 'type synthetic add -l'",
146 eScriptLanguagePython, {ci_usages, api_usages});
147}
148
ScriptInterpreterPythonImpl::Locker Locker
A uniqued constant string class.
Definition ConstString.h:40
const char * GetCString() const
Get the string value as a C string.
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)
ScriptInterpreterPythonImpl & m_interpreter
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(ConstString 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