[gnome-builder/wip/symbol-tree: 7/9] symbol-tree: add plumbing for building tree nodes



commit 325282b84072267a7994eb026f8ad214be3ee185
Author: Christian Hergert <christian hergert me>
Date:   Thu Jun 18 04:37:45 2015 -0700

    symbol-tree: add plumbing for building tree nodes

 plugins/symbol-tree/Makefile.am           |    1 +
 plugins/symbol-tree/symbol-tree-builder.c |   76 +++++++++++++++-
 plugins/symbol-tree/symbol-tree.c         |  133 +++++++++++++++++++++++++++--
 3 files changed, 199 insertions(+), 11 deletions(-)
---
diff --git a/plugins/symbol-tree/Makefile.am b/plugins/symbol-tree/Makefile.am
index 89e0172..55c8217 100644
--- a/plugins/symbol-tree/Makefile.am
+++ b/plugins/symbol-tree/Makefile.am
@@ -25,6 +25,7 @@ libsymbol_tree_la_CFLAGS = \
        -I$(top_srcdir)/src/workbench \
        -I$(top_srcdir)/src/workspace \
        -I$(top_srcdir)/libide \
+       -I$(top_srcdir)/contrib/egg \
        $(NULL)
 
 libsymbol_tree_la_LIBADD = \
diff --git a/plugins/symbol-tree/symbol-tree-builder.c b/plugins/symbol-tree/symbol-tree-builder.c
index 17c1d89..2b45827 100644
--- a/plugins/symbol-tree/symbol-tree-builder.c
+++ b/plugins/symbol-tree/symbol-tree-builder.c
@@ -18,6 +18,8 @@
 
 #include <glib/gi18n.h>
 
+#include "gb-tree.h"
+
 #include "symbol-tree-builder.h"
 
 struct _SymbolTreeBuilder
@@ -31,24 +33,88 @@ static void
 symbol_tree_builder_build_node (GbTreeBuilder *builder,
                                 GbTreeNode    *node)
 {
+  IdeSymbolNode *parent = NULL;
+  IdeSymbolTree *symbol_tree;
+  GbTree *tree;
+  GbTreeNode *root;
   GObject *item;
+  guint n_children;
+  guint i;
 
   g_assert (GB_IS_TREE_BUILDER (builder));
   g_assert (GB_IS_TREE_NODE (node));
 
+  if (!(tree = gb_tree_builder_get_tree (builder)) ||
+      !(root = gb_tree_get_root (tree)) ||
+      !(symbol_tree = IDE_SYMBOL_TREE (gb_tree_node_get_item (root))))
+    return;
+
   item = gb_tree_node_get_item (node);
 
-  if (GB_IS_EDITOR_DOCUMENT (item))
+  if (IDE_IS_SYMBOL_NODE (item))
+    parent = IDE_SYMBOL_NODE (item);
+
+  n_children = ide_symbol_tree_get_n_children (symbol_tree, parent);
+
+  for (i = 0; i < n_children; i++)
     {
-#if 0
+      g_autoptr(IdeSymbolNode) symbol = NULL;
+      const gchar *name;
+      const gchar *icon_name = NULL;
       GbTreeNode *child;
+      IdeSymbolKind kind;
+
+      symbol = ide_symbol_tree_get_nth_child (symbol_tree, parent, i);
+      name = ide_symbol_node_get_name (symbol);
+      kind = ide_symbol_node_get_kind (symbol);
+
+      switch (kind)
+        {
+        case IDE_SYMBOL_FUNCTION:
+          icon_name = "lang-function-symbolic";
+          break;
+
+        case IDE_SYMBOL_ENUM:
+          icon_name = "lang-enum-symbolic";
+          break;
+
+        case IDE_SYMBOL_ENUM_VALUE:
+          icon_name = "lang-enum-value-symbolic";
+          break;
+
+        case IDE_SYMBOL_STRUCT:
+          icon_name = "lang-struct-symbolic";
+          break;
+
+        case IDE_SYMBOL_CLASS:
+          icon_name = "lang-class-symbolic";
+          break;
+
+        case IDE_SYMBOL_METHOD:
+          icon_name = "lang-method-symbolic";
+          break;
+
+        case IDE_SYMBOL_UNION:
+          icon_name = "lang-union-symbolic";
+          break;
+
+        case IDE_SYMBOL_SCALAR:
+        case IDE_SYMBOL_FIELD:
+          icon_name = "lang-variable-symbolic";
+          break;
+
+        case IDE_SYMBOL_NONE:
+        default:
+          icon_name = NULL;
+          break;
+        }
 
       child = g_object_new (GB_TYPE_TREE_NODE,
-                            "text", _("Symbols"),
-                            "icon-name", "lang-class-symbolic",
+                            "text", name,
+                            "icon-name", icon_name,
+                            "item", symbol,
                             NULL);
       gb_tree_node_append (node, child);
-#endif
     }
 }
 
diff --git a/plugins/symbol-tree/symbol-tree.c b/plugins/symbol-tree/symbol-tree.c
index 04c6438..fd6517c 100644
--- a/plugins/symbol-tree/symbol-tree.c
+++ b/plugins/symbol-tree/symbol-tree.c
@@ -19,6 +19,7 @@
 #include <glib/gi18n.h>
 #include <libpeas/peas.h>
 
+#include "egg-task-cache.h"
 
 #include "gb-editor-view.h"
 #include "gb-plugins.h"
