[gnome-builder/wip/chergert/langserv] langserv: add symbol tree support to langserv symbol resolver



commit b54753e9f7ad658a0e7da250e24821d91d7fcab1
Author: Christian Hergert <chergert redhat com>
Date:   Tue Oct 25 04:51:08 2016 -0700

    langserv: add symbol tree support to langserv symbol resolver
    
    We still need to implement the Tree portion of this (right now it is a
    flattened list), but that should be easy enough based on the container
    type (for languages that support it).

 libide/Makefile.am                                 |    6 +
 libide/langserv/ide-langserv-symbol-node-private.h |   37 +++++
 libide/langserv/ide-langserv-symbol-node.c         |  171 ++++++++++++++++++++
 libide/langserv/ide-langserv-symbol-node.h         |   32 ++++
 libide/langserv/ide-langserv-symbol-resolver.c     |  167 +++++++++++++++++++
 libide/langserv/ide-langserv-symbol-tree-private.h |   30 ++++
 libide/langserv/ide-langserv-symbol-tree.c         |  124 ++++++++++++++
 libide/langserv/ide-langserv-symbol-tree.h         |   32 ++++
 8 files changed, 599 insertions(+), 0 deletions(-)
---
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 8621892..acbecca 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -72,7 +72,9 @@ libide_1_0_la_public_headers =                            \
        langserv/ide-langserv-client.h                    \
        langserv/ide-langserv-completion-provider.h       \
        langserv/ide-langserv-diagnostic-provider.h       \
+       langserv/ide-langserv-symbol-node.h               \
        langserv/ide-langserv-symbol-resolver.h           \
+       langserv/ide-langserv-symbol-tree.h               \
        local/ide-local-device.h                          \
        logging/ide-log.h                                 \
        plugins/ide-extension-adapter.h                   \
@@ -245,7 +247,11 @@ libide_1_0_la_public_sources =                            \
        langserv/ide-langserv-client.c                    \
        langserv/ide-langserv-completion-provider.c       \
        langserv/ide-langserv-diagnostic-provider.c       \
+       langserv/ide-langserv-symbol-node.c               \
+       langserv/ide-langserv-symbol-node-private.h       \
        langserv/ide-langserv-symbol-resolver.c           \
+       langserv/ide-langserv-symbol-tree.c               \
+       langserv/ide-langserv-symbol-tree-private.h       \
        local/ide-local-device.c                          \
        logging/ide-log.c                                 \
        plugins/ide-extension-adapter.c                   \
