================
@@ -371,6 +371,191 @@ class CommandObjectScriptingExtensionList : public
CommandObjectParsed {
CommandOptions m_options;
};
+#define LLDB_OPTIONS_scripting_extension_generate
+#include "CommandOptions.inc"
+
+class CommandObjectScriptingExtensionGenerate : public CommandObjectParsed {
+public:
+ CommandObjectScriptingExtensionGenerate(CommandInterpreter &interpreter)
+ : CommandObjectParsed(interpreter, "scripting extension generate",
+ "Generate a scripting extension template. ",
+ "scripting extension generate") {
+ AddSimpleArgumentList(eArgTypeScriptedExtension, eArgRepeatPlus);
+ }
+
+ ~CommandObjectScriptingExtensionGenerate() override = default;
+
+ Options *GetOptions() override { return &m_options; }
+
+ class CommandOptions : public Options {
+ public:
+ CommandOptions() = default;
+ ~CommandOptions() override = default;
+ Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+ ExecutionContext *execution_context) override {
+ Status error;
+ const char short_option =
+ g_scripting_extension_generate_options[option_idx].short_option;
+
+ switch (short_option) {
+ case 'a':
+ m_generate_non_abstract_methods = true;
+ break;
+ case 'l':
+ m_language = (lldb::ScriptLanguage)OptionArgParser::ToOptionEnum(
+ option_arg, GetDefinitions()[option_idx].enum_values,
+ eScriptLanguageNone, error);
+ if (!error.Success())
+ error = Status::FromErrorStringWithFormatv(
+ "unrecognized value for language '{0}'", option_arg);
+ break;
+ case 'n':
+ m_generated_class_prefix = option_arg.str();
+ break;
+ case 'o':
+ m_output_filepath = option_arg.str();
+ break;
+ case 'e': {
+ bool success;
+ m_open_editor = OptionArgParser::ToBoolean(option_arg, true, &success)
+ ? eLazyBoolYes
+ : eLazyBoolNo;
+ if (!success)
+ error = Status::FromErrorStringWithFormatv(
+ "invalid boolean value for -e: '{0}'", option_arg);
+ } break;
+ default:
+ llvm_unreachable("Unimplemented option");
+ }
+
+ return error;
+ }
+
+ void OptionParsingStarting(ExecutionContext *execution_context) override {
+ m_generate_non_abstract_methods = false;
+ m_language = lldb::eScriptLanguageDefault;
+ m_generated_class_prefix.clear();
+ m_output_filepath.clear();
+ m_open_editor = eLazyBoolCalculate;
+ }
+
+ llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+ return llvm::ArrayRef(g_scripting_extension_generate_options);
+ }
+
+ bool m_generate_non_abstract_methods = false;
+ lldb::ScriptLanguage m_language = lldb::eScriptLanguageDefault;
+ std::string m_generated_class_prefix;
+ std::string m_output_filepath;
+ LazyBool m_open_editor = eLazyBoolCalculate;
+ };
+
+ void
+ HandleArgumentCompletion(CompletionRequest &request,
+ OptionElementVector &opt_element_vector) override {
+ // If `-l <lang>` was already given, complete only extensions available
+ // in that language. Bare `-l` (no value yet) and any parse failures
+ // fall back to language-agnostic completion.
+ lldb::ScriptLanguage language = lldb::eScriptLanguageUnknown;
+ llvm::ArrayRef<OptionDefinition> defs = m_options.GetDefinitions();
+ for (const OptionArgElement &elem : opt_element_vector) {
+ if (elem.opt_defs_index < 0 ||
+ static_cast<size_t>(elem.opt_defs_index) >= defs.size())
+ continue;
+ if (defs[elem.opt_defs_index].short_option != 'l' ||
+ elem.opt_arg_pos <= 0)
+ continue;
+ llvm::StringRef value =
+ request.GetParsedLine().GetArgumentAtIndex(elem.opt_arg_pos);
+ Status error;
+ auto candidate =
+ static_cast<lldb::ScriptLanguage>(OptionArgParser::ToOptionEnum(
+ value, defs[elem.opt_defs_index].enum_values,
+ lldb::eScriptLanguageUnknown, error));
+ if (error.Success())
+ language = candidate;
+ break;
+ }
+ PluginManager::AutoCompleteScriptedExtension(
+ request.GetCursorArgumentPrefix(), request, language);
+ lldb_private::CommandCompletions::InvokeCommonCompletionCallbacks(
+ GetCommandInterpreter(), lldb::eDiskFileCompletion, request, nullptr);
+ }
+
+protected:
+ void DoExecute(Args &command, CommandReturnObject &result) override {
+ if (command.GetArgumentCount() == 0) {
+ result.SetError(
+ Status::FromErrorString("specify extension name to generate"));
+ return;
+ }
+
+ std::vector<std::pair<llvm::StringRef, llvm::SmallVector<llvm::StringRef>>>
+ name_import_pair;
+
+ for (size_t i = 0; i < command.GetArgumentCount(); i++) {
+ llvm::StringRef extension_name = command.GetArgumentAtIndex(i);
+ llvm::SmallVector<llvm::StringRef> extension_components;
+ extension_name.split(extension_components, ".");
+ lldb::ScriptedExtension extension =
+ ScriptInterpreter::StringToExtension(extension_components.back());
+ if (extension == eScriptedExtensionInvalid) {
+ result.SetError(Status::FromErrorStringWithFormatv(
+ "unknown scripted extension: '{0}'", extension_name));
+ return;
+ }
+ name_import_pair.push_back({extension_name, extension_components});
+ }
+
+ lldb::ScriptLanguage language =
+ (m_options.m_language == lldb::eScriptLanguageNone)
+ ? m_interpreter.GetDebugger().GetScriptLanguage()
+ : m_options.m_language;
+
+ if (language == lldb::eScriptLanguageNone) {
+ result.AppendError(
+ "the script-lang setting is set to none - scripting not available");
+ return;
+ }
+
+ ScriptInterpreter *script_interpreter =
+ GetDebugger().GetScriptInterpreter(true, language);
+
+ if (script_interpreter == nullptr) {
+ result.AppendError("no script interpreter");
+ return;
+ }
+
+ auto generated_file_or_err = script_interpreter->GenerateExtensionTemplate(
+ m_options.m_generated_class_prefix, name_import_pair,
+ m_options.m_generate_non_abstract_methods,
m_options.m_output_filepath);
+ if (!generated_file_or_err) {
+ result.SetError(generated_file_or_err.takeError());
+ return;
+ }
+
+ // `-e`/`--edit` decides whether to launch an external editor on the
+ // generated file. Defaults to true; pass `-e false` to skip.
----------------
JDevlieghere wrote:
Please cleanup the comments per the LLVM style guide. This isn't adding any
value.
https://github.com/llvm/llvm-project/pull/209647
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits