================
@@ -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

Reply via email to