@@ -31,10 +32,12 @@
 
 struct _SymbolTree
 {
-  GtkBox       parent_instance;
+  GtkBox        parent_instance;
 
-  GbWorkbench *workbench;
-  GbTree      *tree;
+  GCancellable *cancellable;
+  EggTaskCache *symbols_cache;
+  GbWorkbench  *workbench;
+  GbTree       *tree;
 };
 
 enum {
@@ -51,6 +54,34 @@ G_DEFINE_TYPE_WITH_CODE (SymbolTree, symbol_tree, GTK_TYPE_BOX,
                          G_IMPLEMENT_INTERFACE (GB_TYPE_WORKBENCH_ADDIN, workbench_addin_init))
 
 static void
+get_cached_symbol_tree_cb (GObject      *object,
+                           GAsyncResult *result,
+                           gpointer      user_data)
+{
+  EggTaskCache *cache = (EggTaskCache *)object;
+  g_autoptr(SymbolTree) self = user_data;
+  g_autoptr(IdeSymbolTree) symbol_tree = NULL;
+  g_autoptr(GError) error = NULL;
+  GbTreeNode *root;
+
+  g_assert (EGG_IS_TASK_CACHE (cache));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (SYMBOL_IS_TREE (self));
+
+  if (!(symbol_tree = egg_task_cache_get_finish (cache, result, &error)))
+    {
+      if (!g_error_matches (error, G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED))
+        g_warning ("%s", error->message);
+      return;
+    }
+
+  root = g_object_new (GB_TYPE_TREE_NODE,
+                       "item", symbol_tree,
+                       NULL);
+  gb_tree_set_root (self->tree, root);
+}
+
+static void
 notify_active_view_cb (SymbolTree  *self,
                        GParamFlags *pspec,
                        GbWorkbench *workbench)
@@ -70,9 +101,87 @@ notify_active_view_cb (SymbolTree  *self,
 
   if ((GObject *)document != gb_tree_node_get_item (root))
     {
-      root = gb_tree_node_new ();
-      gb_tree_node_set_item (root, G_OBJECT (document));
-      gb_tree_set_root (self->tree, root);
+      /*
+       * First, clear the old tree items.
+       */
+      gb_tree_set_root (self->tree, gb_tree_node_new ());;
+
+      /*
+       * Fetch the symbols via the transparent cache.
+       */
+      if (document != NULL)
+        {
+          if (self->cancellable != NULL)
+            {
+              g_cancellable_cancel (self->cancellable);
+              g_clear_object (&self->cancellable);
+            }
+
+          self->cancellable = g_cancellable_new ();
+
+          egg_task_cache_get_async (self->symbols_cache,
+                                    document,
+                                    FALSE,
+                                    self->cancellable,
+                                    get_cached_symbol_tree_cb,
+                                    g_object_ref (self));
+        }
+    }
+}
+
+static void
+get_symbol_tree_cb (GObject      *object,
+                    GAsyncResult *result,
+                    gpointer      user_data)
+{
+  IdeSymbolResolver *resolver = (IdeSymbolResolver *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(IdeSymbolTree) symbol_tree = NULL;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_SYMBOL_RESOLVER (resolver));
+  g_assert (G_IS_ASYNC_RESULT (result));
+  g_assert (G_IS_TASK (task));
+
+  symbol_tree = ide_symbol_resolver_get_symbol_tree_finish (resolver, result, &error);
+
+  if (!symbol_tree)
+    g_task_return_error (task, error);
+  else
+    g_task_return_pointer (task, g_object_ref (symbol_tree), g_object_unref);
+}
+
+static void
+populate_cache_cb (EggTaskCache  *cache,
+                   gconstpointer  key,
+                   GTask         *task,
+                   gpointer       user_data)
+{
+  GbEditorDocument *document = (GbEditorDocument *)key;
+  IdeLanguage *language;
+  IdeFile *file;
+  IdeSymbolResolver *resolver;
+
+  g_assert (EGG_IS_TASK_CACHE (cache));
+  g_assert (GB_IS_EDITOR_DOCUMENT (document));
+  g_assert (G_IS_TASK (task));
+
+  if ((file = ide_buffer_get_file (IDE_BUFFER (document))) &&
+      (language = ide_file_get_language (file)) &&
+      (resolver = ide_language_get_symbol_resolver (language)))
+    {
+      ide_symbol_resolver_get_symbol_tree_async (resolver,
+                                                 ide_file_get_file (file),
+                                                 g_task_get_cancellable (task),
+                                                 get_symbol_tree_cb,
+                                                 g_object_ref (task));
+    }
+  else
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_NOT_SUPPORTED,
+                               _("Current language does not support symbol resolvers"));
     }
 }
 
@@ -150,6 +259,7 @@ symbol_tree_finalize (GObject *object)
   SymbolTree *self = (SymbolTree *)object;
 
   ide_clear_weak_pointer (&self->workbench);
+  g_clear_object (&self->cancellable);
 
   G_OBJECT_CLASS (symbol_tree_parent_class)->finalize (object);
 }
@@ -191,6 +301,17 @@ symbol_tree_init (SymbolTree *self)
   GbTreeNode *root;
   GbTreeBuilder *builder;
 
+  self->symbols_cache = egg_task_cache_new (g_direct_hash,
+                                            g_direct_equal,
+                                            g_object_ref,
+                                            g_object_unref,
+                                            g_object_ref,
+                                            g_object_unref,
+                                            G_USEC_PER_SEC * 20L,
+                                            populate_cache_cb,
+                                            self,
+                                            NULL);
+
   gtk_widget_init_template (GTK_WIDGET (self));
 
   root = gb_tree_node_new ();


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