[gnome-builder/wip/extensions] diagnostician: use plugins to define diagnostic providers



commit a5359780e85b9a5612d33dac5ceffabe5c3c7cb4
Author: Christian Hergert <christian hergert me>
Date:   Sun Jun 28 13:51:55 2015 -0700

    diagnostician: use plugins to define diagnostic providers

 libide/c/ide-c-language.c                          |   13 -
 libide/ide-buffer.c                                |   48 ++--
 libide/ide-diagnostic-provider.c                   |    7 +
 libide/ide-diagnostician.c                         |  248 +++++++++++++++++---
 libide/ide-diagnostician.h                         |   24 ++-
 libide/ide-internal.h                              |    4 -
 libide/ide-language.c                              |   63 -----
 libide/ide-language.h                              |    2 -
 plugins/clang-diagnostics/clang-diagnostics.plugin |    1 -
 tools/Makefile.am                                  |    3 +
 tools/ide-list-diagnostics.c                       |   60 +++++-
 11 files changed, 325 insertions(+), 148 deletions(-)
---
diff --git a/libide/c/ide-c-language.c b/libide/c/ide-c-language.c
index 90a5274..8657946 100644
--- a/libide/c/ide-c-language.c
+++ b/libide/c/ide-c-language.c
@@ -23,7 +23,6 @@
 #include "ide-c-format-provider.h"
 #include "ide-c-indenter.h"
 #include "ide-c-language.h"
-#include "ide-diagnostician.h"
 #include "ide-extension-point.h"
 #include "ide-internal.h"
 
@@ -57,17 +56,6 @@ ide_c_language_get_completion_providers (IdeLanguage *language)
   return providers;
 }
 
-static IdeDiagnostician *
-ide_c_language_get_diagnostician (IdeLanguage *language)
-{
-  IdeCLanguage *self = (IdeCLanguage *)language;
-  IdeCLanguagePrivate *priv = ide_c_language_get_instance_private (self);
-
-  g_return_val_if_fail (IDE_IS_C_LANGUAGE (self), NULL);
-
-  return priv->diagnostician;
-}
-
 static IdeIndenter *
 ide_c_language_get_indenter (IdeLanguage *language)
 {
@@ -116,7 +104,6 @@ ide_c_language_class_init (IdeCLanguageClass *klass)
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
   language_class->get_completion_providers = ide_c_language_get_completion_providers;
-  language_class->get_diagnostician = ide_c_language_get_diagnostician;
   language_class->get_indenter = ide_c_language_get_indenter;
   language_class->get_refactory = ide_c_language_get_refactory;
   language_class->get_name = ide_c_language_get_name;
diff --git a/libide/ide-buffer.c b/libide/ide-buffer.c
index 61fe8f1..b5db0e3 100644
--- a/libide/ide-buffer.c
+++ b/libide/ide-buffer.c
@@ -60,6 +60,7 @@
 typedef struct
 {
   IdeContext             *context;
+  IdeDiagnostician       *diagnostician;
   IdeDiagnostics         *diagnostics;
   GHashTable             *diagnostics_line_cache;
   IdeFile                *file;
@@ -494,35 +495,29 @@ ide_buffer__diagnose_timeout_cb (gpointer user_data)
 {
   IdeBuffer *self = user_data;
   IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
+  GtkSourceLanguage *language;
 
   g_assert (IDE_IS_BUFFER (self));
 
   priv->diagnose_timeout = 0;
 
-  if (priv->file)
-    {
-      IdeLanguage *language;
-
-      language = ide_file_get_language (priv->file);
-
-      if (language)
-        {
-          IdeDiagnostician *diagnostician;
-
-          diagnostician = ide_language_get_diagnostician (language);
+  /*
+   * FIXME: Why are we getting a diagnostician with a NULL language sometimes?
+   */
+  language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (self));
+  if (ide_diagnostician_get_language (priv->diagnostician) != language)
+    ide_diagnostician_set_language (priv->diagnostician, language);
 
-          if (diagnostician)
-            {
-              priv->diagnostics_dirty = FALSE;
-              priv->in_diagnose = TRUE;
-              g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_BUSY]);
-
-              ide_buffer_sync_to_unsaved_files (self);
-              ide_diagnostician_diagnose_async (diagnostician, priv->file, NULL,
-                                                ide_buffer__diagnostician_diagnose_cb,
-                                                g_object_ref (self));
-            }
-        }
+  if ((priv->file != NULL) && ide_diagnostician_is_ready (priv->diagnostician))
+    {
+      priv->diagnostics_dirty = FALSE;
+      priv->in_diagnose = TRUE;
+      g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_BUSY]);
+
+      ide_buffer_sync_to_unsaved_files (self);
+      ide_diagnostician_diagnose_async (priv->diagnostician, priv->file, NULL,
+                                        ide_buffer__diagnostician_diagnose_cb,
+                                        g_object_ref (self));
     }
 
   return G_SOURCE_REMOVE;
