[NFC][Coroutines] Use structured binding with llvm::enumerate in CoroSplit (#116879)
[llvm-project.git] / lldb / source / Commands / CommandObjectScripting.cpp
blob1f8ee0a9554ec12916f6faa4777da41885fe02a2
1 //===-- CommandObjectScripting.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-exception
6 //
7 //===----------------------------------------------------------------------===//
9 #include "CommandObjectScripting.h"
10 #include "lldb/Core/Debugger.h"
11 #include "lldb/Core/PluginManager.h"
12 #include "lldb/DataFormatters/DataVisualization.h"
13 #include "lldb/Host/Config.h"
14 #include "lldb/Host/OptionParser.h"
15 #include "lldb/Interpreter/CommandInterpreter.h"
16 #include "lldb/Interpreter/CommandOptionArgumentTable.h"
17 #include "lldb/Interpreter/CommandReturnObject.h"
18 #include "lldb/Interpreter/Interfaces/ScriptedInterfaceUsages.h"
19 #include "lldb/Interpreter/OptionArgParser.h"
20 #include "lldb/Interpreter/ScriptInterpreter.h"
21 #include "lldb/Utility/Args.h"
23 using namespace lldb;
24 using namespace lldb_private;
26 #define LLDB_OPTIONS_scripting_run
27 #include "CommandOptions.inc"
29 class CommandObjectScriptingRun : public CommandObjectRaw {
30 public:
31 CommandObjectScriptingRun(CommandInterpreter &interpreter)
32 : CommandObjectRaw(
33 interpreter, "scripting run",
34 "Invoke the script interpreter with provided code and display any "
35 "results. Start the interactive interpreter if no code is "
36 "supplied.",
37 "scripting run [--language <scripting-language> --] "
38 "[<script-code>]") {}
40 ~CommandObjectScriptingRun() override = default;
42 Options *GetOptions() override { return &m_options; }
44 class CommandOptions : public Options {
45 public:
46 CommandOptions() = default;
47 ~CommandOptions() override = default;
48 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
49 ExecutionContext *execution_context) override {
50 Status error;
51 const int short_option = m_getopt_table[option_idx].val;
53 switch (short_option) {
54 case 'l':
55 language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
56 option_arg, GetDefinitions()[option_idx].enum_values,
57 eScriptLanguageNone, error);
58 if (!error.Success())
59 error = Status::FromErrorStringWithFormat(
60 "unrecognized value for language '%s'", option_arg.str().c_str());
61 break;
62 default:
63 llvm_unreachable("Unimplemented option");
66 return error;
69 void OptionParsingStarting(ExecutionContext *execution_context) override {
70 language = lldb::eScriptLanguageNone;
73 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
74 return llvm::ArrayRef(g_scripting_run_options);
77 lldb::ScriptLanguage language = lldb::eScriptLanguageNone;
80 protected:
81 void DoExecute(llvm::StringRef command,
82 CommandReturnObject &result) override {
83 // Try parsing the language option but when the command contains a raw part
84 // separated by the -- delimiter.
85 OptionsWithRaw raw_args(command);
86 if (raw_args.HasArgs()) {
87 if (!ParseOptions(raw_args.GetArgs(), result))
88 return;
89 command = raw_args.GetRawPart();
92 lldb::ScriptLanguage language =
93 (m_options.language == lldb::eScriptLanguageNone)
94 ? m_interpreter.GetDebugger().GetScriptLanguage()
95 : m_options.language;
97 if (language == lldb::eScriptLanguageNone) {
98 result.AppendError(
99 "the script-lang setting is set to none - scripting not available");
100 return;
103 ScriptInterpreter *script_interpreter =
104 GetDebugger().GetScriptInterpreter(true, language);
106 if (script_interpreter == nullptr) {
107 result.AppendError("no script interpreter");
108 return;
111 // Script might change Python code we use for formatting. Make sure we keep
112 // up to date with it.
113 DataVisualization::ForceUpdate();
115 if (command.empty()) {
116 script_interpreter->ExecuteInterpreterLoop();
117 result.SetStatus(eReturnStatusSuccessFinishNoResult);
118 return;
121 // We can do better when reporting the status of one-liner script execution.
122 if (script_interpreter->ExecuteOneLine(command, &result))
123 result.SetStatus(eReturnStatusSuccessFinishNoResult);
124 else
125 result.SetStatus(eReturnStatusFailed);
128 private:
129 CommandOptions m_options;
132 #define LLDB_OPTIONS_scripting_extension_list
133 #include "CommandOptions.inc"
135 class CommandObjectScriptingExtensionList : public CommandObjectParsed {
136 public:
137 CommandObjectScriptingExtensionList(CommandInterpreter &interpreter)
138 : CommandObjectParsed(
139 interpreter, "scripting extension list",
140 "List all the available scripting extension templates. ",
141 "scripting template list [--language <scripting-language> --]") {}
143 ~CommandObjectScriptingExtensionList() override = default;
145 Options *GetOptions() override { return &m_options; }
147 class CommandOptions : public Options {
148 public:
149 CommandOptions() = default;
150 ~CommandOptions() override = default;
151 Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
152 ExecutionContext *execution_context) override {
153 Status error;
154 const int short_option = m_getopt_table[option_idx].val;
156 switch (short_option) {
157 case 'l':
158 m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
159 option_arg, GetDefinitions()[option_idx].enum_values,
160 eScriptLanguageNone, error);
161 if (!error.Success())
162 error = Status::FromErrorStringWithFormatv(
163 "unrecognized value for language '{0}'", option_arg);
164 break;
165 default:
166 llvm_unreachable("Unimplemented option");
169 return error;
172 void OptionParsingStarting(ExecutionContext *execution_context) override {
173 m_language = lldb::eScriptLanguageDefault;
176 llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
177 return llvm::ArrayRef(g_scripting_extension_list_options);
180 lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
183 protected:
184 void DoExecute(Args &command, CommandReturnObject &result) override {
185 Stream &s = result.GetOutputStream();
186 s.Printf("Available scripted extension templates:");
188 auto print_field = [&s](llvm::StringRef key, llvm::StringRef value) {
189 if (!value.empty()) {
190 s.IndentMore();
191 s.Indent();
192 s << key << ": " << value << '\n';
193 s.IndentLess();
197 size_t num_listed_interface = 0;
198 size_t num_extensions = PluginManager::GetNumScriptedInterfaces();
199 for (size_t i = 0; i < num_extensions; i++) {
200 llvm::StringRef plugin_name =
201 PluginManager::GetScriptedInterfaceNameAtIndex(i);
202 if (plugin_name.empty())
203 break;
205 lldb::ScriptLanguage lang =
206 PluginManager::GetScriptedInterfaceLanguageAtIndex(i);
207 if (lang != m_options.m_language)
208 continue;
210 if (!num_listed_interface)
211 s.EOL();
213 num_listed_interface++;
215 llvm::StringRef desc =
216 PluginManager::GetScriptedInterfaceDescriptionAtIndex(i);
217 ScriptedInterfaceUsages usages =
218 PluginManager::GetScriptedInterfaceUsagesAtIndex(i);
220 print_field("Name", plugin_name);
221 print_field("Language", ScriptInterpreter::LanguageToString(lang));
222 print_field("Description", desc);
223 usages.Dump(s, ScriptedInterfaceUsages::UsageKind::API);
224 usages.Dump(s, ScriptedInterfaceUsages::UsageKind::CommandInterpreter);
226 if (i != num_extensions - 1)
227 s.EOL();
230 if (!num_listed_interface)
231 s << " None\n";
234 private:
235 CommandOptions m_options;
238 class CommandObjectMultiwordScriptingExtension : public CommandObjectMultiword {
239 public:
240 CommandObjectMultiwordScriptingExtension(CommandInterpreter &interpreter)
241 : CommandObjectMultiword(
242 interpreter, "scripting extension",
243 "Commands for operating on the scripting extensions.",
244 "scripting extension [<subcommand-options>]") {
245 LoadSubCommand(
246 "list",
247 CommandObjectSP(new CommandObjectScriptingExtensionList(interpreter)));
250 ~CommandObjectMultiwordScriptingExtension() override = default;
253 CommandObjectMultiwordScripting::CommandObjectMultiwordScripting(
254 CommandInterpreter &interpreter)
255 : CommandObjectMultiword(
256 interpreter, "scripting",
257 "Commands for operating on the scripting functionalities.",
258 "scripting <subcommand> [<subcommand-options>]") {
259 LoadSubCommand("run",
260 CommandObjectSP(new CommandObjectScriptingRun(interpreter)));
261 LoadSubCommand("extension",
262 CommandObjectSP(new CommandObjectMultiwordScriptingExtension(
263 interpreter)));
266 CommandObjectMultiwordScripting::~CommandObjectMultiwordScripting() = default;