diff options
author | jimingham <jingham@apple.com> | 2024-07-03 10:39:34 -0700 |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-07-03 10:39:34 -0700 |
commit | 77d131eddb6ca9060c844fae9cb78779fa70c8f0 (patch) | |
tree | f540d78500a8a832a701db3e25b8a53dc91d0fac /lldb/source | |
parent | 94471e6d238acab291b5b652fc18f17c4815cc7d (diff) | |
download | llvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.zip llvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.tar.gz llvm-77d131eddb6ca9060c844fae9cb78779fa70c8f0.tar.bz2 |
Add the ability for Script based commands to specify their "repeat command" (#94823)
Among other things, returning an empty string as the repeat command
disables auto-repeat, which can be useful for state-changing commands.
There's one remaining refinement to this setup, which is that for parsed
script commands, it should be possible to change an option value, or add
a new option value that wasn't originally specified, then ask lldb "make
this back into a command string". That would make doing fancy things
with repeat commands easier.
That capability isn't present in the lldb_private side either, however.
So that's for a next iteration.
I haven't added this to the docs on adding commands yet. I wanted to
make sure this was an acceptable approach before I spend the time to do
that.
Diffstat (limited to 'lldb/source')
5 files changed, 66 insertions, 7 deletions
diff --git a/lldb/source/Commands/CommandObjectCommands.cpp b/lldb/source/Commands/CommandObjectCommands.cpp index f4903e3..c63445b 100644 --- a/lldb/source/Commands/CommandObjectCommands.cpp +++ b/lldb/source/Commands/CommandObjectCommands.cpp @@ -1142,6 +1142,15 @@ public: ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } + std::optional<std::string> GetRepeatCommand(Args &args, + uint32_t index) override { + ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); + if (!scripter) + return std::nullopt; + + return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); + } + llvm::StringRef GetHelp() override { if (m_fetched_help_short) return CommandObjectRaw::GetHelp(); @@ -1588,7 +1597,9 @@ private: options.ForEach(add_element); return error; } - + + size_t GetNumOptions() { return m_num_options; } + private: struct EnumValueStorage { EnumValueStorage() { @@ -1827,6 +1838,15 @@ public: ScriptedCommandSynchronicity GetSynchronicity() { return m_synchro; } + std::optional<std::string> GetRepeatCommand(Args &args, + uint32_t index) override { + ScriptInterpreter *scripter = GetDebugger().GetScriptInterpreter(); + if (!scripter) + return std::nullopt; + + return scripter->GetRepeatCommandForScriptedCommand(m_cmd_obj_sp, args); + } + llvm::StringRef GetHelp() override { if (m_fetched_help_short) return CommandObjectParsed::GetHelp(); @@ -1857,9 +1877,14 @@ public: SetHelpLong(docstring); return CommandObjectParsed::GetHelpLong(); } - - Options *GetOptions() override { return &m_options; } + Options *GetOptions() override { + // CommandObjectParsed requires that a command with no options return + // nullptr. + if (m_options.GetNumOptions() == 0) + return nullptr; + return &m_options; + } protected: void DoExecute(Args &args, diff --git a/lldb/source/Commands/CommandObjectThread.cpp b/lldb/source/Commands/CommandObjectThread.cpp index 5e64dd2..4398cf3 100644 --- a/lldb/source/Commands/CommandObjectThread.cpp +++ b/lldb/source/Commands/CommandObjectThread.cpp @@ -132,7 +132,7 @@ public: Options *GetOptions() override { return &m_options; } std::optional<std::string> GetRepeatCommand(Args ¤t_args, - uint32_t idx) override { + uint32_t index) override { llvm::StringRef count_opt("--count"); llvm::StringRef start_opt("--start"); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h index 95eb5a7..3026b61 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/SWIGPythonBridge.h @@ -206,6 +206,10 @@ public: lldb_private::CommandReturnObject &cmd_retobj, lldb::ExecutionContextRefSP exe_ctx_ref_sp); + static std::optional<std::string> + LLDBSwigPythonGetRepeatCommandForScriptedCommand(PyObject *implementor, + std::string &command); + static bool LLDBSwigPythonCallModuleInit(const char *python_module_name, const char *session_dictionary_name, lldb::DebuggerSP debugger); diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp index 70c9f94..70fa6d8 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPython.cpp @@ -2708,6 +2708,33 @@ bool ScriptInterpreterPythonImpl::RunScriptBasedParsedCommand( return ret_val; } +std::optional<std::string> +ScriptInterpreterPythonImpl::GetRepeatCommandForScriptedCommand( + StructuredData::GenericSP impl_obj_sp, Args &args) { + if (!impl_obj_sp || !impl_obj_sp->IsValid()) + return std::nullopt; + + lldb::DebuggerSP debugger_sp = m_debugger.shared_from_this(); + + if (!debugger_sp.get()) + return std::nullopt; + + std::optional<std::string> ret_val; + + { + Locker py_lock(this, Locker::AcquireLock | Locker::NoSTDIN, + Locker::FreeLock); + + StructuredData::ArraySP args_arr_sp(new StructuredData::Array()); + + // For scripting commands, we send the command string: + std::string command; + args.GetQuotedCommandString(command); + ret_val = SWIGBridge::LLDBSwigPythonGetRepeatCommandForScriptedCommand( + static_cast<PyObject *>(impl_obj_sp->GetValue()), command); + } + return ret_val; +} /// In Python, a special attribute __doc__ contains the docstring for an object /// (function, method, class, ...) if any is defined Otherwise, the attribute's diff --git a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h index fa23540..c2024ef 100644 --- a/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h +++ b/lldb/source/Plugins/ScriptInterpreter/Python/ScriptInterpreterPythonImpl.h @@ -160,13 +160,16 @@ public: lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override; - virtual bool RunScriptBasedParsedCommand( - StructuredData::GenericSP impl_obj_sp, Args& args, + bool RunScriptBasedParsedCommand( + StructuredData::GenericSP impl_obj_sp, Args &args, ScriptedCommandSynchronicity synchronicity, lldb_private::CommandReturnObject &cmd_retobj, Status &error, const lldb_private::ExecutionContext &exe_ctx) override; - + std::optional<std::string> + GetRepeatCommandForScriptedCommand(StructuredData::GenericSP impl_obj_sp, + Args &args) override; + Status GenerateFunction(const char *signature, const StringList &input, bool is_callback) override; |