@@ -905,6 +900,7 @@ ide_buffer__file_notify_language (IdeBuffer  *self,
                                   GParamSpec *pspec,
                                   IdeFile    *file)
 {
+  IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
   GtkSourceLanguage *source_language;
   IdeLanguage *language;
 
@@ -920,6 +916,7 @@ ide_buffer__file_notify_language (IdeBuffer  *self,
     {
       source_language = ide_language_get_source_language (language);
       gtk_source_buffer_set_language (GTK_SOURCE_BUFFER (self), source_language);
+      ide_diagnostician_set_language (priv->diagnostician, source_language);
     }
 
   ide_file_load_settings_async (file,
@@ -935,6 +932,7 @@ ide_buffer_constructed (GObject *object)
 {
   IdeBuffer *self = (IdeBuffer *)object;
   IdeBufferPrivate *priv = ide_buffer_get_instance_private (self);
+  GtkSourceLanguage *language;
   GdkRGBA deprecated_rgba;
   GdkRGBA error_rgba;
   GdkRGBA note_rgba;
@@ -974,8 +972,10 @@ ide_buffer_constructed (GObject *object)
                               "underline-rgba", &error_rgba,
                               NULL);
 
-  priv->highlight_engine = ide_highlight_engine_new (self);
+  language = gtk_source_buffer_get_language (GTK_SOURCE_BUFFER (self));
+  priv->diagnostician = ide_diagnostician_new (priv->context, language);
 
+  priv->highlight_engine = ide_highlight_engine_new (self);
   ide_buffer_reload_highlighter (self);
 }
 
diff --git a/libide/ide-diagnostic-provider.c b/libide/ide-diagnostic-provider.c
index 9b0f9a4..151d537 100644
--- a/libide/ide-diagnostic-provider.c
+++ b/libide/ide-diagnostic-provider.c
@@ -16,6 +16,7 @@
  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#include "ide-context.h"
 #include "ide-diagnostic-provider.h"
 #include "ide-file.h"
 
@@ -24,6 +25,12 @@ G_DEFINE_INTERFACE (IdeDiagnosticProvider, ide_diagnostic_provider, IDE_TYPE_OBJ
 static void
 ide_diagnostic_provider_default_init (IdeDiagnosticProviderInterface *iface)
 {
+  g_object_interface_install_property (iface,
+                                       g_param_spec_object ("context",
+                                                            "Context",
+                                                            "Context",
+                                                            IDE_TYPE_CONTEXT,
+                                                            (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY | 
G_PARAM_STATIC_STRINGS)));
 }
 
 void
diff --git a/libide/ide-diagnostician.c b/libide/ide-diagnostician.c
index a9bc26a..e4d7977 100644
--- a/libide/ide-diagnostician.c
+++ b/libide/ide-diagnostician.c
@@ -19,7 +19,10 @@
 #define G_LOG_DOMAIN "ide-diagnostician"
 
 #include <glib/gi18n.h>
+#include <gtksourceview/gtksource.h>
+#include <libpeas/peas.h>
 
+#include "ide-debug.h"
 #include "ide-diagnostic-provider.h"
 #include "ide-diagnostician.h"
 #include "ide-diagnostics.h"
@@ -28,9 +31,16 @@
 
 struct _IdeDiagnostician
 {
-  IdeObject  parent_instance;
+  IdeObject          parent_instance;
 
-  GPtrArray *providers;
+  GPtrArray         *providers;
+  GtkSourceLanguage *language;
+};
+
+enum {
+  PROP_0,
+  PROP_LANGUAGE,
+  LAST_PROP
 };
 
 typedef struct
@@ -42,6 +52,8 @@ typedef struct
 
 G_DEFINE_TYPE (IdeDiagnostician, ide_diagnostician, IDE_TYPE_OBJECT)
 
+static GParamSpec *gParamSpecs [LAST_PROP];
+
 static void
 diagnose_state_free (gpointer data)
 {
@@ -54,26 +66,6 @@ diagnose_state_free (gpointer data)
     }
 }
 
-void
-_ide_diagnostician_add_provider (IdeDiagnostician      *self,
-                                 IdeDiagnosticProvider *provider)
-{
-  g_return_if_fail (IDE_IS_DIAGNOSTICIAN (self));
-  g_return_if_fail (IDE_IS_DIAGNOSTIC_PROVIDER (provider));
-
-  g_ptr_array_add (self->providers, g_object_ref (provider));
-}
-
-void
-_ide_diagnostician_remove_provider (IdeDiagnostician      *self,
-                                    IdeDiagnosticProvider *provider)
-{
-  g_return_if_fail (IDE_IS_DIAGNOSTICIAN (self));
-  g_return_if_fail (IDE_IS_DIAGNOSTIC_PROVIDER (provider));
-
-  g_ptr_array_remove (self->providers, provider);
-}
-
 static void
 diagnose_cb (GObject      *object,
              GAsyncResult *result,
@@ -120,6 +112,8 @@ ide_diagnostician_diagnose_async (IdeDiagnostician    *self,
   g_autoptr(GTask) task = NULL;
   gsize i;
 
+  IDE_ENTRY;
+
   g_return_if_fail (IDE_IS_DIAGNOSTICIAN (self));
   g_return_if_fail (IDE_IS_FILE (file));
   g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
@@ -131,7 +125,7 @@ ide_diagnostician_diagnose_async (IdeDiagnostician    *self,
       g_task_return_pointer (task,
                              _ide_diagnostics_new (NULL),
                              (GDestroyNotify)ide_diagnostics_unref);
-      return;
+      IDE_EXIT;
     }
 
   state = g_slice_new0 (DiagnoseState);
@@ -152,6 +146,8 @@ ide_diagnostician_diagnose_async (IdeDiagnostician    *self,
                                               diagnose_cb,
                                               g_object_ref (task));
     }
+
+  IDE_EXIT;
 }
 
 IdeDiagnostics *
@@ -160,20 +156,172 @@ ide_diagnostician_diagnose_finish (IdeDiagnostician  *self,
                                    GError           **error)
 {
   GTask *task = (GTask *)result;
+  IdeDiagnostics *ret;
+
+  IDE_ENTRY;
 
   g_return_val_if_fail (G_IS_TASK (result), NULL);
 
-  return g_task_propagate_pointer (task, error);
+  ret = g_task_propagate_pointer (task, error);
+
+  IDE_RETURN (ret);
+}
+
+static gboolean
+supports_language (const gchar *languages,
+                   const gchar *lang_id)
+{
+  g_auto(GStrv) parts = g_strsplit (languages, ",", 0);
+
+  return (g_strv_contains ((const gchar * const *)parts, lang_id) ||
+          g_strv_contains ((const gchar * const *)parts, "*"));
+}
+
+static void
+ide_diagnostician__engine_load_plugin (IdeDiagnostician *self,
+                                       PeasPluginInfo   *plugin_info,
+                                       PeasEngine       *engine)
+{
+  PeasExtension *exten;
+  IdeContext *context;
+  const gchar *languages;
+  const gchar *lang_id;
+
+  g_assert (IDE_IS_DIAGNOSTICIAN (self));
+  g_assert (plugin_info != NULL);
+  g_assert (PEAS_IS_ENGINE (engine));
+
+  if ((self->language == NULL) || !(lang_id = gtk_source_language_get_id (self->language)))
+    return;
+
+  if (!peas_engine_provides_extension (engine, plugin_info, IDE_TYPE_DIAGNOSTIC_PROVIDER))
+    return;
+
+  languages = peas_plugin_info_get_external_data (plugin_info, "Diagnostic-Languages");
+  if (!supports_language (languages, lang_id))
+    return;
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  exten = peas_engine_create_extension (engine, plugin_info, IDE_TYPE_DIAGNOSTIC_PROVIDER,
+                                        "context", context,
+                                        NULL);
+  g_ptr_array_add (self->providers, exten);
+}
+
+static void
+ide_diagnostician__engine_unload_plugin (IdeDiagnostician *self,
+                                         PeasPluginInfo   *plugin_info,
+                                         PeasEngine       *engine)
+{
+  gsize i;
+
+  g_assert (IDE_IS_DIAGNOSTICIAN (self));
+  g_assert (plugin_info != NULL);
+  g_assert (PEAS_IS_ENGINE (engine));
+
+  for (i = 0; i < self->providers->len; i++)
+    {
+      PeasExtension *exten = g_ptr_array_index (self->providers, i);
+
+      if (peas_extension_base_get_plugin_info (PEAS_EXTENSION_BASE (exten)) == plugin_info)
+        {
+          g_ptr_array_remove_index_fast (self->providers, i);
+          break;
+        }
+    }
+}
+
+static void
+ide_diagnostician_reload (IdeDiagnostician *self,
+                          const gchar      *lang_id)
+{
+  g_return_if_fail (IDE_IS_DIAGNOSTICIAN (self));
+
+  if (self->providers->len > 0)
+    g_ptr_array_remove_range (self->providers, 0, self->providers->len);
+
+  if (lang_id != NULL)
+    {
+      PeasEngine *engine;
+      const GList *list;
+
+      engine = peas_engine_get_default ();
+      list = peas_engine_get_plugin_list (engine);
+
+      for (; list; list = list->next)
+        ide_diagnostician__engine_load_plugin (self, list->data, engine);
+    }
+}
+
+/**
+ * ide_diagnostician_get_language:
+ *
+ * Gets the IdeDiagnostician::language property.
+ *
+ * Returns: (nullable) (transfer none): A #GtkSourceLanguage or %NULL.
+ */
+GtkSourceLanguage *
+ide_diagnostician_get_language (IdeDiagnostician *self)
+{
+  g_return_val_if_fail (IDE_IS_DIAGNOSTICIAN (self), NULL);
+
+  return self->language;
+}
+
+void
+ide_diagnostician_set_language (IdeDiagnostician  *self,
+                                GtkSourceLanguage *language)
+{
+  g_return_if_fail (IDE_IS_DIAGNOSTICIAN (self));
+  g_return_if_fail (!language || GTK_SOURCE_IS_LANGUAGE (language));
+
+  if (g_set_object (&self->language, language))
+    {
+      const gchar *lang_id = NULL;
+
+      if (language != NULL)
+        lang_id = gtk_source_language_get_id (language);
+      ide_diagnostician_reload (self, lang_id);
+      g_object_notify_by_pspec (G_OBJECT (self), gParamSpecs [PROP_LANGUAGE]);
+    }
+}
+
+static void
+ide_diagnostician_get_property (GObject    *object,
+                                guint       prop_id,
+                                GValue     *value,
+                                GParamSpec *pspec)
+{
+  IdeDiagnostician *self = (IdeDiagnostician *)object;
+
+  switch (prop_id)
+    {
+    case PROP_LANGUAGE:
+      g_value_set_object (value, ide_diagnostician_get_language (self));
+      break;
+
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
 }
 
 static void
-ide_diagnostician_dispose (GObject *object)
+ide_diagnostician_set_property (GObject      *object,
+                                guint         prop_id,
+                                const GValue *value,
+                                GParamSpec   *pspec)
 {
   IdeDiagnostician *self = (IdeDiagnostician *)object;
 
-  g_clear_pointer (&self->providers, g_ptr_array_unref);
+  switch (prop_id)
+    {
+    case PROP_LANGUAGE:
+      ide_diagnostician_set_language (self, g_value_get_object (value));
+      break;
 
-  G_OBJECT_CLASS (ide_diagnostician_parent_class)->dispose (object);
+    default:
+      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+    }
 }
 
 static void
@@ -181,11 +329,55 @@ ide_diagnostician_class_init (IdeDiagnosticianClass *klass)
 {
   GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-  object_class->dispose = ide_diagnostician_dispose;
+  object_class->get_property = ide_diagnostician_get_property;
+  object_class->set_property = ide_diagnostician_set_property;
+
+  gParamSpecs [PROP_LANGUAGE] =
+    g_param_spec_object ("language",
+                         _("Language"),
+                         _("Language"),
+                         GTK_SOURCE_TYPE_LANGUAGE,
+                         (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+  g_object_class_install_properties (object_class, LAST_PROP, gParamSpecs);
 }
 
 static void
 ide_diagnostician_init (IdeDiagnostician *self)
 {
+  PeasEngine *engine;
+
   self->providers = g_ptr_array_new_with_free_func (g_object_unref);
+
+  engine = peas_engine_get_default ();
+
+  g_signal_connect_object (engine,
+                           "load-plugin",
+                           G_CALLBACK (ide_diagnostician__engine_load_plugin),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  g_signal_connect_object (engine,
+                           "unload-plugin",
+                           G_CALLBACK (ide_diagnostician__engine_unload_plugin),
+                           self,
+                           G_CONNECT_SWAPPED);
+}
+
+IdeDiagnostician *
+ide_diagnostician_new (IdeContext        *context,
+                       GtkSourceLanguage *language)
+{
+  return g_object_new (IDE_TYPE_DIAGNOSTICIAN,
+                       "context", context,
+                       "language", language,
+                       NULL);
+}
+
+gboolean
+ide_diagnostician_is_ready (IdeDiagnostician *diagnostician)
+{
+  g_return_val_if_fail (IDE_IS_DIAGNOSTICIAN (diagnostician), FALSE);
+
+  return (diagnostician->providers->len > 0);
 }
diff --git a/libide/ide-diagnostician.h b/libide/ide-diagnostician.h
index c3b7f56..56160a4 100644
--- a/libide/ide-diagnostician.h
+++ b/libide/ide-diagnostician.h
@@ -19,6 +19,8 @@
 #ifndef IDE_DIAGNOSTICIAN_H
 #define IDE_DIAGNOSTICIAN_H
 
+#include <gtksourceview/gtksource.h>
+
 #include "ide-object.h"
 
 G_BEGIN_DECLS
@@ -27,14 +29,20 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeDiagnostician, ide_diagnostician, IDE, DIAGNOSTICIAN, IdeObject)
 
-void            ide_diagnostician_diagnose_async  (IdeDiagnostician     *diagnostician,
-                                                   IdeFile              *file,
-                                                   GCancellable         *cancellable,
-                                                   GAsyncReadyCallback   callback,
-                                                   gpointer              user_data);
-IdeDiagnostics *ide_diagnostician_diagnose_finish (IdeDiagnostician     *diagnostician,
-                                                   GAsyncResult         *result,
-                                                   GError              **error);
+IdeDiagnostician  *ide_diagnostician_new             (IdeContext           *context,
+                                                      GtkSourceLanguage    *language);
+void               ide_diagnostician_set_language    (IdeDiagnostician     *diagnostician,
+                                                      GtkSourceLanguage    *language);
+GtkSourceLanguage *ide_diagnostician_get_language    (IdeDiagnostician     *diagnostician);
+gboolean           ide_diagnostician_is_ready        (IdeDiagnostician     *diagnostician);
+void               ide_diagnostician_diagnose_async  (IdeDiagnostician     *diagnostician,
+                                                      IdeFile              *file,
+                                                      GCancellable         *cancellable,
+                                                      GAsyncReadyCallback   callback,
+                                                      gpointer              user_data);
+IdeDiagnostics    *ide_diagnostician_diagnose_finish (IdeDiagnostician     *diagnostician,
+                                                      GAsyncResult         *result,
+                                                      GError              **error);
 
 G_END_DECLS
 
diff --git a/libide/ide-internal.h b/libide/ide-internal.h
index a6a2a6a..bc66644 100644
--- a/libide/ide-internal.h
+++ b/libide/ide-internal.h
@@ -75,10 +75,6 @@ void                _ide_diagnostic_take_fixit              (IdeDiagnostic
                                                              IdeFixit              *fixit);
 void                _ide_diagnostic_take_range              (IdeDiagnostic         *self,
                                                              IdeSourceRange        *range);
-void                _ide_diagnostician_add_provider         (IdeDiagnostician      *self,
-                                                             IdeDiagnosticProvider *provider);
-void                _ide_diagnostician_remove_provider      (IdeDiagnostician      *self,
-                                                             IdeDiagnosticProvider *provider);
 IdeDiagnostics     *_ide_diagnostics_new                    (GPtrArray             *ar);
 const gchar        *_ide_file_get_content_type              (IdeFile               *self);
 GtkSourceFile      *_ide_file_set_content_type              (IdeFile               *self,
diff --git a/libide/ide-language.c b/libide/ide-language.c
index 3dff789..48c5cb8 100644
--- a/libide/ide-language.c
+++ b/libide/ide-language.c
@@ -20,8 +20,6 @@
 
 #include "ide-context.h"
 #include "ide-ctags-service.h"
-#include "ide-diagnostician.h"
-#include "ide-gca-diagnostic-provider.h"
 #include "ide-indenter.h"
 #include "ide-internal.h"
 #include "ide-language.h"
@@ -36,7 +34,6 @@ G_DEFINE_TYPE_WITH_PRIVATE (IdeLanguage, ide_language, IDE_TYPE_OBJECT)
 
 enum {
   PROP_0,
-  PROP_DIAGNOSTICIAN,
   PROP_INDENTER,
   PROP_ID,
   PROP_NAME,
@@ -45,7 +42,6 @@ enum {
 };
 
 static GParamSpec *gParamSpecs [LAST_PROP];
-static IdeDiagnostician *gDiagnostician;
 
 /**
  * ide_language_get_source_language:
@@ -123,53 +119,6 @@ ide_language_get_completion_providers (IdeLanguage *self)
 }
 
 /**
- * ide_language_get_diagnostician:
- *
- * Returns the #IdeDiagnostician for the #IdeLanguage.
- *
- * The diagnostician is responsible for querying the proper language tools to
- * diagnose issues with a particular #IdeFile.
- *
- * See ide_diagnostician_diagnose_async() for more information.
- *
- * If the #IdeLanguage does not have an #IdeDiagnostician, then %NULL is
- * returned.
- *
- * Returns: (transfer none) (nullable): An #IdeDiagnostician or %NULL.
- */
-IdeDiagnostician *
-ide_language_get_diagnostician (IdeLanguage *self)
-{
-  g_return_val_if_fail (IDE_IS_LANGUAGE (self), NULL);
-
-  if (IDE_LANGUAGE_GET_CLASS (self)->get_diagnostician)
-    return IDE_LANGUAGE_GET_CLASS (self)->get_diagnostician (self);
-
-  return NULL;
-}
-
-static IdeDiagnostician *
-ide_language_real_get_diagnostician (IdeLanguage *self)
-{
-  if (!gDiagnostician)
-    {
-      IdeDiagnosticProvider *provider;
-      IdeContext *context;
-
-      context = ide_object_get_context (IDE_OBJECT (self));
-      gDiagnostician = g_object_new (IDE_TYPE_DIAGNOSTICIAN,
-                                     "context", context,
-                                     NULL);
-      provider = g_object_new (IDE_TYPE_GCA_DIAGNOSTIC_PROVIDER,
-                               "context", context,
-                               NULL);
-      _ide_diagnostician_add_provider (gDiagnostician, provider);
-    }
-
-  return gDiagnostician;
-}
-
-/**
  * ide_language_get_indenter:
  *
  * Fetches the #IdeIndenter for @language.
@@ -266,10 +215,6 @@ ide_language_get_property (GObject    *object,
 
   switch (prop_id)
     {
-    case PROP_DIAGNOSTICIAN:
-      g_value_set_object (value, ide_language_get_diagnostician (self));
-      break;
-
     case PROP_ID:
       g_value_set_string (value, ide_language_get_id (self));
       break;
@@ -319,14 +264,6 @@ ide_language_class_init (IdeLanguageClass *klass)
   object_class->set_property = ide_language_set_property;
 
   klass->get_completion_providers = ide_language_real_get_completion_providers;
-  klass->get_diagnostician = ide_language_real_get_diagnostician;
-
-  gParamSpecs [PROP_DIAGNOSTICIAN] =
-    g_param_spec_object ("diagnostician",
-                         _("Diagnostician"),
-                         _("The diagnostician for the language."),
-                         IDE_TYPE_DIAGNOSTICIAN,
-                         (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
 
   gParamSpecs [PROP_ID] =
     g_param_spec_string ("id",
diff --git a/libide/ide-language.h b/libide/ide-language.h
index 00c8ba7..c7a537e 100644
--- a/libide/ide-language.h
+++ b/libide/ide-language.h
@@ -34,7 +34,6 @@ struct _IdeLanguageClass
 {
   IdeObjectClass parent;
 
-  IdeDiagnostician  *(*get_diagnostician)        (IdeLanguage *self);
   IdeIndenter       *(*get_indenter)             (IdeLanguage *self);
   const gchar       *(*get_name)                 (IdeLanguage *self);
   IdeRefactory      *(*get_refactory)            (IdeLanguage *self);
@@ -42,7 +41,6 @@ struct _IdeLanguageClass
   GList             *(*get_completion_providers) (IdeLanguage *self);
 };
 
-IdeDiagnostician  *ide_language_get_diagnostician        (IdeLanguage *self);
 const gchar       *ide_language_get_id                   (IdeLanguage *self);
 IdeIndenter       *ide_language_get_indenter             (IdeLanguage *self);
 const gchar       *ide_language_get_name                 (IdeLanguage *self);
diff --git a/plugins/clang-diagnostics/clang-diagnostics.plugin 
b/plugins/clang-diagnostics/clang-diagnostics.plugin
index 0638cfd..5e99959 100644
--- a/plugins/clang-diagnostics/clang-diagnostics.plugin
+++ b/plugins/clang-diagnostics/clang-diagnostics.plugin
@@ -8,4 +8,3 @@ Builtin=true
 Hidden=true
 Depends=gnome-builder-plugin-clang
 X-Diagnostic-Languages=c,chdr,cpp
-X-Diagnostic-Priority=100
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 3f4ef1f..5339b67 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -3,6 +3,9 @@ tools_PROGRAMS =
 tools_cflags = \
        -I$(top_srcdir)/libide \
        -I$(top_builddir)/libide \
+       -DPACKAGE_DATADIR="\"${datadir}\"" \
+       -DPACKAGE_LOCALE_DIR=\""${datadir}/locale"\" \
+       -DPACKAGE_LIBDIR=\""${libdir}"\" \
        $(LIBIDE_CFLAGS) \
        $(NULL)
 
diff --git a/tools/ide-list-diagnostics.c b/tools/ide-list-diagnostics.c
index de7bbae..944832c 100644
--- a/tools/ide-list-diagnostics.c
+++ b/tools/ide-list-diagnostics.c
@@ -23,6 +23,7 @@
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <ide.h>
+#include <libpeas/peas.h>
 #include <stdlib.h>
 
 static GMainLoop *gMainLoop;
@@ -217,7 +218,7 @@ context_cb (GObject      *object,
 {
   g_autoptr(IdeContext) context = NULL;
   g_autoptr(GError) error = NULL;
-  IdeDiagnostician *diagnostician;
+  g_autoptr(IdeDiagnostician) diagnostician = NULL;
   IdeLanguage *language;
   IdeProject *project;
   IdeFile *file;
@@ -251,12 +252,12 @@ context_cb (GObject      *object,
     }
 
   language = ide_file_get_language (file);
-  diagnostician = ide_language_get_diagnostician (language);
+  diagnostician = ide_diagnostician_new (context, ide_language_get_source_language (language));
 
-  if (!diagnostician)
+  if (!ide_diagnostician_is_ready (diagnostician))
     {
-      g_printerr (_("No diagnostician for language \"%s\"\n"),
-                  ide_language_get_name (language));
+      g_printerr (_("No diagnostic providers for language \"%s\"\n"),
+                  ide_language_get_id (language));
       quit (EXIT_FAILURE);
       return;
     }
@@ -268,6 +269,53 @@ context_cb (GObject      *object,
                                     g_object_ref (context));
 }
 
+/*
+ * TODO: We should make this more generic.
+ */
+static void
+load_plugins (void)
+{
+  PeasEngine *engine;
+  const GList *list;
+
+  engine = peas_engine_get_default ();
+
+  if (g_getenv ("GB_IN_TREE_PLUGINS") != NULL)
+    {
+      GDir *dir;
+
+      if ((dir = g_dir_open ("plugins", 0, NULL)))
+        {
+          const gchar *name;
+
+          while ((name = g_dir_read_name (dir)))
+            {
+              gchar *path;
+
+              path = g_build_filename ("plugins", name, NULL);
+              peas_engine_prepend_search_path (engine, path, path);
+              g_free (path);
+            }
+
+          g_dir_close (dir);
+        }
+    }
+  else
+    {
+      peas_engine_prepend_search_path (engine,
+                                       PACKAGE_LIBDIR"/gnome-builder/plugins",
+                                       PACKAGE_DATADIR"/gnome-builder/plugins");
+    }
+
+  list = peas_engine_get_plugin_list (engine);
+
+  for (; list; list = list->next)
+    {
+      if (peas_plugin_info_is_builtin (list->data))
+        peas_engine_load_plugin (engine, list->data);
+    }
+}
+
 gint
 main (gint   argc,
       gchar *argv[])
@@ -308,6 +356,8 @@ main (gint   argc,
       return EXIT_FAILURE;
     }
 
+  load_plugins ();
+
   gFile = g_file_new_for_path (path);
 
   project_file = g_file_new_for_path (project_path);


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