diff --git a/libide/langserv/ide-langserv-symbol-node-private.h 
b/libide/langserv/ide-langserv-symbol-node-private.h
new file mode 100644
index 0000000..8482672
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-node-private.h
@@ -0,0 +1,37 @@
+/* ide-langserv-symbol-node-private.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef IDE_LANGSERV_SYMBOL_NODE_PRIVATE_H
+#define IDE_LANGSERV_SYMBOL_NODE_PRIVATE_H
+
+#include "ide-langserv-symbol-node.h"
+
+G_BEGIN_DECLS
+
+IdeLangservSymbolNode *ide_langserv_symbol_node_new (GFile       *file,
+                                                     const gchar *name,
+                                                     const gchar *parent_name,
+                                                     gint         kind,
+                                                     guint        begin_line,
+                                                     guint        begin_column,
+                                                     guint        end_line,
+                                                     guint        end_column);
+
+G_END_DECLS
+
+#endif /* IDE_LANGSERV_SYMBOL_NODE_PRIVATE_H */
diff --git a/libide/langserv/ide-langserv-symbol-node.c b/libide/langserv/ide-langserv-symbol-node.c
new file mode 100644
index 0000000..b35885c
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-node.c
@@ -0,0 +1,171 @@
+/* ide-langserv-symbol-node.c
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-langserv-symbol-node"
+
+#include "ide-debug.h"
+
+#include "diagnostics/ide-source-location.h"
+#include "files/ide-file.h"
+#include "langserv/ide-langserv-symbol-node.h"
+
+typedef struct
+{
+  GFile *file;
+  gchar *parent_name;
+  IdeSymbolKind kind;
+  struct {
+    guint line;
+    guint column;
+  } begin, end;
+} IdeLangservSymbolNodePrivate;
+
+struct _IdeLangservSymbolNode
+{
+  IdeSymbolNode parent_instance;
+};
+
+G_DEFINE_TYPE_WITH_PRIVATE (IdeLangservSymbolNode, ide_langserv_symbol_node, IDE_TYPE_SYMBOL_NODE)
+
+static void
+ide_langserv_symbol_node_get_location_async (IdeSymbolNode       *node,
+                                             GCancellable        *cancellable,
+                                             GAsyncReadyCallback  callback,
+                                             gpointer             user_data)
+{
+  IdeLangservSymbolNode *self = (IdeLangservSymbolNode *)node;
+  IdeLangservSymbolNodePrivate *priv = ide_langserv_symbol_node_get_instance_private (self);
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(IdeFile) ifile = NULL;
+  g_autoptr(IdeSourceLocation) location = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_LANGSERV_SYMBOL_NODE (node));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_langserv_symbol_node_get_location_async);
+
+  ifile = ide_file_new (NULL, priv->file);
+  location = ide_source_location_new (ifile, priv->begin.line, priv->begin.column, 0);
+
+  g_task_return_pointer (task, g_steal_pointer (&location), (GDestroyNotify)ide_source_location_unref);
+
+  IDE_EXIT;
+}
+
+static IdeSourceLocation *
+ide_langserv_symbol_node_get_location_finish (IdeSymbolNode  *node,
+                                              GAsyncResult   *result,
+                                              GError        **error)
+{
+  IdeSourceLocation *ret;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_LANGSERV_SYMBOL_NODE (node));
+  g_assert (G_IS_TASK (result));
+
+  ret = g_task_propagate_pointer (G_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+ide_langserv_symbol_node_finalize (GObject *object)
+{
+  IdeLangservSymbolNode *self = (IdeLangservSymbolNode *)object;
+  IdeLangservSymbolNodePrivate *priv = ide_langserv_symbol_node_get_instance_private (self);
+
+  g_clear_pointer (&priv->parent_name, g_free);
+  g_clear_object (&priv->file);
+
+  G_OBJECT_CLASS (ide_langserv_symbol_node_parent_class)->finalize (object);
+}
+
+static void
+ide_langserv_symbol_node_class_init (IdeLangservSymbolNodeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeSymbolNodeClass *symbol_node_class = IDE_SYMBOL_NODE_CLASS (klass);
+
+  object_class->finalize = ide_langserv_symbol_node_finalize;
+
+  symbol_node_class->get_location_async = ide_langserv_symbol_node_get_location_async;
+  symbol_node_class->get_location_finish = ide_langserv_symbol_node_get_location_finish;
+}
+
+static void
+ide_langserv_symbol_node_init (IdeLangservSymbolNode *self)
+{
+}
+
+IdeLangservSymbolNode *
+ide_langserv_symbol_node_new (GFile       *file,
+                              const gchar *name,
+                              const gchar *parent_name,
+                              gint         kind,
+                              guint        begin_line,
+                              guint        begin_column,
+                              guint        end_line,
+                              guint        end_column)
+{
+  IdeLangservSymbolNode *self;
+  IdeLangservSymbolNodePrivate *priv;
+
+  g_return_val_if_fail (G_IS_FILE (file), NULL);
+
+  switch (kind)
+    {
+    case 1:   kind = IDE_SYMBOL_FILE;         break;
+    case 2:   kind = IDE_SYMBOL_MODULE;       break;
+    case 3:   kind = IDE_SYMBOL_NAMESPACE;    break;
+    case 4:   kind = IDE_SYMBOL_PACKAGE;      break;
+    case 5:   kind = IDE_SYMBOL_CLASS;        break;
+    case 6:   kind = IDE_SYMBOL_METHOD;       break;
+    case 7:   kind = IDE_SYMBOL_PROPERTY;     break;
+    case 8:   kind = IDE_SYMBOL_FIELD;        break;
+    case 9:   kind = IDE_SYMBOL_CONSTRUCTOR;  break;
+    case 10:  kind = IDE_SYMBOL_ENUM;         break;
+    case 11:  kind = IDE_SYMBOL_INTERFACE;    break;
+    case 12:  kind = IDE_SYMBOL_FUNCTION;     break;
+    case 13:  kind = IDE_SYMBOL_VARIABLE;     break;
+    case 14:  kind = IDE_SYMBOL_CONSTANT;     break;
+    case 15:  kind = IDE_SYMBOL_STRING;       break;
+    case 16:  kind = IDE_SYMBOL_NUMBER;       break;
+    case 17:  kind = IDE_SYMBOL_BOOLEAN;      break;
+    case 18:  kind = IDE_SYMBOL_ARRAY;        break;
+    default:  kind = IDE_SYMBOL_NONE;         break;
+    }
+
+  self = g_object_new (IDE_TYPE_LANGSERV_SYMBOL_NODE,
+                       "flags", 0,
+                       "kind", kind,
+                       "name", name,
+                       NULL);
+  priv = ide_langserv_symbol_node_get_instance_private (self);
+
+  priv->file = g_object_ref (file);
+  priv->parent_name = g_strdup (parent_name);
+  priv->begin.line = begin_line;
+  priv->begin.column = begin_column;
+  priv->end.line = end_line;
+  priv->end.column = end_column;
+
+  return self;
+}
diff --git a/libide/langserv/ide-langserv-symbol-node.h b/libide/langserv/ide-langserv-symbol-node.h
new file mode 100644
index 0000000..5e12c8a
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-node.h
@@ -0,0 +1,32 @@
+/* ide-langserv-symbol-node.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef IDE_LANGSERV_SYMBOL_NODE_H
+#define IDE_LANGSERV_SYMBOL_NODE_H
+
+#include "symbols/ide-symbol-node.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LANGSERV_SYMBOL_NODE (ide_langserv_symbol_node_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeLangservSymbolNode, ide_langserv_symbol_node, IDE, LANGSERV_SYMBOL_NODE, 
IdeSymbolNode)
+
+G_END_DECLS
+
+#endif /* IDE_LANGSERV_SYMBOL_NODE_H */
diff --git a/libide/langserv/ide-langserv-symbol-resolver.c b/libide/langserv/ide-langserv-symbol-resolver.c
index ab125dc..290a6ac 100644
--- a/libide/langserv/ide-langserv-symbol-resolver.c
+++ b/libide/langserv/ide-langserv-symbol-resolver.c
@@ -24,7 +24,11 @@
 
 #include "diagnostics/ide-source-location.h"
 #include "files/ide-file.h"
