https://github.com/medismailben created
https://github.com/llvm/llvm-project/pull/209400
This patch improves `scripting extension list` in three ways.
First, it groups the output by `ScriptedExtension`: instead of one row per
registered plugin instance, one entry per extension is printed with a combined
`Language` field.
Second, it colorizes and visually separates the output. Each entry is preceded
by a dimmed dashed separator; field labels are printed in bold green, the
extension name value in bold cyan as a mini-heading, and `None` usage values
are dimmed, all via the same `ansi::FormatAnsiTerminalCodes(..., use_color)`
idiom `Breakpoint::GetDescription` uses elsewhere, gracefully no-op when color
is disabled or unsupported. `ScriptedInterfaceUsages::Dump` takes an optional
`use_color` parameter so its own `API Usages:` / `Command Interpreter Usages:`
labels can match.
Third, it adds `-j`/`--json` to emit a JSON array of `{name, description,
languages, api_usages, command_interpreter_usages}` per extension, mirroring
`plugin list`'s existing `-j`. `DoExecute` now computes the extension grouping
once and branches into `OutputJsonFormat` or `OutputTextFormat`, sharing a
`GetLanguagesForExtension` helper. It also accepts optional positional
`<extension-name>` arguments to filter the listing to specific extensions
(matched via the same case-insensitive `ScriptInterpreter::StringToExtension`
used by `scripting extension generate`), with completion wired up via
`eScriptedExtensionCompletion`.
Also fix a latent lifetime bug in the shared language-collection helper so it
owns its `std::string` values instead of holding `StringRef`s to temporaries;
the JSON path made it observable.
>From 4ead739172a9485d428e9a08bd9739a3333af6a6 Mon Sep 17 00:00:00 2001
From: Med Ismail Bennani <[email protected]>
Date: Mon, 13 Jul 2026 13:57:32 -0700
Subject: [PATCH] [lldb/script] Improve `scripting extension list` output and
filtering
This patch improves `scripting extension list` in three ways.
First, it groups the output by `ScriptedExtension`: instead of one row
per registered plugin instance, one entry per extension is printed with
a combined `Language` field.
Second, it colorizes and visually separates the output. Each entry is
preceded by a dimmed dashed separator; field labels are printed in bold
green, the extension name value in bold cyan as a mini-heading, and
`None` usage values are dimmed, all via the same
`ansi::FormatAnsiTerminalCodes(..., use_color)` idiom
`Breakpoint::GetDescription` uses elsewhere, gracefully no-op when color
is disabled or unsupported. `ScriptedInterfaceUsages::Dump` takes an
optional `use_color` parameter so its own `API Usages:` /
`Command Interpreter Usages:` labels can match.
Third, it adds `-j`/`--json` to emit a JSON array of
`{name, description, languages, api_usages, command_interpreter_usages}`
per extension, mirroring `plugin list`'s existing `-j`. `DoExecute` now
computes the extension grouping once and branches into
`OutputJsonFormat` or `OutputTextFormat`, sharing a
`GetLanguagesForExtension` helper. It also accepts optional positional
`<extension-name>` arguments to filter the listing to specific
extensions (matched via the same case-insensitive
`ScriptInterpreter::StringToExtension` used by `scripting extension
generate`), with completion wired up via `eScriptedExtensionCompletion`.
Also fix a latent lifetime bug in the shared language-collection helper
so it owns its `std::string` values instead of holding `StringRef`s to
temporaries; the JSON path made it observable.
Signed-off-by: Med Ismail Bennani <[email protected]>
---
.../Interfaces/ScriptedInterfaceUsages.h | 2 +-
.../lldb/Interpreter/ScriptInterpreter.h | 5 +
.../Commands/CommandObjectScripting.cpp | 191 +++++++++++++++---
lldb/source/Commands/Options.td | 3 +
.../Interfaces/ScriptedInterfaceUsages.cpp | 14 +-
lldb/source/Interpreter/ScriptInterpreter.cpp | 45 +++++
.../command-scripting-extension-list.test | 101 ++++-----
7 files changed, 279 insertions(+), 82 deletions(-)
diff --git a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h
b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h
index d958e782d86bd..48f38eb70bdb3 100644
--- a/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h
+++ b/lldb/include/lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h
@@ -32,7 +32,7 @@ class ScriptedInterfaceUsages {
enum class UsageKind { CommandInterpreter, API };
- void Dump(Stream &s, UsageKind kind) const;
+ void Dump(Stream &s, UsageKind kind, bool use_color = false) const;
private:
std::vector<llvm::StringRef> m_command_interpreter_usages;
diff --git a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
index 7ab098f177a80..2b9cb8f7bb866 100644
--- a/lldb/include/lldb/Interpreter/ScriptInterpreter.h
+++ b/lldb/include/lldb/Interpreter/ScriptInterpreter.h
@@ -526,6 +526,11 @@ class ScriptInterpreter : public PluginInterface {
static lldb::ScriptLanguage StringToLanguage(const llvm::StringRef &string);
+ static llvm::StringLiteral
+ ExtensionToString(lldb::ScriptedExtension extension);
+
+ static lldb::ScriptedExtension StringToExtension(llvm::StringRef string);
+
lldb::ScriptLanguage GetLanguage() { return m_script_lang; }
virtual lldb::ScriptedProcessInterfaceUP CreateScriptedProcessInterface() {
diff --git a/lldb/source/Commands/CommandObjectScripting.cpp
b/lldb/source/Commands/CommandObjectScripting.cpp
index 21400a62d697f..851e501a714c8 100644
--- a/lldb/source/Commands/CommandObjectScripting.cpp
+++ b/lldb/source/Commands/CommandObjectScripting.cpp
@@ -18,8 +18,11 @@
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
#include "lldb/Interpreter/OptionArgParser.h"
#include "lldb/Interpreter/ScriptInterpreter.h"
+#include "lldb/Utility/AnsiTerminal.h"
#include "lldb/Utility/Args.h"
+#include "llvm/ADT/StringMap.h"
+
using namespace lldb;
using namespace lldb_private;
@@ -138,12 +141,23 @@ class CommandObjectScriptingExtensionList : public
CommandObjectParsed {
: CommandObjectParsed(
interpreter, "scripting extension list",
"List all the available scripting extension templates. ",
- "scripting template list [--language <scripting-language> --]") {}
+ "scripting extension list [--language <scripting-language> --] "
+ "[--json --] [<extension-name> ...]") {
+ AddSimpleArgumentList(eArgTypeScriptedExtension, eArgRepeatStar);
+ }
~CommandObjectScriptingExtensionList() override = default;
Options *GetOptions() override { return &m_options; }
+ void HandleArgumentCompletion(
+ CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), lldb::eScriptedExtensionCompletion, request,
+ nullptr);
+ }
+
class CommandOptions : public Options {
public:
CommandOptions() = default;
@@ -162,6 +176,9 @@ class CommandObjectScriptingExtensionList : public
CommandObjectParsed {
error = Status::FromErrorStringWithFormatv(
"unrecognized value for language '{0}'", option_arg);
break;
+ case 'j':
+ m_json_format = true;
+ break;
default:
llvm_unreachable("Unimplemented option");
}
@@ -171,6 +188,7 @@ class CommandObjectScriptingExtensionList : public
CommandObjectParsed {
void OptionParsingStarting(ExecutionContext *execution_context) override {
m_language = lldb::eScriptLanguageDefault;
+ m_json_format = false;
}
llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
@@ -178,53 +196,164 @@ class CommandObjectScriptingExtensionList : public
CommandObjectParsed {
}
lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
+ bool m_json_format = false;
};
protected:
void DoExecute(Args &command, CommandReturnObject &result) override {
- Stream &s = result.GetOutputStream();
- s.Printf("Available scripted extension templates:");
+ llvm::StringMap<std::vector<size_t>> grouped_by_extension;
+ for (size_t i = 0; i < PluginManager::GetNumScriptedInterfaces(); i++) {
+ lldb::ScriptedExtension extension =
+ PluginManager::GetScriptedInterfaceExtensionAtIndex(i);
+ if (extension == eScriptedExtensionInvalid)
+ continue;
+
+ llvm::StringLiteral extension_name =
+ ScriptInterpreter::ExtensionToString(extension);
+ if (grouped_by_extension.contains(extension_name))
+ grouped_by_extension[extension_name].push_back(i);
+ else
+ grouped_by_extension[extension_name] = {i};
+ }
- auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) {
- if (!value.empty()) {
- s.IndentMore();
- s.Indent();
- s << key << ": " << value << '\n';
- s.IndentLess();
+ if (command.GetArgumentCount() > 0) {
+ llvm::StringMap<std::vector<size_t>> filtered;
+ for (const Args::ArgEntry &arg : command.entries()) {
+ lldb::ScriptedExtension extension =
+ ScriptInterpreter::StringToExtension(arg.ref());
+ if (extension == eScriptedExtensionInvalid) {
+ result.AppendErrorWithFormat(
+ "no scripted extension named '%s'", arg.c_str());
+ return;
+ }
+ llvm::StringLiteral extension_name =
+ ScriptInterpreter::ExtensionToString(extension);
+ auto it = grouped_by_extension.find(extension_name);
+ if (it != grouped_by_extension.end())
+ filtered[extension_name] = it->second;
}
- };
+ grouped_by_extension = std::move(filtered);
+ }
- size_t num_listed_interface = 0;
- size_t num_extensions = PluginManager::GetNumScriptedInterfaces();
- for (size_t i = 0; i < num_extensions; i++) {
- llvm::StringRef plugin_name =
- PluginManager::GetScriptedInterfaceNameAtIndex(i);
- if (plugin_name.empty())
- break;
+ if (m_options.m_json_format)
+ OutputJsonFormat(grouped_by_extension, result);
+ else
+ OutputTextFormat(grouped_by_extension, result);
+ }
+private:
+ std::vector<std::string>
+ GetLanguagesForExtension(const std::vector<size_t> &indices) {
+ std::vector<std::string> languages;
+ for (const size_t idx : indices) {
lldb::ScriptLanguage lang =
- PluginManager::GetScriptedInterfaceLanguageAtIndex(i);
+ PluginManager::GetScriptedInterfaceLanguageAtIndex(idx);
if (lang != m_options.m_language)
continue;
+ languages.push_back(ScriptInterpreter::LanguageToString(lang));
+ }
+ return languages;
+ }
+
+ void
+ OutputJsonFormat(const llvm::StringMap<std::vector<size_t>>
&grouped_by_extension,
+ CommandReturnObject &result) {
+ llvm::json::Array extensions;
+ for (const auto &extension_pair : grouped_by_extension) {
+ llvm::StringRef desc =
+ PluginManager::GetScriptedInterfaceDescriptionAtIndex(
+ extension_pair.second[0]);
+ ScriptedInterfaceUsages usages =
+ PluginManager::GetScriptedInterfaceUsagesAtIndex(
+ extension_pair.second[0]);
+
+ // llvm::json::Value's StringRef constructor does not copy the
+ // underlying characters, so every string handed to the JSON structure
+ // below must be an owned std::string -- otherwise it dangles by the
+ // time the object tree is serialized at the end of this function.
+ llvm::json::Array languages;
+ for (const std::string &lang :
GetLanguagesForExtension(extension_pair.second))
+ languages.push_back(lang);
+
+ llvm::json::Array api_usages;
+ for (llvm::StringRef usage : usages.GetSBAPIUsages())
+ api_usages.push_back(usage.str());
+
+ llvm::json::Array cmd_usages;
+ for (llvm::StringRef usage : usages.GetCommandInterpreterUsages())
+ cmd_usages.push_back(usage.str());
+
+ extensions.push_back(llvm::json::Object{
+ {"name", extension_pair.first().str()},
+ {"description", desc.str()},
+ {"languages", std::move(languages)},
+ {"api_usages", std::move(api_usages)},
+ {"command_interpreter_usages", std::move(cmd_usages)},
+ });
+ }
+
+ std::string str;
+ llvm::raw_string_ostream os(str);
+ os << llvm::formatv("{0:2}", llvm::json::Value(std::move(extensions)));
+ result.AppendMessage(str);
+ result.SetStatus(eReturnStatusSuccessFinishResult);
+ }
+
+ void
+ OutputTextFormat(const llvm::StringMap<std::vector<size_t>>
&grouped_by_extension,
+ CommandReturnObject &result) {
+ Stream &s = result.GetOutputStream();
+ const bool use_color = s.AsRawOstream().colors_enabled();
+ auto ansi_code = [use_color](llvm::StringRef code) {
+ return ansi::FormatAnsiTerminalCodes(code, use_color);
+ };
+ const std::string label_color = ansi_code("${ansi.fg.green}${ansi.bold}");
+ const std::string name_color = ansi_code("${ansi.fg.cyan}${ansi.bold}");
+ const std::string sep_color = ansi_code("${ansi.faint}");
+ const std::string reset = ansi_code("${ansi.normal}");
+ const std::string separator(
+ std::min<uint64_t>(GetDebugger().GetTerminalWidth(), 80), '-');
- if (!num_listed_interface)
- s.EOL();
+ s.Printf("Available scripted extension templates:");
+ auto print_field = [&](llvm::StringRef key, llvm::StringRef value,
+ const std::string &value_color = std::string()) {
+ if (value.empty())
+ return;
+ s.IndentMore();
+ s.Indent();
+ s << label_color << key << ": " << reset;
+ if (!value_color.empty())
+ s << value_color << value << reset;
+ else
+ s << value;
+ s << '\n';
+ s.IndentLess();
+ };
+
+ size_t num_listed_interface = 0;
+ for (const auto &extension_pair : grouped_by_extension) {
num_listed_interface++;
+ s.EOL();
+ s << sep_color << separator << reset;
+ s.EOL();
+
llvm::StringRef desc =
- PluginManager::GetScriptedInterfaceDescriptionAtIndex(i);
+ PluginManager::GetScriptedInterfaceDescriptionAtIndex(
+ extension_pair.second[0]);
ScriptedInterfaceUsages usages =
- PluginManager::GetScriptedInterfaceUsagesAtIndex(i);
+ PluginManager::GetScriptedInterfaceUsagesAtIndex(
+ extension_pair.second[0]);
- print_field("Name", plugin_name);
- print_field("Language", ScriptInterpreter::LanguageToString(lang));
+ print_field("Name", extension_pair.first(), name_color);
print_field("Description", desc);
- usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API);
- usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter);
-
- if (i != num_extensions - 1)
- s.EOL();
+ print_field("Language",
+ llvm::join(GetLanguagesForExtension(extension_pair.second),
+ ""));
+ usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API, use_color);
+ usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter,
+ use_color);
}
if (!num_listed_interface)
@@ -261,8 +390,8 @@
CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
LoadSubCommand("run",
CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
LoadSubCommand("extension",
- CommandObjectSP(new CommandObjectMultiwordScriptingExtension(
- interpreter)));
+ CommandObjectSP(
+ new
CommandObjectMultiwordScriptingExtension(interpreter)));
}
CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;
diff --git a/lldb/source/Commands/Options.td b/lldb/source/Commands/Options.td
index 7e6e2c173d67f..bd6fa8efad0a5 100644
--- a/lldb/source/Commands/Options.td
+++ b/lldb/source/Commands/Options.td
@@ -1582,6 +1582,9 @@ let Command = "scripting extension list" in {
Desc<"Specify the scripting "
" language. If none is specified the default scripting language "
"is used.">;
+ def scripting_extension_list_json
+ : Option<"json", "j">,
+ Desc<"Output the scripted extension list in json format.">;
}
let Command = "source info" in {
diff --git a/lldb/source/Interpreter/Interfaces/ScriptedInterfaceUsages.cpp
b/lldb/source/Interpreter/Interfaces/ScriptedInterfaceUsages.cpp
index 05d7a5d852f8c..3fcbe20182960 100644
--- a/lldb/source/Interpreter/Interfaces/ScriptedInterfaceUsages.cpp
+++ b/lldb/source/Interpreter/Interfaces/ScriptedInterfaceUsages.cpp
@@ -8,20 +8,28 @@
#include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
+#include "lldb/Utility/AnsiTerminal.h"
+
using namespace lldb;
using namespace lldb_private;
-void ScriptedInterfaceUsages::Dump(Stream &s, UsageKind kind) const {
+void ScriptedInterfaceUsages::Dump(Stream &s, UsageKind kind,
+ bool use_color) const {
+ const std::string label =
+ ansi::FormatAnsiTerminalCodes("${ansi.fg.green}${ansi.bold}", use_color);
+ const std::string dim = ansi::FormatAnsiTerminalCodes("${ansi.faint}",
use_color);
+ const std::string reset = ansi::FormatAnsiTerminalCodes("${ansi.normal}",
use_color);
+
s.IndentMore();
s.Indent();
llvm::StringRef usage_kind =
(kind == UsageKind::CommandInterpreter) ? "Command Interpreter" : "API";
- s << usage_kind << " Usages:";
+ s << label << usage_kind << " Usages:" << reset;
const std::vector<llvm::StringRef> &usages =
(kind == UsageKind::CommandInterpreter) ? GetCommandInterpreterUsages()
: GetSBAPIUsages();
if (usages.empty())
- s << " None\n";
+ s << ' ' << dim << "None" << reset << '\n';
else if (usages.size() == 1)
s << " " << usages.front() << '\n';
else {
diff --git a/lldb/source/Interpreter/ScriptInterpreter.cpp
b/lldb/source/Interpreter/ScriptInterpreter.cpp
index 8dafb7f823e70..8420782b02814 100644
--- a/lldb/source/Interpreter/ScriptInterpreter.cpp
+++ b/lldb/source/Interpreter/ScriptInterpreter.cpp
@@ -16,6 +16,7 @@
#include "lldb/Utility/Stream.h"
#include "lldb/Utility/StringList.h"
#include "lldb/ValueObject/ValueObject.h"
+#include "llvm/ADT/StringSwitch.h"
#if defined(_WIN32)
#include "lldb/Host/windows/ConnectionGenericFileWindows.h"
#endif
@@ -188,6 +189,50 @@ ScriptInterpreter::StringToLanguage(const llvm::StringRef
&language) {
return eScriptLanguageUnknown;
}
+llvm::StringLiteral
+ScriptInterpreter::ExtensionToString(lldb::ScriptedExtension extension) {
+ switch (extension) {
+ case eScriptedExtensionInvalid:
+ return "Invalid";
+ case eScriptedExtensionOperatingSystem:
+ return "OperatingSystem";
+ case eScriptedExtensionScriptedPlatform:
+ return "ScriptedPlatform";
+ case eScriptedExtensionScriptedProcess:
+ return "ScriptedProcess";
+ case eScriptedExtensionScriptedBreakpointResolver:
+ return "ScriptedBreakpointResolver";
+ case eScriptedExtensionScriptedThreadPlan:
+ return "ScriptedThreadPlan";
+ case eScriptedExtensionScriptedFrameProvider:
+ return "ScriptedFrameProvider";
+ case eScriptedExtensionScriptedHook:
+ return "ScriptedHook";
+ case eScriptedExtensionScriptedThread:
+ return "ScriptedThread";
+ case eScriptedExtensionScriptedFrame:
+ return "ScriptedFrame";
+ }
+ llvm_unreachable("unhandled ScriptedExtension");
+}
+
+lldb::ScriptedExtension
+ScriptInterpreter::StringToExtension(llvm::StringRef string) {
+ return llvm::StringSwitch<lldb::ScriptedExtension>(string)
+ .CaseLower("OperatingSystem", eScriptedExtensionOperatingSystem)
+ .CaseLower("ScriptedPlatform", eScriptedExtensionScriptedPlatform)
+ .CaseLower("ScriptedProcess", eScriptedExtensionScriptedProcess)
+ .CaseLower("ScriptedBreakpointResolver",
+ eScriptedExtensionScriptedBreakpointResolver)
+ .CaseLower("ScriptedThreadPlan", eScriptedExtensionScriptedThreadPlan)
+ .CaseLower("ScriptedFrameProvider",
+ eScriptedExtensionScriptedFrameProvider)
+ .CaseLower("ScriptedHook", eScriptedExtensionScriptedHook)
+ .CaseLower("ScriptedThread", eScriptedExtensionScriptedThread)
+ .CaseLower("ScriptedFrame", eScriptedExtensionScriptedFrame)
+ .Default(eScriptedExtensionInvalid);
+}
+
Status ScriptInterpreter::SetBreakpointCommandCallback(
std::vector<std::reference_wrapper<BreakpointOptions>> &bp_options_vec,
const char *callback_text) {
diff --git a/lldb/test/Shell/Commands/command-scripting-extension-list.test
b/lldb/test/Shell/Commands/command-scripting-extension-list.test
index 8ca183a609671..880d4035516de 100644
--- a/lldb/test/Shell/Commands/command-scripting-extension-list.test
+++ b/lldb/test/Shell/Commands/command-scripting-extension-list.test
@@ -2,53 +2,60 @@
# RUN: %lldb -s %s -o exit | FileCheck %s
scripting extension list
-# CHECK:Available scripted extension templates:
-
-# CHECK: Name: OperatingSystemPythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Mock thread state
-# CHECK-NEXT: API Usages: None
-# CHECK-NEXT: Command Interpreter Usages:
-# CHECK-NEXT: settings set target.process.python-os-plugin-path
<script-path>
-# CHECK-NEXT: settings set
process.experimental.os-plugin-reports-all-threads [0/1]
-
-# CHECK: Name: ScriptedPlatformPythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Mock platform and interact with its processes.
-# CHECK-NEXT: API Usages: None
-# CHECK-NEXT: Command Interpreter Usages: None
-
-# CHECK: Name: ScriptedProcessPythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Mock process state
-# CHECK-NEXT: API Usages:
-# CHECK-NEXT: SBAttachInfo.SetScriptedProcessClassName
-# CHECK-NEXT: SBAttachInfo.SetScriptedProcessDictionary
-# CHECK-NEXT: SBTarget.Attach
-# CHECK-NEXT: SBLaunchInfo.SetScriptedProcessClassName
-# CHECK-NEXT: SBLaunchInfo.SetScriptedProcessDictionary
-# CHECK-NEXT: SBTarget.Launch
-# CHECK-NEXT: Command Interpreter Usages:
-# CHECK-NEXT: process attach -C <script-name> [-k key -v value ...]
-# CHECK-NEXT: process launch -C <script-name> [-k key -v value ...]
-
-# CHECK: Name: ScriptedThreadPlanPythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Alter thread stepping logic and stop reason
-# CHECK-NEXT: API Usages: SBThread.StepUsingScriptedThreadPlan
-# CHECK-NEXT: Command Interpreter Usages: thread step-scripted -C
<script-name> [-k key -v value ...]
-
-# CHECK: Name: ScriptedThreadPythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Provide thread state for a scripted process.
-# CHECK-NEXT: API Usages: None
-# CHECK-NEXT: Command Interpreter Usages: None
-
-# CHECK: Name: ScriptedFramePythonInterface
-# CHECK-NEXT: Language: Python
-# CHECK-NEXT: Description: Provide frame state for scripted threads and frame
providers.
-# CHECK-NEXT: API Usages: None
-# CHECK-NEXT: Command Interpreter Usages: None
+# CHECK: Available scripted extension templates:
+
+# The extensions are grouped by lldb::ScriptedExtension in a hash map, so
+# groups are not printed in a fixed order across builds. Match each group's
+# fields with CHECK-DAG instead of CHECK-NEXT.
+# CHECK-DAG: Name: OperatingSystem
+# CHECK-DAG: Language: Python
+# CHECK-DAG: Description: Mock thread state
+# CHECK-DAG: settings set target.process.python-os-plugin-path <script-path>
+# CHECK-DAG: settings set process.experimental.os-plugin-reports-all-threads
[0/1]
+
+# CHECK-DAG: Name: ScriptedPlatform
+# CHECK-DAG: Description: Mock platform and interact with its processes.
+
+# CHECK-DAG: Name: ScriptedProcess
+# CHECK-DAG: Description: Mock process state
+# CHECK-DAG: SBAttachInfo.SetScriptedProcessClassName
+# CHECK-DAG: SBAttachInfo.SetScriptedProcessDictionary
+# CHECK-DAG: SBTarget.Attach
+# CHECK-DAG: SBLaunchInfo.SetScriptedProcessClassName
+# CHECK-DAG: SBLaunchInfo.SetScriptedProcessDictionary
+# CHECK-DAG: SBTarget.Launch
+# CHECK-DAG: process attach -C <script-name> [-k key -v value ...]
+# CHECK-DAG: process launch -C <script-name> [-k key -v value ...]
+
+# CHECK-DAG: Name: ScriptedThreadPlan
+# CHECK-DAG: Description: Alter thread stepping logic and stop reason
+# CHECK-DAG: SBThread.StepUsingScriptedThreadPlan
+# CHECK-DAG: thread step-scripted -C <script-name> [-k key -v value ...]
+
+# CHECK-DAG: Name: ScriptedBreakpointResolver
+# CHECK-DAG: Description: Create a breakpoint that chooses locations based on
user-created callbacks
+# CHECK-DAG: SBTarget.BreakpointCreateFromScript
+# CHECK-DAG: breakpoint set -P classname [-k key -v value ...]
+
+# CHECK-DAG: Name: ScriptedFrameProvider
+# CHECK-DAG: Description: Provide scripted stack frames for threads
+# CHECK-DAG: SBTarget.RegisterScriptedFrameProvider
+# CHECK-DAG: SBTarget.RemoveScriptedFrameProvider
+# CHECK-DAG: SBTarget.ClearScriptedFrameProvider
+# CHECK-DAG: target frame-provider register -C <script-name> [-k key -v value
...]
+# CHECK-DAG: target frame-provider list
+# CHECK-DAG: target frame-provider remove <provider-name>
+# CHECK-DAG: target frame-provider clear
+
+# CHECK-DAG: Name: ScriptedHook
+# CHECK-DAG: Description: Perform actions on target lifecycle events (module
load/unload, process stop).
+# CHECK-DAG: target hook add -P <script-name> [-k key -v value ...]
+
+# CHECK-DAG: Name: ScriptedThread
+# CHECK-DAG: Description: Provide thread state for a scripted process.
+
+# CHECK-DAG: Name: ScriptedFrame
+# CHECK-DAG: Description: Provide frame state for scripted threads and frame
providers.
scripting extension list -l lua
# CHECK: Available scripted extension templates: None
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits