[gnome-builder] plugins/valgrind: refactor for libide-foundry



commit c68f57e199379c6d3f1102f39f9aeffa7f636f39
Author: Christian Hergert <chergert redhat com>
Date:   Mon Jul 11 23:27:09 2022 -0700

    plugins/valgrind: refactor for libide-foundry
    
     - Use IdeRunTool API
     - Add keybindings
     - Add config tweaks as actions

 src/plugins/valgrind/gbp-valgrind-tool.c           | 204 +++++++++++++++++++++
 src/plugins/valgrind/gbp-valgrind-tool.h           |  31 ++++
 .../valgrind/gbp-valgrind-workbench-addin.c        | 196 ++++----------------
 src/plugins/valgrind/gtk/keybindings.json          |   1 +
 src/plugins/valgrind/gtk/menus.ui                  |  87 +++++++--
 src/plugins/valgrind/meson.build                   |   3 +
 .../org.gnome.builder.valgrind.gschema.xml         |  28 +++
 src/plugins/valgrind/valgrind-plugin.c             |   4 +
 src/plugins/valgrind/valgrind.gresource.xml        |   3 +-
 src/plugins/valgrind/valgrind.plugin               |   5 +-
 10 files changed, 388 insertions(+), 174 deletions(-)
---
diff --git a/src/plugins/valgrind/gbp-valgrind-tool.c b/src/plugins/valgrind/gbp-valgrind-tool.c
new file mode 100644
index 000000000..62c48ae97
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-tool.c
@@ -0,0 +1,204 @@
+/* gbp-valgrind-tool.c
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define G_LOG_DOMAIN "gbp-valgrind-tool"
+
+#include "config.h"
+
+#include <libide-gui.h>
+
+#include "gbp-valgrind-tool.h"
+
+struct _GbpValgrindTool
+{
+  IdeRunTool  parent_instance;
+  char       *log_name;
+};
+
+G_DEFINE_FINAL_TYPE (GbpValgrindTool, gbp_valgrind_tool, IDE_TYPE_RUN_TOOL)
+
+static gboolean
+gbp_valgrind_tool_handler_cb (IdeRunContext       *run_context,
+                              const char * const  *argv,
+                              const char * const  *env,
+                              const char          *cwd,
+                              IdeUnixFDMap        *unix_fd_map,
+                              gpointer             user_data,
+                              GError             **error)
+{
+  GbpValgrindTool *self = user_data;
+  g_autoptr(GSettings) settings = NULL;
+  g_autoptr(GString) leak_kinds = NULL;
+  g_autofree char *name = NULL;
+  g_autofree char *leak_check = NULL;
+  gboolean track_origins;
+  int source_fd;
+  int dest_fd;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (IDE_IS_RUN_CONTEXT (run_context));
+  g_assert (IDE_IS_UNIX_FD_MAP (unix_fd_map));
+  g_assert (argv != NULL);
+  g_assert (env != NULL);
+  g_assert (GBP_IS_VALGRIND_TOOL (self));
+
+  settings = g_settings_new ("org.gnome.builder.valgrind");
+
+  if (cwd != NULL)
+    ide_run_context_set_cwd (run_context, cwd);
+
+  dest_fd = ide_unix_fd_map_get_max_dest_fd (unix_fd_map) + 1;
+  if (!ide_run_context_merge_unix_fd_map (run_context, unix_fd_map, error))
+    IDE_RETURN (FALSE);
+
+  /* Create a temp file to write to and an FD to access it */
+  if (-1 == (source_fd = g_file_open_tmp ("gnome-builder-valgrind-XXXXXX.txt", &name, error)))
+    IDE_RETURN (FALSE);
+
+  /* Set our FD for valgrind to log to */
+  ide_run_context_take_fd (run_context, source_fd, dest_fd);
+
+  /* Save the filename so we can open it after exiting */
+  ide_set_string (&self->log_name, name);
+  g_debug ("Using %s for valgrind log", name);
+
+  track_origins = g_settings_get_boolean (settings, "track-origins");
+  leak_check = g_settings_get_string (settings, "leak-check");
+
+  leak_kinds = g_string_new (NULL);
+  if (g_settings_get_boolean (settings, "leak-kind-definite"))
+    g_string_append (leak_kinds, "definite,");
+  if (g_settings_get_boolean (settings, "leak-kind-possible"))
+    g_string_append (leak_kinds, "possible,");
+  if (g_settings_get_boolean (settings, "leak-kind-indirect"))
+    g_string_append (leak_kinds, "indirect,");
+  if (g_settings_get_boolean (settings, "leak-kind-reachable"))
+    g_string_append (leak_kinds, "reachable,");
+
+  ide_run_context_append_argv (run_context, "valgrind");
+  ide_run_context_append_formatted (run_context, "--log-fd=%d", dest_fd);
+  ide_run_context_append_formatted (run_context, "--leak-check=%s", leak_check);
+  ide_run_context_append_formatted (run_context, "--track-origins=%s", track_origins ? "yes" : "no");
+
+  if (leak_kinds->len > 0)
+    {
+      g_string_truncate (leak_kinds, leak_kinds->len-1);
+      ide_run_context_append_formatted (run_context, "--show-leak-kinds=%s", leak_kinds->str);
+    }
+
+  if (env[0] != NULL)
+    {
+      /* If we have to exec "env" to pass environment variables, then we
+       * must follow children to get to our target executable.
+       */
+      ide_run_context_append_argv (run_context, "--trace-children=yes");
+      ide_run_context_append_argv (run_context, "env");
+      ide_run_context_append_args (run_context, env);
+    }
+
+  ide_run_context_append_args (run_context, argv);
+
+  IDE_RETURN (TRUE);
+}
+
+static void
+gbp_valgrind_tool_prepare_to_run (IdeRunTool    *run_tool,
+                                  IdePipeline   *pipeline,
+                                  IdeRunCommand *run_command,
+                                  IdeRunContext *run_context)
+{
+  GbpValgrindTool *self = (GbpValgrindTool *)run_tool;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (GBP_IS_VALGRIND_TOOL (self));
+  g_assert (IDE_IS_PIPELINE (pipeline));
+  g_assert (IDE_IS_RUN_COMMAND (run_command));
+  g_assert (IDE_IS_RUN_CONTEXT (run_context));
+
+  ide_run_context_push (run_context,
+                        gbp_valgrind_tool_handler_cb,
+                        g_object_ref (self),
+                        g_object_unref);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_tool_stopped (IdeRunTool *run_tool)
+{
+  GbpValgrindTool *self = (GbpValgrindTool *)run_tool;
+  g_autoptr(GFile) file = NULL;
+  IdeWorkbench *workbench;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_MAIN_THREAD ());
+  g_assert (GBP_IS_VALGRIND_TOOL (self));
+
+  if (self->log_name == NULL)
+    IDE_EXIT;
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  workbench = ide_workbench_from_context (context);
+  file = g_file_new_for_path (self->log_name);
+
+  ide_workbench_open_async (workbench,
+                            file,
+                            "editorui",
+                            IDE_BUFFER_OPEN_FLAGS_NONE,
+                            NULL, NULL, NULL, NULL);
+
+  g_clear_pointer (&self->log_name, g_free);
+
+  IDE_EXIT;
+}
+
+static void
+gbp_valgrind_tool_finalize (GObject *object)
+{
+  GbpValgrindTool *self = (GbpValgrindTool *)object;
+
+  g_clear_pointer (&self->log_name, g_free);
+
+  G_OBJECT_CLASS (gbp_valgrind_tool_parent_class)->finalize (object);
+}
+
+static void
+gbp_valgrind_tool_class_init (GbpValgrindToolClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeRunToolClass *run_tool_class = IDE_RUN_TOOL_CLASS (klass);
+
+  object_class->finalize = gbp_valgrind_tool_finalize;
+
+  run_tool_class->prepare_to_run = gbp_valgrind_tool_prepare_to_run;
+  run_tool_class->stopped = gbp_valgrind_tool_stopped;
+}
+
+static void
+gbp_valgrind_tool_init (GbpValgrindTool *self)
+{
+  ide_run_tool_set_icon_name (IDE_RUN_TOOL (self), "system-run-symbolic");
+}
diff --git a/src/plugins/valgrind/gbp-valgrind-tool.h b/src/plugins/valgrind/gbp-valgrind-tool.h
new file mode 100644
index 000000000..be8f5abaf
--- /dev/null
+++ b/src/plugins/valgrind/gbp-valgrind-tool.h
@@ -0,0 +1,31 @@
+/* gbp-valgrind-tool.h
+ *
+ * Copyright 2022 Christian Hergert <chergert redhat com>
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#pragma once
+
+#include <libide-foundry.h>
+
+G_BEGIN_DECLS
+
+#define GBP_TYPE_VALGRIND_TOOL (gbp_valgrind_tool_get_type())
+
+G_DECLARE_FINAL_TYPE (GbpValgrindTool, gbp_valgrind_tool, GBP, VALGRIND_TOOL, IdeRunTool)
+
+G_END_DECLS
diff --git a/src/plugins/valgrind/gbp-valgrind-workbench-addin.c 
b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
index 6427e7e94..173dab00a 100644
--- a/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
+++ b/src/plugins/valgrind/gbp-valgrind-workbench-addin.c
@@ -34,212 +34,89 @@
 
 struct _GbpValgrindWorkbenchAddin
 {
-  GObject          parent_instance;
-
-  IdeWorkbench    *workbench;
-  IdeRunManager   *run_manager;
-  IdeBuildManager *build_manager;
-  char            *log_name;
-
-  guint            has_handler : 1;
+  GObject       parent_instance;
+  GActionGroup *actions;
 };
 
 static void
-gbp_valgrind_workbench_addin_runner_exited_cb (GbpValgrindWorkbenchAddin *self,
-                                               IdeRunner                 *runner)
-{
-  g_autoptr(GFile) file = NULL;
-
-  IDE_ENTRY;
-
-  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-  g_assert (IDE_IS_RUNNER (runner));
-
-  if (self->workbench == NULL || self->log_name == NULL)
-    IDE_EXIT;
-
-  file = g_file_new_for_path (self->log_name);
-  ide_workbench_open_async (self->workbench,
-                            file,
-                            "editorui",
-                            IDE_BUFFER_OPEN_FLAGS_NONE,
-                            NULL, NULL, NULL);
-
-  IDE_EXIT;
-}
-
-static void
-gbp_valgrind_workbench_addin_run_handler (IdeRunManager *run_manager,
-                                          IdeRunner     *runner,
-                                          gpointer       user_data)
-{
-  GbpValgrindWorkbenchAddin *self = user_data;
-  g_autoptr(GError) error = NULL;
-  g_autofree char *name = NULL;
-  char log_fd_param[32];
-  int map_fd;
-  int fd;
-
-  IDE_ENTRY;
-
-  g_assert (IDE_IS_RUN_MANAGER (run_manager));
-  g_assert (IDE_IS_RUNNER (runner));
-  g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-
-  /* Create a temp file to write to and an FD to access it */
-  errno = 0;
-  fd = g_file_open_tmp ("gnome-builder-valgrind-XXXXXX.txt", &name, &error);
-  if (fd < 0)
-    {
-      g_warning ("Failed to create FD to communicate with Valgrind: %s: %s",
-                 g_strerror (errno), error->message);
-      IDE_EXIT;
-    }
-
-  /* Save the filename so we can open it after exiting */
-  g_clear_pointer (&self->log_name, g_free);
-  self->log_name = g_steal_pointer (&name);
-
-  /* Get the FD number as it will exist within the subprocess */
-  map_fd = ide_runner_take_fd (runner, fd, -1);
-  g_snprintf (log_fd_param, sizeof log_fd_param, "--log-fd=%d", map_fd);
-
-  /* Setup arguments to valgrind so it writes output to temp file. Add in
-   * reverse order so we can just use prepend() repeatedly */
-  ide_runner_prepend_argv (runner, "--track-origins=yes");
-  ide_runner_prepend_argv (runner, log_fd_param);
-  ide_runner_prepend_argv (runner, "valgrind");
-
-  g_signal_connect_object (runner,
-                           "exited",
-                           G_CALLBACK (gbp_valgrind_workbench_addin_runner_exited_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
-
-  IDE_EXIT;
-}
-
-static void
-gbp_valgrind_workbench_addin_notify_pipeline_cb (GbpValgrindWorkbenchAddin *self,
-                                                 GParamSpec                *pspec,
-                                                 IdeBuildManager           *build_manager)
+gbp_valgrind_workbench_addin_load (IdeWorkbenchAddin *addin,
+                                   IdeWorkbench      *workbench)
 {
-  IdePipeline *pipeline;
-  IdeRuntime *runtime;
-  gboolean can_handle = FALSE;
+  GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
+  g_autoptr(GSettings) settings = NULL;
+  static const char *keys[] = {
+    "leak-check",
+    "leak-kind-definite",
+    "leak-kind-indirect",
+    "leak-kind-possible",
+    "leak-kind-reachable",
+    "track-origins",
+  };
 
   IDE_ENTRY;
 
   g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-  g_assert (IDE_IS_BUILD_MANAGER (build_manager));
-  g_assert (IDE_IS_RUN_MANAGER (self->run_manager));
-
-  if (!(pipeline = ide_build_manager_get_pipeline (build_manager)) ||
-      !(runtime = ide_pipeline_get_runtime (pipeline)) ||
-      !ide_runtime_contains_program_in_path (runtime, "valgrind", NULL))
-    IDE_GOTO (not_found);
+  g_assert (IDE_IS_WORKBENCH (workbench));
 
-  can_handle = TRUE;
+  settings = g_settings_new ("org.gnome.builder.valgrind");
+  self->actions = G_ACTION_GROUP (g_simple_action_group_new ());
 
-not_found:
-  if (can_handle != self->has_handler)
+  for (guint i = 0; i < G_N_ELEMENTS (keys); i++)
     {
-      self->has_handler = can_handle;
-
-      if (can_handle)
-        ide_run_manager_add_handler (self->run_manager,
-                                     "valgrind",
-                                     _("Run with Valgrind"),
-                                     "system-run-symbolic",
-                                     "<Primary>F10",
-                                     gbp_valgrind_workbench_addin_run_handler,
-                                     g_object_ref (self),
-                                     g_object_unref);
-      else
-        ide_run_manager_remove_handler (self->run_manager, "valgrind");
+      g_autoptr(GAction) action = g_settings_create_action (settings, keys[i]);
+      g_action_map_add_action (G_ACTION_MAP (self->actions), action);
     }
 
   IDE_EXIT;
 }
 
 static void
-gbp_valgrind_workbench_addin_project_loaded (IdeWorkbenchAddin *addin,
-                                             IdeProjectInfo    *project_info)
+gbp_valgrind_workbench_addin_unload (IdeWorkbenchAddin *addin,
+                                     IdeWorkbench      *workbench)
 {
   GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
-  IdeBuildManager *build_manager;
-  IdeRunManager *run_manager;
-  IdeContext *context;
 
   IDE_ENTRY;
 
   g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-  g_assert (IDE_IS_PROJECT_INFO (project_info));
-  g_assert (IDE_IS_WORKBENCH (self->workbench));
-
-  context = ide_workbench_get_context (self->workbench);
-  build_manager = ide_build_manager_from_context (context);
-  run_manager = ide_run_manager_from_context (context);
-
-  g_set_object (&self->build_manager, build_manager);
-  g_set_object (&self->run_manager, run_manager);
-
-  g_signal_connect_object (build_manager,
-                           "notify::pipeline",
-                           G_CALLBACK (gbp_valgrind_workbench_addin_notify_pipeline_cb),
-                           self,
-                           G_CONNECT_SWAPPED);
+  g_assert (IDE_IS_WORKBENCH (workbench));
 
-  gbp_valgrind_workbench_addin_notify_pipeline_cb (self, NULL, build_manager);
+  g_clear_object (&self->actions);
 
   IDE_EXIT;
 }
 
 static void
-gbp_valgrind_workbench_addin_load (IdeWorkbenchAddin *addin,
-                                   IdeWorkbench      *workbench)
+gbp_valgrind_workbench_addin_workspace_added (IdeWorkbenchAddin *addin,
+                                              IdeWorkspace      *workspace)
 {
   GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
 
   IDE_ENTRY;
 
   g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-  g_assert (IDE_IS_WORKBENCH (workbench));
+  g_assert (IDE_IS_WORKSPACE (workspace));
 
-  self->workbench = workbench;
+  if (IDE_IS_PRIMARY_WORKSPACE (workspace))
+    gtk_widget_insert_action_group (GTK_WIDGET (workspace),
+                                    "valgrind",
+                                    self->actions);
 
   IDE_EXIT;
 }
 
 static void
-gbp_valgrind_workbench_addin_unload (IdeWorkbenchAddin *addin,
-                                     IdeWorkbench      *workbench)
+gbp_valgrind_workbench_addin_workspace_removed (IdeWorkbenchAddin *addin,
+                                                IdeWorkspace      *workspace)
 {
   GbpValgrindWorkbenchAddin *self = (GbpValgrindWorkbenchAddin *)addin;
 
   IDE_ENTRY;
 
   g_assert (GBP_IS_VALGRIND_WORKBENCH_ADDIN (self));
-  g_assert (IDE_IS_WORKBENCH (workbench));
-
-  if (self->build_manager != NULL)
-    {
-      g_signal_handlers_disconnect_by_func (self->build_manager,
-                                            G_CALLBACK (gbp_valgrind_workbench_addin_notify_pipeline_cb),
-                                            self);
-      g_clear_object (&self->build_manager);
-    }
-
-  if (self->run_manager != NULL)
-    {
-      if (self->has_handler)
-        ide_run_manager_remove_handler (self->run_manager, "valgrind");
-      g_clear_object (&self->run_manager);
-    }
-
-  g_clear_pointer (&self->log_name, g_free);
+  g_assert (IDE_IS_WORKSPACE (workspace));
 
-  self->workbench = NULL;
+  gtk_widget_insert_action_group (GTK_WIDGET (workspace), "valgrind", NULL);
 
   IDE_EXIT;
 }
@@ -249,7 +126,8 @@ workbench_addin_iface_init (IdeWorkbenchAddinInterface *iface)
 {
   iface->load = gbp_valgrind_workbench_addin_load;
   iface->unload = gbp_valgrind_workbench_addin_unload;
-  iface->project_loaded = gbp_valgrind_workbench_addin_project_loaded;
+  iface->workspace_added = gbp_valgrind_workbench_addin_workspace_added;
+  iface->workspace_removed = gbp_valgrind_workbench_addin_workspace_removed;
 }
 
 G_DEFINE_FINAL_TYPE_WITH_CODE (GbpValgrindWorkbenchAddin, gbp_valgrind_workbench_addin, G_TYPE_OBJECT,
diff --git a/src/plugins/valgrind/gtk/keybindings.json b/src/plugins/valgrind/gtk/keybindings.json
new file mode 100644
index 000000000..6b4af3c9e
--- /dev/null
+++ b/src/plugins/valgrind/gtk/keybindings.json
@@ -0,0 +1 @@
+{ "trigger" : "<Control><Shift><Alt>v", "action" : "run-manager.run-with-handler", "args" : "'valgrind'", 
"when" : "canBuild()", "phase" : "capture" },
diff --git a/src/plugins/valgrind/gtk/menus.ui b/src/plugins/valgrind/gtk/menus.ui
index 4a2e8122a..b2bee6f15 100644
--- a/src/plugins/valgrind/gtk/menus.ui
+++ b/src/plugins/valgrind/gtk/menus.ui
@@ -1,26 +1,89 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <interface>
   <menu id="run-menu">
-    <section id="run-menu-section">
+    <section id="run-menu-observation-section">
       <item>
         <attribute name="id">valgrind-run-handler</attribute>
         <attribute name="after">default-run-handler</attribute>
         <attribute name="action">run-manager.run-with-handler</attribute>
-        <attribute name="target">valgrind</attribute>
-        <attribute name="label" translatable="yes">Run with Valgrind</attribute>
+        <attribute name="target" type="s">'valgrind'</attribute>
+        <attribute name="label" translatable="yes">Run with Leak Detector</attribute>
         <attribute name="verb-icon-name">system-run-symbolic</attribute>
-        <attribute name="accel">&lt;Control&gt;F10</attribute>
+        <attribute name="accel">&lt;control&gt;&lt;shift&gt;&lt;alt&gt;v</attribute>
       </item>
     </section>
   </menu>
-  <menu id="project-tree-run-with-submenu">
-    <section id="project-tree-menu-run-with-section">
-      <item>
-        <attribute name="id">project-tree-menu-valgrind</attribute>
-        <attribute name="label" translatable="yes">Run with Valgrind</attribute>
-        <attribute name="action">buildui.run-with-handler</attribute>
-        <attribute name="target" type="s">'valgrind'</attribute>
-      </item>
+  <menu id="run-menu">
+    <section id="run-menu-tools-section">
+      <submenu id="run-menu-valgrind-submenu">
+        <attribute name="before">run-menu-verbose-logging</attribute>
+        <attribute name="label" translatable="yes">Leak Detector</attribute>
+        <section id="run-menu-valgrind-origins-section">
+          <item>
+            <attribute name="label" translatable="yes">Track Origin of Leaks</attribute>
+            <attribute name="action">valgrind.track-origins</attribute>
+            <attribute name="role">check</attribute>
+          </item>
+        </section>
+        <section id="run-menu-valgrind-leak-check">
+          <attribute name="label" translatable="yes">Report Leaks</attribute>
+          <item>
+            <attribute name="label" translatable="yes">Summary</attribute>
+            <attribute name="action">valgrind.leak-check</attribute>
+            <attribute name="target" type="s">'summary'</attribute>
+            <attribute name="role">radio</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Full</attribute>
+            <attribute name="action">valgrind.leak-check</attribute>
+            <attribute name="target" type="s">'full'</attribute>
+            <attribute name="role">radio</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Disabled</attribute>
+            <attribute name="action">valgrind.leak-check</attribute>
+            <attribute name="target" type="s">'no'</attribute>
+            <attribute name="role">radio</attribute>
+          </item>
+        </section>
+        <section id="run-menu-valgrind-leak-kinds">
+          <attribute name="label" translatable="yes">Leak Kinds</attribute>
+          <item>
+            <attribute name="label" translatable="yes">Definite</attribute>
+            <attribute name="action">valgrind.leak-kind-definite</attribute>
+            <attribute name="role">check</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Indirect</attribute>
+            <attribute name="action">valgrind.leak-kind-indirect</attribute>
+            <attribute name="role">check</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Possible</attribute>
+            <attribute name="action">valgrind.leak-kind-possible</attribute>
+            <attribute name="role">check</attribute>
+          </item>
+          <item>
+            <attribute name="label" translatable="yes">Reachable</attribute>
+            <attribute name="action">valgrind.leak-kind-reachable</attribute>
+            <attribute name="role">check</attribute>
+          </item>
+        </section>
+      </submenu>
+    </section>
+  </menu>
+  <menu id="project-tree-menu">
+    <section id="project-tree-menu-foundry-section">
+      <submenu id="project-tree-run-with-submenu">
+        <section id="project-tree-menu-run-with-section">
+          <item>
+            <attribute name="id">project-tree-menu-valgrind</attribute>
+            <attribute name="label" translatable="yes">Run with Leak Detector</attribute>
+            <attribute name="action">buildui.run-with-handler</attribute>
+            <attribute name="target" type="s">'valgrind'</attribute>
+          </item>
+        </section>
+      </submenu>
     </section>
   </menu>
 </interface>
diff --git a/src/plugins/valgrind/meson.build b/src/plugins/valgrind/meson.build
index 72bb792f9..132ba5616 100644
--- a/src/plugins/valgrind/meson.build
+++ b/src/plugins/valgrind/meson.build
@@ -2,6 +2,7 @@ if get_option('plugin_valgrind')
 
 plugins_sources += files([
   'valgrind-plugin.c',
+  'gbp-valgrind-tool.c',
   'gbp-valgrind-workbench-addin.c',
 ])
 
@@ -13,4 +14,6 @@ plugin_valgrind_resources = gnome.compile_resources(
 
 plugins_sources += plugin_valgrind_resources
 
+install_data(['org.gnome.builder.valgrind.gschema.xml'], install_dir: schema_dir)
+
 endif
diff --git a/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml 
b/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml
new file mode 100644
index 000000000..fe9eb0387
--- /dev/null
+++ b/src/plugins/valgrind/org.gnome.builder.valgrind.gschema.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<schemalist>
+  <schema id="org.gnome.builder.valgrind" path="/org/gnome/builder/valgrind/" gettext-domain="gnome-builder">
+    <key name="leak-kind-definite" type="b">
+      <default>true</default>
+    </key>
+    <key name="leak-kind-possible" type="b">
+      <default>true</default>
+    </key>
+    <key name="leak-kind-indirect" type="b">
+      <default>false</default>
+    </key>
+    <key name="leak-kind-reachable" type="b">
+      <default>false</default>
+    </key>
+    <key name="track-origins" type="b">
+      <default>true</default>
+    </key>
+    <key name="leak-check" type="s">
+      <choices>
+        <choice value="no"/>
+        <choice value="summary"/>
+        <choice value="full"/>
+      </choices>
+      <default>'summary'</default>
+    </key>
+  </schema>
+</schemalist>
diff --git a/src/plugins/valgrind/valgrind-plugin.c b/src/plugins/valgrind/valgrind-plugin.c
index d6d0a5715..b3df73279 100644
--- a/src/plugins/valgrind/valgrind-plugin.c
+++ b/src/plugins/valgrind/valgrind-plugin.c
@@ -26,11 +26,15 @@
 
 #include <libide-gui.h>
 
+#include "gbp-valgrind-tool.h"
 #include "gbp-valgrind-workbench-addin.h"
 
 _IDE_EXTERN void
 _gbp_valgrind_register_types (PeasObjectModule *module)
 {
+  peas_object_module_register_extension_type (module,
+                                              IDE_TYPE_RUN_TOOL,
+                                              GBP_TYPE_VALGRIND_TOOL);
   peas_object_module_register_extension_type (module,
                                               IDE_TYPE_WORKBENCH_ADDIN,
                                               GBP_TYPE_VALGRIND_WORKBENCH_ADDIN);
diff --git a/src/plugins/valgrind/valgrind.gresource.xml b/src/plugins/valgrind/valgrind.gresource.xml
index 534ca0ffb..bfc01b311 100644
--- a/src/plugins/valgrind/valgrind.gresource.xml
+++ b/src/plugins/valgrind/valgrind.gresource.xml
@@ -2,6 +2,7 @@
 <gresources>
   <gresource prefix="/plugins/valgrind">
     <file>valgrind.plugin</file>
-    <file>gtk/menus.ui</file>
+    <file preprocess="xml-stripblanks">gtk/menus.ui</file>
+    <file>gtk/keybindings.json</file>
   </gresource>
 </gresources>
diff --git a/src/plugins/valgrind/valgrind.plugin b/src/plugins/valgrind/valgrind.plugin
index 028e7c046..3b1faa29f 100644
--- a/src/plugins/valgrind/valgrind.plugin
+++ b/src/plugins/valgrind/valgrind.plugin
@@ -2,8 +2,9 @@
 Authors=Christian Hergert <christian hergert me>
 Builtin=true
 Copyright=Copyright © 2017-2022 Christian Hergert
-Description=Provides integration with valgrind
+Depends=buildui;
+Description=Provides integration with valgrind to detect leaks
 Embedded=_gbp_valgrind_register_types
 Module=valgrind
-Name=Valgrind
+Name=Leak Detector
 X-Category=debuggers


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]