================
@@ -46,12 +48,287 @@ class CommandObjectPluginLoad : public CommandObjectParsed 
{
   }
 };
 
+namespace {
+// Helper function to perform an action on each matching plugin.
+// The action callback is given the containing namespace along with plugin info
+// for each matching plugin.
+static int ActOnMatchingPlugins(
+    const llvm::StringRef pattern,
+    std::function<void(const PluginNamespace &plugin_namespace,
+                       const std::vector<RegisteredPluginInfo> &plugin_info)>
+        action) {
+  int num_matching = 0;
+
+  for (const PluginNamespace &plugin_namespace :
+       PluginManager::GetPluginNamespaces()) {
+
+    std::vector<RegisteredPluginInfo> matching_plugins;
+    for (const RegisteredPluginInfo &plugin_info :
+         plugin_namespace.get_info()) {
+      if (PluginManager::MatchPluginName(pattern, plugin_namespace,
+                                         plugin_info))
+        matching_plugins.push_back(plugin_info);
+    }
+
+    if (!matching_plugins.empty()) {
+      num_matching += matching_plugins.size();
+      action(plugin_namespace, matching_plugins);
+    }
+  }
+
+  return num_matching;
+}
+
+// Call the "SetEnable" function for each matching plugins.
+// Used to share the majority of the code between the enable
+// and disable commands.
+int SetEnableOnMatchingPlugins(const llvm::StringRef &pattern,
+                               CommandReturnObject &result, bool enabled) {
+  return ActOnMatchingPlugins(
+      pattern, [&](const PluginNamespace &plugin_namespace,
+                   const std::vector<RegisteredPluginInfo> &plugins) {
+        result.AppendMessage(plugin_namespace.name);
+        for (const auto &plugin : plugins) {
+          if (!plugin_namespace.set_enabled(plugin.name, enabled)) {
+            result.AppendErrorWithFormat("failed to enable plugin %s.%s",
+                                         plugin_namespace.name.data(),
+                                         plugin.name.data());
+            continue;
+          }
+
+          result.AppendMessageWithFormat(
+              "  %s %-30s %s\n", enabled ? "[+]" : "[-]", plugin.name.data(),
+              plugin.description.data());
+        }
+      });
+}
+
+static std::string ConvertJSONToPrettyString(const llvm::json::Value &json) {
+  std::string str;
+  llvm::raw_string_ostream os(str);
+  os << llvm::formatv("{0:2}", json).str();
+  os.flush();
+  return str;
+}
+
+#define LLDB_OPTIONS_plugin_list
+#include "CommandOptions.inc"
+
+// These option definitions are used by the plugin list command.
+class PluginListCommandOptions : public Options {
+public:
+  PluginListCommandOptions() = default;
+
+  ~PluginListCommandOptions() override = default;
+
+  Status SetOptionValue(uint32_t option_idx, llvm::StringRef option_arg,
+                        ExecutionContext *execution_context) override {
+    Status error;
+    const int short_option = m_getopt_table[option_idx].val;
+
+    switch (short_option) {
+    case 'j':
+      m_json_format = true;
+      break;
+    default:
+      llvm_unreachable("Unimplemented option");
+    }
+
+    return error;
+  }
+
+  void OptionParsingStarting(ExecutionContext *execution_context) override {
+    m_json_format = false;
+  }
+
+  llvm::ArrayRef<OptionDefinition> GetDefinitions() override {
+    return llvm::ArrayRef(g_plugin_list_options);
+  }
+
+  // Instance variables to hold the values for command options.
+  bool m_json_format = false;
+};
+} // namespace
+
+class CommandObjectPluginList : public CommandObjectParsed {
+public:
+  CommandObjectPluginList(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "plugin list",
+                            "Report info about registered LLDB plugins.",
+                            nullptr) {
+    AddSimpleArgumentList(eArgTypeManagedPlugin);
+    SetHelpLong(R"(
+Display information about registered plugins.
+The plugin information is formatted as shown below:
+
+    <plugin-namespace>
+      [+] <plugin-name>                  Plugin #1 description
+      [-] <plugin-name>                  Plugin #2 description
+
+An enabled plugin is marked with [+] and a disabled plugin is marked with [-].
+
+Plugins can be listed by namespace and name with:
+
+  plugin list <plugin-namespace>[.<plugin-name>]
+
+Plugins can be listed by namespace alone or with a fully qualified name. When 
listed
+with just a namespace all plugins in that namespace are listed.  When no 
arguments
+are given all plugins are listed.
+
+Examples:
+List all plugins
+
+  (lldb) plugin list
+
+List all plugins in the system-runtime namespace
+
+  (lldb) plugin list system-runtime
+
+List only the plugin 'foo' matching a fully qualified name exactly
+
+  (lldb) plugin list system-runtime.foo
+)");
+  }
+
+  ~CommandObjectPluginList() override = default;
+
+  Options *GetOptions() override { return &m_options; }
+
+protected:
+  void DoExecute(Args &command, CommandReturnObject &result) override {
+    size_t argc = command.GetArgumentCount();
+    result.SetStatus(eReturnStatusSuccessFinishResult);
+
+    // Create a temporary vector to hold the patterns to simplify the logic
+    // for the case when the user passes no patterns
+    std::vector<llvm::StringRef> patterns;
+    patterns.reserve(argc == 0 ? 1 : argc);
+    if (argc == 0)
+      patterns.push_back("");
+    else
+      for (size_t i = 0; i < argc; ++i)
+        patterns.push_back(command[i].ref());
+
+    if (m_options.m_json_format)
+      OutputJsonFormat(patterns, result);
+    else
+      OutputTextFormat(patterns, result);
+  }
+
+private:
+  void OutputJsonFormat(const std::vector<llvm::StringRef> &patterns,
+                        CommandReturnObject &result) {
+    llvm::json::Object obj;
+    bool found_empty = false;
+    for (const llvm::StringRef pattern : patterns) {
+      llvm::json::Object pat_obj = PluginManager::GetJSON(pattern);
+      if (pat_obj.empty()) {
+        found_empty = true;
+        result.AppendErrorWithFormat(
+            "Found no matching plugins for pattern '%s'", pattern.data());
+        break;
+      }
+      for (auto &entry : pat_obj) {
+        obj[entry.first] = std::move(entry.second);
+      }
+    }
+    if (!found_empty) {
+      result.AppendMessage(ConvertJSONToPrettyString(std::move(obj)));
+    }
+  }
+
+  void OutputTextFormat(const std::vector<llvm::StringRef> &patterns,
+                        CommandReturnObject &result) {
+    for (const llvm::StringRef pattern : patterns) {
+      int num_matching = ActOnMatchingPlugins(
+          pattern, [&](const PluginNamespace &plugin_namespace,
+                       const std::vector<RegisteredPluginInfo> &plugins) {
+            result.AppendMessage(plugin_namespace.name);
+            for (auto &plugin : plugins) {
+              result.AppendMessageWithFormat(
+                  "  %s %-30s %s\n", plugin.enabled ? "[+]" : "[-]",
+                  plugin.name.data(), plugin.description.data());
+            }
+          });
+      if (num_matching == 0) {
+        result.AppendErrorWithFormat(
+            "Found no matching plugins for pattern '%s'", pattern.data());
+        break;
+      }
+    }
+  }
+
+  PluginListCommandOptions m_options;
+};
+
+static void DoPluginEnableDisable(Args &command, CommandReturnObject &result,
+                                  bool enable) {
+  const char *name = enable ? "enable" : "disable";
+  size_t argc = command.GetArgumentCount();
+  if (argc == 0) {
+    result.AppendErrorWithFormat("'plugin %s' requires one or more arguments",
+                                 name);
+    return;
+  }
+  result.SetStatus(eReturnStatusSuccessFinishResult);
+
+  for (size_t i = 0; i < argc; ++i) {
+    llvm::StringRef pattern = command[i].ref();
+    int num_matching = SetEnableOnMatchingPlugins(pattern, result, enable);
+
+    if (num_matching == 0) {
+      result.AppendErrorWithFormat(
+          "Found no matching plugins to %s for pattern '%s'", name,
+          pattern.data());
+      break;
+    }
+  }
+}
+
+class CommandObjectPluginEnable : public CommandObjectParsed {
+public:
+  CommandObjectPluginEnable(CommandInterpreter &interpreter)
+      : CommandObjectParsed(interpreter, "plugin enable",
+                            "Enable registered LLDB plugins.", nullptr) {
+    AddSimpleArgumentList(eArgTypeManagedPlugin);
+  }
+
+  ~CommandObjectPluginEnable() override = default;
+
+protected:
+  void DoExecute(Args &command, CommandReturnObject &result) override {
+    DoPluginEnableDisable(command, result, true);
----------------
clayborg wrote:

```
DoPluginEnableDisable(command, result, /*enable=*/true);
```

https://github.com/llvm/llvm-project/pull/134418
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to