+#include "langserv/ide-langserv-symbol-node.h"
+#include "langserv/ide-langserv-symbol-node-private.h"
 #include "langserv/ide-langserv-symbol-resolver.h"
+#include "langserv/ide-langserv-symbol-tree.h"
+#include "langserv/ide-langserv-symbol-tree-private.h"
 
 typedef struct
 {
@@ -283,8 +287,171 @@ ide_langserv_symbol_resolver_lookup_symbol_finish (IdeSymbolResolver  *resolver,
 }
 
 static void
+ide_langserv_symbol_resolver_document_symbol_cb (GObject      *object,
+                                                 GAsyncResult *result,
+                                                 gpointer      user_data)
+{
+  IdeLangservClient *client = (IdeLangservClient *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(IdeLangservSymbolTree) tree = NULL;
+  g_autoptr(GError) error = NULL;
+  g_autoptr(JsonNode) return_value = NULL;
+  g_autoptr(GPtrArray) symbols = NULL;
+  JsonArray *array;
+  guint length;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_LANGSERV_CLIENT (client));
+  g_assert (G_IS_TASK (task));
+
+  if (!ide_langserv_client_call_finish (client, result, &return_value, &error))
+    {
+      g_task_return_error (task, g_steal_pointer (&error));
+      IDE_EXIT;
+    }
+
+  if (!JSON_NODE_HOLDS_ARRAY (return_value) ||
+      NULL == (array = json_node_get_array (return_value)))
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_INVALID_DATA,
+                               "Invalid result for textDocument/documentSymbol");
+      IDE_EXIT;
+    }
+
+  length = json_array_get_length (array);
+
+  symbols = g_ptr_array_new_with_free_func (g_object_unref);
+
+  for (guint i = 0; i < length; i++)
+    {
+      JsonNode *node = json_array_get_element (array, i);
+      g_autoptr(IdeLangservSymbolNode) symbol = NULL;
+      g_autoptr(GFile) file = NULL;
+      const gchar *name = NULL;
+      const gchar *container_name = NULL;
+      const gchar *uri = NULL;
+      gboolean success;
+      gint kind = -1;
+      struct {
+        gint line;
+        gint column;
+      } begin, end;
+
+      /* Mandatory fields */
+      success = JCON_EXTRACT (node,
+        "name", JCONE_STRING (name),
+        "kind", JCONE_INT (kind),
+        "location", "{",
+          "uri", JCONE_STRING (uri),
+          "range", "{",
+            "start", "{",
+              "line", JCONE_INT (begin.line),
+              "character", JCONE_INT (begin.column),
+            "}",
+            "end", "{",
+              "line", JCONE_INT (end.line),
+              "character", JCONE_INT (end.column),
+            "}",
+          "}",
+        "}"
+      );
+
+      if (!success)
+        continue;
+
+      /* Optional fields */
+      JCON_EXTRACT (node, "containerName", &container_name);
+
+      file = g_file_new_for_uri (uri);
+
+      symbol = ide_langserv_symbol_node_new (file, name, container_name, kind,
+                                             begin.line, begin.column,
+                                             end.line, end.column);
+
+      g_ptr_array_add (symbols, g_steal_pointer (&symbol));
+    }
+
+  tree = ide_langserv_symbol_tree_new (g_steal_pointer (&symbols));
+
+  g_task_return_pointer (task, g_steal_pointer (&tree), g_object_unref);
+
+  IDE_EXIT;
+}
+
+static void
+ide_langserv_symbol_resolver_get_symbol_tree_async (IdeSymbolResolver   *resolver,
+                                                    GFile               *file,
+                                                    GCancellable        *cancellable,
+                                                    GAsyncReadyCallback  callback,
+                                                    gpointer             user_data)
+{
+  IdeLangservSymbolResolver *self = (IdeLangservSymbolResolver *)resolver;
+  IdeLangservSymbolResolverPrivate *priv = ide_langserv_symbol_resolver_get_instance_private (self);
+  g_autoptr(GTask) task = NULL;
+  g_autoptr(JsonNode) params = NULL;
+  g_autofree gchar *uri = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_LANGSERV_SYMBOL_RESOLVER (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_langserv_symbol_resolver_get_symbol_tree_async);
+
+  if (priv->client == NULL)
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_NOT_CONNECTED,
+                               "Cannot query language server, not connected");
+      IDE_EXIT;
+    }
+
+  uri = g_file_get_uri (file);
+
+  params = JCON_NEW (
+    "textDocument", "{",
+      "uri", JCON_STRING (uri),
+    "}"
+  );
+
+  ide_langserv_client_call_async (priv->client,
+                                  "textDocument/documentSymbol",
+                                  g_steal_pointer (&params),
+                                  cancellable,
+                                  ide_langserv_symbol_resolver_document_symbol_cb,
+                                  g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+static IdeSymbolTree *
+ide_langserv_symbol_resolver_get_symbol_tree_finish (IdeSymbolResolver  *resolver,
+                                                     GAsyncResult       *result,
+                                                     GError            **error)
+{
+  IdeSymbolTree *ret;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_LANGSERV_SYMBOL_RESOLVER (resolver), NULL);
+  g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+  ret = g_task_propagate_pointer (G_TASK (result), error);
+
+  IDE_RETURN (ret);
+}
+
+static void
 symbol_resolver_iface_init (IdeSymbolResolverInterface *iface)
 {
   iface->lookup_symbol_async = ide_langserv_symbol_resolver_lookup_symbol_async;
   iface->lookup_symbol_finish = ide_langserv_symbol_resolver_lookup_symbol_finish;
+  iface->get_symbol_tree_async = ide_langserv_symbol_resolver_get_symbol_tree_async;
+  iface->get_symbol_tree_finish = ide_langserv_symbol_resolver_get_symbol_tree_finish;
 }
diff --git a/libide/langserv/ide-langserv-symbol-tree-private.h 
b/libide/langserv/ide-langserv-symbol-tree-private.h
new file mode 100644
index 0000000..4c9afe1
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-tree-private.h
@@ -0,0 +1,30 @@
+/* ide-langserv-symbol-tree-private.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef IDE_LANGSERV_SYMBOL_TREE_PRIVATE_H
+#define IDE_LANGSERV_SYMBOL_TREE_PRIVATE_H
+
+#include "ide-langserv-symbol-tree.h"
+
+G_BEGIN_DECLS
+
+IdeLangservSymbolTree *ide_langserv_symbol_tree_new (GPtrArray *symbols);
+
+G_END_DECLS
+
+#endif /* IDE_LANGSERV_SYMBOL_TREE_PRIVATE_H */
diff --git a/libide/langserv/ide-langserv-symbol-tree.c b/libide/langserv/ide-langserv-symbol-tree.c
new file mode 100644
index 0000000..07eaf29
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-tree.c
@@ -0,0 +1,124 @@
+/* ide-langserv-symbol-tree.c
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#define G_LOG_DOMAIN "ide-langserv-symbol-tree"
+
+#include "ide-langserv-symbol-tree.h"
+
+typedef struct
+{
+  GPtrArray *symbols;
+} IdeLangservSymbolTreePrivate;
+
+struct _IdeLangservSymbolTree
+{
+  GObject parent_instance;
+};
+
+static void symbol_tree_iface_init (IdeSymbolTreeInterface *iface);
+
+G_DEFINE_TYPE_WITH_CODE (IdeLangservSymbolTree, ide_langserv_symbol_tree, G_TYPE_OBJECT,
+                         G_ADD_PRIVATE (IdeLangservSymbolTree)
+                         G_IMPLEMENT_INTERFACE (IDE_TYPE_SYMBOL_TREE, symbol_tree_iface_init))
+
+static guint
+ide_langserv_symbol_tree_get_n_children (IdeSymbolTree *tree,
+                                         IdeSymbolNode *parent)
+{
+  IdeLangservSymbolTree *self = (IdeLangservSymbolTree *)tree;
+  IdeLangservSymbolTreePrivate *priv = ide_langserv_symbol_tree_get_instance_private (self);
+
+  g_assert (IDE_IS_LANGSERV_SYMBOL_TREE (self));
+  g_assert (!parent || IDE_IS_SYMBOL_NODE (parent));
+
+  /* TODO: FIXME: XXX: Take symbol parent into account */
+
+  if (parent != NULL)
+    return 0;
+
+  return priv->symbols->len;
+}
+
+static IdeSymbolNode *
+ide_langserv_symbol_tree_get_nth_child (IdeSymbolTree *tree,
+                                        IdeSymbolNode *parent,
+                                        guint          nth)
+{
+  IdeLangservSymbolTree *self = (IdeLangservSymbolTree *)tree;
+  IdeLangservSymbolTreePrivate *priv = ide_langserv_symbol_tree_get_instance_private (self);
+
+  g_return_val_if_fail (IDE_IS_LANGSERV_SYMBOL_TREE (self), NULL);
+  g_return_val_if_fail (!parent || IDE_IS_SYMBOL_NODE (parent), NULL);
+  g_return_val_if_fail (nth < priv->symbols->len, NULL);
+
+  return g_object_ref (g_ptr_array_index (priv->symbols, nth));
+}
+
+static void
+symbol_tree_iface_init (IdeSymbolTreeInterface *iface)
+{
+  iface->get_n_children = ide_langserv_symbol_tree_get_n_children;
+  iface->get_nth_child = ide_langserv_symbol_tree_get_nth_child;
+}
+
+static void
+ide_langserv_symbol_tree_finalize (GObject *object)
+{
+  IdeLangservSymbolTree *self = (IdeLangservSymbolTree *)object;
+  IdeLangservSymbolTreePrivate *priv = ide_langserv_symbol_tree_get_instance_private (self);
+
+  g_clear_pointer (&priv->symbols, g_ptr_array_unref);
+
+  G_OBJECT_CLASS (ide_langserv_symbol_tree_parent_class)->finalize (object);
+}
+
+static void
+ide_langserv_symbol_tree_class_init (IdeLangservSymbolTreeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_langserv_symbol_tree_finalize;
+}
+
+static void
+ide_langserv_symbol_tree_init (IdeLangservSymbolTree *self)
+{
+}
+
+/**
+ * ide_langserv_symbol_tree_new:
+ * @symbols: (transfer container) (element-type Ide.LangservSymbolNode): The symbols
+ *
+ * Creates a new #IdeLangservSymbolTree but takes ownership of @ar.
+ *
+ * Returns: (transfer full): A newly allocated #IdeLangservSymbolTree.
+ */
+IdeLangservSymbolTree *
+ide_langserv_symbol_tree_new (GPtrArray *symbols)
+{
+  IdeLangservSymbolTreePrivate *priv;
+  IdeLangservSymbolTree *self;
+
+  g_return_val_if_fail (symbols != NULL, NULL);
+
+  self = g_object_new (IDE_TYPE_LANGSERV_SYMBOL_TREE, NULL);
+  priv = ide_langserv_symbol_tree_get_instance_private (self);
+  priv->symbols = symbols;
+
+  return self;
+}
diff --git a/libide/langserv/ide-langserv-symbol-tree.h b/libide/langserv/ide-langserv-symbol-tree.h
new file mode 100644
index 0000000..9457334
--- /dev/null
+++ b/libide/langserv/ide-langserv-symbol-tree.h
@@ -0,0 +1,32 @@
+/* ide-langserv-symbol-tree.h
+ *
+ * Copyright (C) 2016 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/>.
+ */
+
+#ifndef IDE_LANGSERV_SYMBOL_TREE_H
+#define IDE_LANGSERV_SYMBOL_TREE_H
+
+#include "symbols/ide-symbol-tree.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_LANGSERV_SYMBOL_TREE (ide_langserv_symbol_tree_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeLangservSymbolTree, ide_langserv_symbol_tree, IDE, LANGSERV_SYMBOL_TREE, GObject)
+
+G_END_DECLS
+
+#endif /* IDE_LANGSERV_SYMBOL_TREE_H */


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