[gnome-builder/wip/slaf/xml-symbol-resolver: 1/25] xml-pack: add a symbol resolver



commit c8207b992117c628fd41fe755e9b604ce918b4e9
Author: Sébastien Lafargue <slafargue gnome org>
Date:   Thu Jan 12 23:33:46 2017 +0100

    xml-pack: add a symbol resolver

 contrib/xml/Makefile.am                    |   20 +-
 libide/Makefile.am                         |    2 +-
 plugins/color-picker/gtk/color-picker.ui   |    1 +
 plugins/symbol-tree/symbol-tree.h          |    3 +-
 plugins/xml-pack/Makefile.am               |    8 +
 plugins/xml-pack/ide-xml-service.c         |  525 ++++++++++++++++++++++++++++
 plugins/xml-pack/ide-xml-service.h         |   47 +++
 plugins/xml-pack/ide-xml-symbol-node.c     |  184 ++++++++++
 plugins/xml-pack/ide-xml-symbol-node.h     |   45 +++
 plugins/xml-pack/ide-xml-symbol-resolver.c |  193 ++++++++++
 plugins/xml-pack/ide-xml-symbol-resolver.h |   32 ++
 plugins/xml-pack/ide-xml-symbol-tree.c     |  123 +++++++
 plugins/xml-pack/ide-xml-symbol-tree.h     |   35 ++
 plugins/xml-pack/xml-pack-plugin.c         |    8 +
 plugins/xml-pack/xml-pack.plugin           |    4 +-
 15 files changed, 1223 insertions(+), 7 deletions(-)
---
diff --git a/contrib/xml/Makefile.am b/contrib/xml/Makefile.am
index 96d8568..2263449 100644
--- a/contrib/xml/Makefile.am
+++ b/contrib/xml/Makefile.am
@@ -1,11 +1,23 @@
-noinst_LTLIBRARIES = libxml.la
+pkglibdir = $(libdir)/gnome-builder
+pkglib_LTLIBRARIES = libxml-private.la
 
-libxml_la_SOURCES = \
+libxml_private_la_SOURCES = \
        xml-reader.c \
        xml-reader.h \
        $(NULL)
 
-libxml_la_CFLAGS = $(XML_CFLAGS)
-libxml_la_LIBADD = $(XML_LIBS)
+libxml_private_la_CFLAGS = \
+       $(DEBUG_CFLAGS) \
+       $(OPTIMIZE_CFLAGS) \
+       $(XML_CFLAGS) \
+       $(NULL)
+
+libxml_private_la_LIBADD = \
+       $(XML_LIBS)
+       $(NULL)
+
+libxml_private_la_LDFLAGS = \
+       $(OPTIMIZE_LDFLAGS) \
+       $(NULL)
 
 -include $(top_srcdir)/git.mk
diff --git a/libide/Makefile.am b/libide/Makefile.am
index 1839c33..7b4408f 100644
--- a/libide/Makefile.am
+++ b/libide/Makefile.am
@@ -565,7 +565,7 @@ libide_1_0_la_LIBADD =                                          \
        $(top_builddir)/contrib/pnl/libpanel-gtk.la             \
        $(top_builddir)/contrib/search/libsearch.la             \
        $(top_builddir)/contrib/tmpl/libtemplate-glib-1.0.la    \
-       $(top_builddir)/contrib/xml/libxml.la                   \
+       $(top_builddir)/contrib/xml/libxml-private.la                   \
        $(NULL)
 
 if ENABLE_WEBKIT
diff --git a/plugins/color-picker/gtk/color-picker.ui b/plugins/color-picker/gtk/color-picker.ui
index 557825e..4a350a2 100644
--- a/plugins/color-picker/gtk/color-picker.ui
+++ b/plugins/color-picker/gtk/color-picker.ui
@@ -18,6 +18,7 @@
         <property name="expand">true</property>
       </packing>
     </child>
+    <child></child>
     <child>
       <object class="GstylePaletteWidget" id="palette_widget">
         <property name="visible">1</property>
diff --git a/plugins/symbol-tree/symbol-tree.h b/plugins/symbol-tree/symbol-tree.h
index e2e3a4f..1e3b720 100644
--- a/plugins/symbol-tree/symbol-tree.h
+++ b/plugins/symbol-tree/symbol-tree.h
@@ -20,12 +20,13 @@
 #define SYMBOL_TREE_H
 
 #include <glib-object.h>
+#include <ide.h>
 
 G_BEGIN_DECLS
 
 #define SYMBOL_TYPE_TREE (symbol_tree_get_type())
 
-G_DECLARE_FINAL_TYPE (SymbolTree, symbol_tree, SYMBOL, TREE, GObject)
+G_DECLARE_FINAL_TYPE (SymbolTree, symbol_tree, SYMBOL, TREE, IdeObject)
 
 G_END_DECLS
 
diff --git a/plugins/xml-pack/Makefile.am b/plugins/xml-pack/Makefile.am
index c700f64..a4de185 100644
--- a/plugins/xml-pack/Makefile.am
+++ b/plugins/xml-pack/Makefile.am
@@ -11,6 +11,14 @@ libxml_pack_plugin_la_SOURCES = \
        ide-xml-highlighter.h \
        ide-xml-indenter.c \
        ide-xml-indenter.h \
+       ide-xml-service.c \
+       ide-xml-service.h \
+       ide-xml-symbol-node.c \
+       ide-xml-symbol-node.h \
+       ide-xml-symbol-resolver.c \
+       ide-xml-symbol-resolver.h \
+       ide-xml-symbol-tree.c \
+       ide-xml-symbol-tree.h \
        ide-xml.c \
        ide-xml.h \
        xml-pack-plugin.c \
diff --git a/plugins/xml-pack/ide-xml-service.c b/plugins/xml-pack/ide-xml-service.c
new file mode 100644
index 0000000..cefce65
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-service.c
@@ -0,0 +1,525 @@
+/* ide-xml-service.c
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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-xml-service"
+
+#include <egg-task-cache.h>
+#include <glib/gi18n.h>
+#include <gtksourceview/gtksource.h>
+#include <math.h>
+
+#include "ide-xml-service.h"
+#include "xml-reader.h"
+
+#define DEFAULT_EVICTION_MSEC (60 * 1000)
+
+typedef GPtrArray IdeXmlStack;
+
+static inline IdeXmlStack *
+stack_new (void)
+{
+  return g_ptr_array_new ();
+}
+
+static inline void
+stack_push (IdeXmlStack *stack,
+            gpointer     ptr)
+{
+  g_ptr_array_add (stack, ptr);
+}
+
+static inline gpointer
+stack_pop (IdeXmlStack *stack)
+{
+  gint end = stack->len - 1;
+
+  return (end < 0) ? NULL : g_ptr_array_remove_index_fast (stack, end);
+}
+
+static inline gint
+stack_is_empty (IdeXmlStack *stack)
+{
+  return (stack->len == 0);
+}
+
+static inline void
+stack_destroy (IdeXmlStack *stack)
+{
+  g_ptr_array_unref (stack);
+}
+
+static inline gsize
+stack_get_size (IdeXmlStack *stack)
+{
+  return stack->len;
+}
+
+struct _IdeXmlService
+{
+  IdeObject         parent_instance;
+
+  EggTaskCache     *trees;
+  GCancellable     *cancellable;
+};
+
+static void service_iface_init (IdeServiceInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (IdeXmlService, ide_xml_service, IDE_TYPE_OBJECT, 0,
+                                G_IMPLEMENT_INTERFACE (IDE_TYPE_SERVICE, service_iface_init))
+
+static IdeXmlSymbolNode *
+create_node_from_reader (XmlReader *reader)
+{
+  const gchar *name;
+  GFile *file = NULL;
+  guint line = 0;
+  guint line_offset = 0;
+
+  name = xml_reader_get_name (reader);
+
+  return ide_xml_symbol_node_new (name, file, line, line_offset);
+}
+
+static void
+print_node (IdeXmlSymbolNode *node,
+            guint             depth)
+{
+  g_autofree gchar *spacer;
+
+  spacer = g_strnfill (depth, '\t');
+  printf ("%s%s (%i)\n",
+          spacer,
+          ide_symbol_node_get_name (IDE_SYMBOL_NODE (node)),
+          depth);
+}
+
+static IdeXmlSymbolNode *
+ide_xml_service_walk_tree (IdeXmlService    *self,
+                           XmlReader        *reader)
+{
+  IdeXmlStack *stack;
+  IdeXmlSymbolNode *root_node;
+  IdeXmlSymbolNode *parent_node;
+  IdeXmlSymbolNode *current_node;
+  IdeXmlSymbolNode *previous_node = NULL;
+  xmlReaderTypes type;
+  gint depth = 0;
+  gint current_depth = 0;
+  gboolean is_empty;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (XML_IS_READER (reader));
+
+  stack = stack_new ();
+
+  parent_node = root_node = ide_xml_symbol_node_new ("root", NULL, 0, 0);
+  stack_push (stack, parent_node);
+
+  while (xml_reader_read (reader))
+    {
+      type = xml_reader_get_node_type (reader);
+      if ( type == XML_READER_TYPE_ELEMENT)
+        {
+          current_node = create_node_from_reader (reader);
+          depth = xml_reader_get_depth (reader);
+          is_empty = xml_reader_is_empty_element (reader);
+
+          /* TODO: take end elements into account and use:
+           * || ABS (depth - current_depth) > 1
+           */
+          if (depth < 0)
+            {
+              g_warning ("Wrong xml element depth, current:%i new:%i\n", current_depth, depth);
+              break;
+            }
+
+          if (depth > current_depth)
+            {
+              ++current_depth;
+              stack_push (stack, parent_node);
+
+              g_assert (previous_node != NULL);
+              parent_node = previous_node;
+              ide_xml_symbol_node_take_child (parent_node, current_node);
+            }
+          else if (depth < current_depth)
+            {
+              --current_depth;
+              parent_node = stack_pop (stack);
+              if (parent_node == NULL)
+                {
+                  g_warning ("Xml nodes stack empty\n");
+                  break;
+                }
+
+              g_assert (parent_node != NULL);
+              ide_xml_symbol_node_take_child (parent_node, current_node);
+            }
+          else
+            {
+              ide_xml_symbol_node_take_child (parent_node, current_node);
+            }
+
+          previous_node = current_node;
+          print_node (current_node, depth);
+        }
+    }
+
+  printf ("stack size:%li\n", stack_get_size (stack));
+
+  stack_destroy (stack);
+
+  return root_node;
+}
+
+static IdeXmlSymbolNode *
+ide_xml_service_build_tree (IdeXmlService *self,
+                            GBytes        *content,
+                            GFile         *file)
+{
+  IdeXmlSymbolNode *root_node;
+  XmlReader *reader;
+  const gchar *data;
+  g_autofree gchar *uri;
+  gsize size;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+
+  data = g_bytes_get_data (content, &size);
+  uri = g_file_get_uri (file);
+  reader = xml_reader_new ();
+  xml_reader_load_from_data (reader, data, size, uri, NULL);
+  root_node = ide_xml_service_walk_tree (self, reader);
+
+  g_object_unref (reader);
+
+  return root_node;
+}
+
+static GBytes *
+ide_xml_service_get_file_content (IdeXmlService *self,
+                                  GFile         *file)
+{
+  IdeContext *context;
+  IdeBufferManager *manager;
+  IdeBuffer *buffer;
+  GBytes *content = NULL;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (G_IS_FILE (file));
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  manager = ide_context_get_buffer_manager (context);
+  if (NULL != (buffer = ide_buffer_manager_find_buffer (manager, file)))
+    content = ide_buffer_get_content (buffer);
+
+  return content;
+}
+
+static void
+ide_xml_service_build_tree_cb (EggTaskCache  *cache,
+                               gconstpointer  key,
+                               GTask         *task,
+                               gpointer       user_data)
+{
+  IdeXmlService *self = user_data;
+  g_autofree gchar *path = NULL;
+  IdeContext *context;
+  IdeFile *ifile = (IdeFile *)key;
+  GFile *gfile;
+  IdeXmlSymbolNode *root_node;
+  GBytes *content = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (key != NULL);
+  g_assert (IDE_IS_FILE ((IdeFile *)key));
+  g_assert (G_IS_TASK (task));
+
+  gfile = ide_file_get_file (ifile);
+  context = ide_object_get_context (IDE_OBJECT (self));
+
+  if (!gfile || !(path = g_file_get_path (gfile)))
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_NOT_SUPPORTED,
+                               _("File must be saved localy to parse."));
+      return;
+    }
+
+  printf ("tree path:%s\n", path);
+  if (NULL != (content = ide_xml_service_get_file_content (self, gfile)))
+    {
+      root_node = ide_xml_service_build_tree (self, content, gfile);
+      g_task_return_pointer (task, root_node, g_object_unref);
+    }
+  else
+    {
+      g_task_return_new_error (task,
+                               G_IO_ERROR,
+                               G_IO_ERROR_FAILED,
+                               _("Failed to create xml tree."));
+      return;
+    }
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_service_buffer_saved (IdeXmlService    *self,
+                              IdeBuffer        *buffer,
+                              IdeBufferManager *buffer_manager)
+{
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (IDE_IS_BUFFER_MANAGER (buffer_manager));
+
+  printf ("buffer saved:%p\n", buffer);
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_service_get_root_node_cb (GObject      *object,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  EggTaskCache *cache = (EggTaskCache *)object;
+  g_autoptr(IdeXmlSymbolNode) ret = NULL;
+  g_autoptr(GTask) task = user_data;
+  GError *error = NULL;
+
+  g_assert (EGG_IS_TASK_CACHE (cache));
+
+  if (!(ret = egg_task_cache_get_finish (cache, result, &error)))
+    g_task_return_error (task, error);
+  else
+    {
+      printf ("new tree:%p\n", ret);
+    g_task_return_pointer (task, g_steal_pointer (&ret), g_object_unref);
+    }
+}
+
+/**
+ * ide_xml_service_get_root_node_async:
+ *
+ * This function is used to asynchronously retrieve the root node for
+ * a particular file.
+ *
+ * If the root node is up to date, then no parsing will occur and the
+ * existing root node will be used.
+ *
+ * If the root node is out of date, then the source file(s) will be
+ * parsed asynchronously.
+ */
+void
+ide_xml_service_get_root_node_async (IdeXmlService       *self,
+                                     IdeFile             *file,
+                                     gint64               min_serial,
+                                     GCancellable        *cancellable,
+                                     GAsyncReadyCallback  callback,
+                                     gpointer             user_data)
+{
+  IdeXmlSymbolNode *cached;
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+  g_return_if_fail (IDE_IS_FILE (file));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  if (min_serial == 0)
+    {
+      IdeContext *context;
+      IdeUnsavedFiles *unsaved_files;
+
+      context = ide_object_get_context (IDE_OBJECT (self));
+      unsaved_files = ide_context_get_unsaved_files (context);
+      min_serial = ide_unsaved_files_get_sequence (unsaved_files);
+    }
+
+  /*
+   * If we have a cached unit, and it is new enough, then re-use it.
+   */
+  if ((cached = egg_task_cache_peek (self->trees, file)) &&
+      (ide_xml_symbol_node_get_serial (cached) >= min_serial))
+    {
+      printf ("get cached tree:%p\n", cached);
+      g_task_return_pointer (task, g_object_ref (cached), g_object_unref);
+      return;
+    }
+
+  printf ("egg_task_cache_get_async\n");
+  egg_task_cache_get_async (self->trees,
+                            file,
+                            TRUE,
+                            cancellable,
+                            ide_xml_service_get_root_node_cb,
+                            g_object_ref (task));
+}
+
+/**
+ * ide_xml_service_get_root_node_finish:
+ *
+ * Completes an asychronous request to get a root node for a given file.
+ * See ide_xml_service_get_root_node_async() for more information.
+ *
+ * Returns: (transfer full): An #IdeXmlSymbolNode or %NULL up on failure.
+ */
+IdeXmlSymbolNode *
+ide_xml_service_get_root_node_finish (IdeXmlService  *self,
+                                      GAsyncResult   *result,
+                                      GError        **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_xml_service_context_loaded (IdeService *service)
+{
+  IdeBufferManager *buffer_manager;
+  IdeXmlService *self = (IdeXmlService *)service;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  buffer_manager = ide_context_get_buffer_manager (context);
+
+  g_signal_connect_object (buffer_manager,
+                           "buffer-saved",
+                           G_CALLBACK (ide_xml_service_buffer_saved),
+                           self,
+                           G_CONNECT_SWAPPED);
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_service_start (IdeService *service)
+{
+  IdeXmlService *self = (IdeXmlService *)service;
+
+  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+
+  self->trees = egg_task_cache_new ((GHashFunc)ide_file_hash,
+                                    (GEqualFunc)ide_file_equal,
+                                    g_object_ref,
+                                    g_object_unref,
+                                    g_object_ref,
+                                    g_object_unref,
+                                    DEFAULT_EVICTION_MSEC,
+                                    ide_xml_service_build_tree_cb,
+                                    self,
+                                    NULL);
+
+  egg_task_cache_set_name (self->trees, "xml trees cache");
+}
+
+static void
+ide_xml_service_stop (IdeService *service)
+{
+  IdeXmlService *self = (IdeXmlService *)service;
+
+  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+
+  if (self->cancellable && !g_cancellable_is_cancelled (self->cancellable))
+    g_cancellable_cancel (self->cancellable);
+
+  g_clear_object (&self->cancellable);
+  g_clear_object (&self->trees);
+}
+
+static void
+ide_xml_service_finalize (GObject *object)
+{
+  IdeXmlService *self = (IdeXmlService *)object;
+
+  IDE_ENTRY;
+
+  g_clear_object (&self->trees);
+  g_clear_object (&self->cancellable);
+
+  G_OBJECT_CLASS (ide_xml_service_parent_class)->finalize (object);
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_service_class_init (IdeXmlServiceClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_xml_service_finalize;
+}
+
+static void
+service_iface_init (IdeServiceInterface *iface)
+{
+  iface->context_loaded = ide_xml_service_context_loaded;
+  iface->start = ide_xml_service_start;
+  iface->stop = ide_xml_service_stop;
+}
+
+static void
+ide_xml_service_class_finalize (IdeXmlServiceClass *klass)
+{
+}
+
+static void
+ide_xml_service_init (IdeXmlService *self)
+{
+}
+
+void
+_ide_xml_service_register_type (GTypeModule *module)
+{
+  ide_xml_service_register_type (module);
+}
+
+/**
+ * ide_xml_service_get_cached_root_node:
+ *
+ * Gets the #IdeXmlSymbolNode root node for the corresponding file.
+ *
+ * Returns: (transfer NULL): A xml symbol node.
+ */
+IdeXmlSymbolNode *
+ide_xml_service_get_cached_root_node (IdeXmlService *self,
+                                      GFile         *file)
+{
+  IdeXmlSymbolNode *cached;
+
+  g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
+  g_return_val_if_fail (IDE_IS_FILE (file), NULL);
+
+  cached = egg_task_cache_peek (self->trees, file);
+
+  return cached ? g_object_ref (cached) : NULL;
+}
diff --git a/plugins/xml-pack/ide-xml-service.h b/plugins/xml-pack/ide-xml-service.h
new file mode 100644
index 0000000..c49ed7e
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-service.h
@@ -0,0 +1,47 @@
+/* ide-xml-service.h
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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_XML_SERVICE_H
+#define IDE_XML_SERVICE_H
+
+#include <gtksourceview/gtksource.h>
+
+#include "ide-xml-symbol-node.h"
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_SERVICE (ide_xml_service_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeXmlService, ide_xml_service, IDE, XML_SERVICE, IdeObject)
+
+IdeXmlSymbolNode   *ide_xml_service_get_cached_root_node      (IdeXmlService        *self,
+                                                               GFile                *file);
+void                ide_xml_service_get_root_node_async       (IdeXmlService        *self,
+                                                               IdeFile              *file,
+                                                               gint64                min_serial,
+                                                               GCancellable         *cancellable,
+                                                               GAsyncReadyCallback   callback,
+                                                               gpointer              user_data);
+IdeXmlSymbolNode   *ide_xml_service_get_root_node_finish      (IdeXmlService        *self,
+                                                               GAsyncResult         *result,
+                                                               GError              **error);
+
+G_END_DECLS
+
+#endif /* IDE_XML_SERVICE_H */
diff --git a/plugins/xml-pack/ide-xml-symbol-node.c b/plugins/xml-pack/ide-xml-symbol-node.c
new file mode 100644
index 0000000..30ab3df
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-node.c
@@ -0,0 +1,184 @@
+/* ide-xml-symbol-node.c
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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-xml-symbol-node"
+
+#include "ide-xml-symbol-node.h"
+
+struct _IdeXmlSymbolNode
+{
+  IdeSymbolNode             parent_instance;
+  GPtrArray                *children;
+  GFile                    *file;
+  guint                     line;
+  guint                     line_offset;
+  gint64                    serial;
+};
+
+G_DEFINE_TYPE (IdeXmlSymbolNode, ide_xml_symbol_node, IDE_TYPE_SYMBOL_NODE)
+
+static void
+ide_xml_symbol_node_get_location_cb (GObject      *object,
+                                     GAsyncResult *result,
+                                     gpointer      user_data)
+{
+  IdeXmlSymbolResolver *resolver = (IdeXmlSymbolResolver *)object;
+  g_autoptr(IdeSourceLocation) location = NULL;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(GError) error = NULL;
+
+  g_assert (IDE_IS_XML_SYMBOL_RESOLVER (resolver));
+  g_assert (G_IS_TASK (task));
+
+  //location = ide_xml_symbol_resolver_get_location_finish (resolver, result, &error);
+
+  if (location == NULL)
+    g_task_return_error (task, g_steal_pointer (&error));
+  else
+    g_task_return_pointer (task,
+                           g_steal_pointer (&location),
+                           (GDestroyNotify)ide_source_location_unref);
+}
+
+static void
+ide_xml_symbol_node_get_location_async (IdeSymbolNode       *node,
+                                        GCancellable        *cancellable,
+                                        GAsyncReadyCallback  callback,
+                                        gpointer             user_data)
+{
+  IdeXmlSymbolNode *self = (IdeXmlSymbolNode *)node;
+  g_autoptr(GTask) task = NULL;
+
+  g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_xml_symbol_node_get_location_async);
+
+  /* ide_xml_symbol_resolver_get_location_async (self->resolver, */
+  /*                                             self->index, */
+  /*                                             self->entry, */
+  /*                                             NULL, */
+  /*                                             ide_xml_symbol_node_get_location_cb, */
+  /*                                             g_steal_pointer (&task)); */
+}
+
+static IdeSourceLocation *
+ide_xml_symbol_node_get_location_finish (IdeSymbolNode  *node,
+                                         GAsyncResult   *result,
+                                         GError        **error)
+{
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (node), NULL);
+  g_return_val_if_fail (G_IS_TASK (result), NULL);
+
+  return g_task_propagate_pointer (G_TASK (result), error);
+}
+
+static void
+ide_xml_symbol_node_finalize (GObject *object)
+{
+  IdeXmlSymbolNode *self = (IdeXmlSymbolNode *)object;
+
+  g_clear_pointer (&self->children, g_ptr_array_unref);
+  /* self->entry = NULL; */
+  /* g_clear_object (&self->index); */
+
+  G_OBJECT_CLASS (ide_xml_symbol_node_parent_class)->finalize (object);
+}
+
+static void
+ide_xml_symbol_node_class_init (IdeXmlSymbolNodeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+  IdeSymbolNodeClass *symbol_node_class = IDE_SYMBOL_NODE_CLASS (klass);
+
+  object_class->finalize = ide_xml_symbol_node_finalize;
+
+  symbol_node_class->get_location_async = ide_xml_symbol_node_get_location_async;
+  symbol_node_class->get_location_finish = ide_xml_symbol_node_get_location_finish;
+}
+
+static void
+ide_xml_symbol_node_init (IdeXmlSymbolNode *self)
+{
+}
+
+IdeXmlSymbolNode *
+ide_xml_symbol_node_new (const gchar            *name,
+                         GFile                  *file,
+                         guint                   line,
+                         guint                   line_offset)
+{
+  IdeXmlSymbolNode *self;
+  IdeSymbolFlags flags = IDE_SYMBOL_FLAGS_NONE;
+
+  g_assert (!ide_str_empty0 (name));
+  //g_assert (G_IS_FILE (file));
+
+  self = g_object_new (IDE_TYPE_XML_SYMBOL_NODE,
+                       "name", name,
+                       "kind", IDE_SYMBOL_NONE,
+                       "flags", flags,
+                       NULL);
+
+  self->file = file;
+  self->line = line;
+  self->line_offset = line_offset;
+
+  return self;
+}
+
+guint
+ide_xml_symbol_node_get_n_children (IdeXmlSymbolNode *self)
+{
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), 0);
+
+  return self->children != NULL ? self->children->len : 0;
+}
+
+IdeSymbolNode *
+ide_xml_symbol_node_get_nth_child (IdeXmlSymbolNode *self,
+                                   guint             nth_child)
+{
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
+
+  if (self->children != NULL && nth_child < self->children->len)
+    return g_object_ref (g_ptr_array_index (self->children, nth_child));
+
+  return NULL;
+}
+
+void
+ide_xml_symbol_node_take_child (IdeXmlSymbolNode *self,
+                                IdeXmlSymbolNode *child)
+{
+  g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
+  g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (child));
+
+  if (self->children == NULL)
+    self->children = g_ptr_array_new_with_free_func (g_object_unref);
+  g_ptr_array_add (self->children, child);
+}
+
+gint64
+ide_xml_symbol_node_get_serial (IdeXmlSymbolNode *self)
+{
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), -1);
+
+  return self->serial;
+}
diff --git a/plugins/xml-pack/ide-xml-symbol-node.h b/plugins/xml-pack/ide-xml-symbol-node.h
new file mode 100644
index 0000000..3c9f6fa
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-node.h
@@ -0,0 +1,45 @@
+/* ide-xml-symbol-node.h
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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_XML_SYMBOL_NODE_H
+#define IDE_XML_SYMBOL_NODE_H
+
+#include "ide-xml-symbol-resolver.h"
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_SYMBOL_NODE (ide_xml_symbol_node_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeXmlSymbolNode, ide_xml_symbol_node, IDE, XML_SYMBOL_NODE, IdeSymbolNode)
+
+IdeXmlSymbolNode         *ide_xml_symbol_node_new              (const gchar            *name,
+                                                                GFile                  *file,
+                                                                guint                   line,
+                                                                guint                   line_offset);
+void                      ide_xml_symbol_node_take_child       (IdeXmlSymbolNode       *self,
+                                                                IdeXmlSymbolNode       *child);
+guint                     ide_xml_symbol_node_get_n_children   (IdeXmlSymbolNode       *self);
+IdeSymbolNode            *ide_xml_symbol_node_get_nth_child    (IdeXmlSymbolNode       *self,
+                                                                guint                   nth_child);
+gint64                    ide_xml_symbol_node_get_serial       (IdeXmlSymbolNode       *self);
+
+G_END_DECLS
+
+#endif /* IDE_XML_SYMBOL_NODE_H */
diff --git a/plugins/xml-pack/ide-xml-symbol-resolver.c b/plugins/xml-pack/ide-xml-symbol-resolver.c
new file mode 100644
index 0000000..e14c272
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-resolver.c
@@ -0,0 +1,193 @@
+/* ide-xml-symbol-resolver.c
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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 "xml-symbol-resolver"
+
+#include "ide-xml-service.h"
+#include "ide-xml-symbol-tree.h"
+
+#include "ide-xml-symbol-resolver.h"
+
+struct _IdeXmlSymbolResolver
+{
+  IdeObject parent_instance;
+};
+
+static void symbol_resolver_iface_init (IdeSymbolResolverInterface *iface);
+
+G_DEFINE_DYNAMIC_TYPE_EXTENDED (IdeXmlSymbolResolver, ide_xml_symbol_resolver, IDE_TYPE_OBJECT, 0,
+                                G_IMPLEMENT_INTERFACE (IDE_TYPE_SYMBOL_RESOLVER, symbol_resolver_iface_init))
+
+static void
+ide_xml_symbol_resolver_lookup_symbol_async (IdeSymbolResolver   *resolver,
+                                             IdeSourceLocation   *location,
+                                             GCancellable        *cancellable,
+                                             GAsyncReadyCallback  callback,
+                                             gpointer             user_data)
+{
+  IdeXmlSymbolResolver *self = (IdeXmlSymbolResolver *)resolver;
+  g_autoptr(GTask) task = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_XML_SYMBOL_RESOLVER (self));
+  g_assert (location != NULL);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  g_task_return_new_error (task,
+                           G_IO_ERROR,
+                           G_IO_ERROR_UNKNOWN,
+                           "No symbol lookup for xml files.");
+
+  IDE_EXIT;
+}
+
+static IdeSymbol *
+ide_xml_symbol_resolver_lookup_symbol_finish (IdeSymbolResolver  *resolver,
+                                              GAsyncResult       *result,
+                                              GError            **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_RESOLVER (resolver), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_xml_symbol_resolver_get_symbol_tree_cb (GObject      *object,
+                                            GAsyncResult *result,
+                                            gpointer      user_data)
+{
+  IdeXmlService *service = (IdeXmlService *)object;
+  g_autoptr(GTask) task = user_data;
+  IdeContext *context;
+  IdeXmlSymbolNode *root_node;
+  IdeXmlSymbolTree *symbol_tree;
+  GError *error = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (G_IS_TASK (task));
+  g_assert (IDE_IS_XML_SERVICE (service));
+
+  context = ide_object_get_context (IDE_OBJECT (service));
+  root_node = ide_xml_service_get_root_node_finish (service, result, &error);
+  if (root_node != NULL)
+    {
+      symbol_tree = ide_xml_symbol_tree_new (root_node);
+
+      g_task_return_pointer (task, symbol_tree, g_object_unref);
+    }
+  else
+    g_task_return_error (task, error);
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_symbol_resolver_get_symbol_tree_async (IdeSymbolResolver   *resolver,
+                                               GFile               *file,
+                                               GCancellable        *cancellable,
+                                               GAsyncReadyCallback  callback,
+                                               gpointer             user_data)
+{
+  IdeXmlSymbolResolver *self = (IdeXmlSymbolResolver *)resolver;
+  g_autoptr(GTask) task = NULL;
+  IdeContext *context;
+  IdeXmlService *service;
+  g_autoptr(IdeFile) ifile = NULL;
+
+  IDE_ENTRY;
+
+  g_assert (IDE_IS_XML_SYMBOL_RESOLVER (self));
+  g_assert (G_IS_FILE (file));
+  g_assert (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  context = ide_object_get_context (IDE_OBJECT (self));
+  service = ide_context_get_service_typed (context, IDE_TYPE_XML_SERVICE);
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+
+  ifile = g_object_new (IDE_TYPE_FILE,
+                        "file", file,
+                        "context", context,
+                        NULL);
+
+  printf ("=> ask symbol tree for:%s\n", g_file_get_path (file));
+
+  ide_xml_service_get_root_node_async (service,
+                                       ifile,
+                                       0,
+                                       cancellable,
+                                       ide_xml_symbol_resolver_get_symbol_tree_cb,
+                                       g_object_ref (task));
+
+  IDE_EXIT;
+}
+
+static IdeSymbolTree *
+ide_xml_symbol_resolver_get_symbol_tree_finish (IdeSymbolResolver  *resolver,
+                                                GAsyncResult       *result,
+                                                GError            **error)
+{
+  IdeSymbolTree *ret;
+  GTask *task = (GTask *)result;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_RESOLVER (resolver), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  ret = g_task_propagate_pointer (task, error);
+
+  IDE_RETURN (ret);
+}
+
+static void
+ide_xml_symbol_resolver_class_init (IdeXmlSymbolResolverClass *klass)
+{
+}
+
+static void
+ide_xml_symbol_resolver_class_finalize (IdeXmlSymbolResolverClass *klass)
+{
+}
+
+static void
+ide_xml_symbol_resolver_init (IdeXmlSymbolResolver *self)
+{
+}
+
+void
+_ide_xml_symbol_resolver_register_type (GTypeModule *module)
+{
+  ide_xml_symbol_resolver_register_type (module);
+}
+
+static void
+symbol_resolver_iface_init (IdeSymbolResolverInterface *iface)
+{
+  iface->lookup_symbol_async = ide_xml_symbol_resolver_lookup_symbol_async;
+  iface->lookup_symbol_finish = ide_xml_symbol_resolver_lookup_symbol_finish;
+  iface->get_symbol_tree_async = ide_xml_symbol_resolver_get_symbol_tree_async;
+  iface->get_symbol_tree_finish = ide_xml_symbol_resolver_get_symbol_tree_finish;
+}
diff --git a/plugins/xml-pack/ide-xml-symbol-resolver.h b/plugins/xml-pack/ide-xml-symbol-resolver.h
new file mode 100644
index 0000000..45c77b5
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-resolver.h
@@ -0,0 +1,32 @@
+/* ide-xml-symbol-resolver.h
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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_XML_SYMBOL_RESOLVER_H
+#define IDE_XML_SYMBOL_RESOLVER_H
+
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_SYMBOL_RESOLVER (ide_xml_symbol_resolver_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeXmlSymbolResolver, ide_xml_symbol_resolver, IDE, XML_SYMBOL_RESOLVER, IdeObject)
+
+G_END_DECLS
+
+#endif /* IDE_XML_SYMBOL_RESOLVER_H */
diff --git a/plugins/xml-pack/ide-xml-symbol-tree.c b/plugins/xml-pack/ide-xml-symbol-tree.c
new file mode 100644
index 0000000..3de0331
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-tree.c
@@ -0,0 +1,123 @@
+/* ide-xml-symbol-tree.c
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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-xml-symbol-tree"
+
+#include "ide-xml-symbol-tree.h"
+
+struct _IdeXmlSymbolTree
+{
+  GObject           parent_instance;
+
+  IdeXmlSymbolNode *root_node;
+};
+
+static void symbol_tree_iface_init (IdeSymbolTreeInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (IdeXmlSymbolTree, ide_xml_symbol_tree, G_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (IDE_TYPE_SYMBOL_TREE, symbol_tree_iface_init))
+
+static guint
+ide_xml_symbol_tree_get_n_children (IdeSymbolTree *tree,
+                                    IdeSymbolNode *node)
+{
+  IdeXmlSymbolTree *self = (IdeXmlSymbolTree *)tree;
+
+  g_assert (IDE_IS_XML_SYMBOL_TREE (tree));
+  g_assert (node == NULL || IDE_IS_XML_SYMBOL_NODE (node));
+
+  if (node == NULL)
+    node = (IdeSymbolNode *)self->root_node;
+
+  return ide_xml_symbol_node_get_n_children (IDE_XML_SYMBOL_NODE (node));
+}
+
+static IdeSymbolNode *
+ide_xml_symbol_tree_get_nth_child (IdeSymbolTree *tree,
+                                   IdeSymbolNode *node,
+                                   guint          nth)
+{
+  IdeXmlSymbolTree *self = (IdeXmlSymbolTree *)tree;
+  gint n_children;
+
+  g_assert (IDE_IS_XML_SYMBOL_TREE (tree));
+  g_assert (node == NULL || IDE_IS_XML_SYMBOL_NODE (node));
+
+  if (node == NULL)
+    node = (IdeSymbolNode *)self->root_node;
+
+  n_children = ide_xml_symbol_node_get_n_children (IDE_XML_SYMBOL_NODE (node));
+  if (nth < n_children)
+    return ide_xml_symbol_node_get_nth_child (IDE_XML_SYMBOL_NODE (node), nth);
+  else
+    {
+      g_warning ("nth child %u is out of bounds", nth);
+      return NULL;
+    }
+}
+
+static void
+symbol_tree_iface_init (IdeSymbolTreeInterface *iface)
+{
+  iface->get_n_children = ide_xml_symbol_tree_get_n_children;
+  iface->get_nth_child = ide_xml_symbol_tree_get_nth_child;
+}
+
+/**
+ * ide_xml_symbol_tree_new:
+ * @root_node: A #IdeXmlSymbolNode
+ *
+ * Create a new #IdeXmlSymbolTree
+ *
+ * Returns: (transfer full): A newly allocated #IdeXmlSymbolTree.
+ */
+IdeXmlSymbolTree *
+ide_xml_symbol_tree_new (IdeXmlSymbolNode *root_node)
+{
+  IdeXmlSymbolTree *self;
+
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (root_node), NULL);
+
+  self = g_object_new (IDE_TYPE_XML_SYMBOL_TREE, NULL);
+  self->root_node = g_object_ref (root_node);
+
+  return self;
+}
+
+static void
+ide_xml_symbol_tree_finalize (GObject *object)
+{
+  IdeXmlSymbolTree *self = (IdeXmlSymbolTree *)object;
+
+  g_clear_object (&self->root_node);
+
+  G_OBJECT_CLASS (ide_xml_symbol_tree_parent_class)->finalize (object);
+}
+
+static void
+ide_xml_symbol_tree_class_init (IdeXmlSymbolTreeClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_xml_symbol_tree_finalize;
+}
+
+static void
+ide_xml_symbol_tree_init (IdeXmlSymbolTree *self)
+{
+}
diff --git a/plugins/xml-pack/ide-xml-symbol-tree.h b/plugins/xml-pack/ide-xml-symbol-tree.h
new file mode 100644
index 0000000..d91730d
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-symbol-tree.h
@@ -0,0 +1,35 @@
+/* ide-xml-symbol-tree.h
+ *
+ * Copyright (C) 2017 Sébastien Lafargue <slafargue gnome org>
+ *
+ * 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_XML_SYMBOL_TREE_H
+#define IDE_XML_SYMBOL_TREE_H
+
+#include <ide.h>
+#include "ide-xml-symbol-node.h"
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_SYMBOL_TREE (ide_xml_symbol_tree_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeXmlSymbolTree, ide_xml_symbol_tree, IDE, XML_SYMBOL_TREE, GObject)
+
+IdeXmlSymbolTree *ide_xml_symbol_tree_new (IdeXmlSymbolNode *root_node);
+
+G_END_DECLS
+
+#endif /* IDE_XML_SYMBOL_TREE_H */
diff --git a/plugins/xml-pack/xml-pack-plugin.c b/plugins/xml-pack/xml-pack-plugin.c
index b9cb996..2732265 100644
--- a/plugins/xml-pack/xml-pack-plugin.c
+++ b/plugins/xml-pack/xml-pack-plugin.c
@@ -20,16 +20,24 @@
 
 #include "ide-xml-highlighter.h"
 #include "ide-xml-indenter.h"
+#include "ide-xml-service.h"
+#include "ide-xml-symbol-resolver.h"
 
 void _ide_xml_highlighter_register_type (GTypeModule *module);
 void _ide_xml_indenter_register_type (GTypeModule *module);
+void _ide_xml_symbol_resolver_register_type (GTypeModule *module);
+void _ide_xml_service_register_type (GTypeModule *module);
 
 void
 peas_register_types (PeasObjectModule *module)
 {
   _ide_xml_highlighter_register_type (G_TYPE_MODULE (module));
   _ide_xml_indenter_register_type (G_TYPE_MODULE (module));
+  _ide_xml_symbol_resolver_register_type (G_TYPE_MODULE (module));
+  _ide_xml_service_register_type (G_TYPE_MODULE (module));
 
   peas_object_module_register_extension_type (module, IDE_TYPE_HIGHLIGHTER, IDE_TYPE_XML_HIGHLIGHTER);
   peas_object_module_register_extension_type (module, IDE_TYPE_INDENTER, IDE_TYPE_XML_INDENTER);
+  peas_object_module_register_extension_type (module, IDE_TYPE_SYMBOL_RESOLVER, 
IDE_TYPE_XML_SYMBOL_RESOLVER);
+  peas_object_module_register_extension_type (module, IDE_TYPE_SERVICE, IDE_TYPE_XML_SERVICE);
 }
diff --git a/plugins/xml-pack/xml-pack.plugin b/plugins/xml-pack/xml-pack.plugin
index 76078cb..f1b03f4 100644
--- a/plugins/xml-pack/xml-pack.plugin
+++ b/plugins/xml-pack/xml-pack.plugin
@@ -1,11 +1,13 @@
 [Plugin]
 Module=xml-pack-plugin
-Name=XML Auto-Indenter
+Name=XML Auto-Indenter, highlighter and resolver
 Description=Provides language support features for XML
 Authors=Christian Hergert <christian hergert me>
 Copyright=Copyright © 2015 Christian Hergert
 Builtin=true
 X-Indenter-Languages=xml,html
 X-Indenter-Languages-Priority=0
+X-Symbol-Resolver-Languages=xml,html
+X-Symbol-Resolver-Languages-Priority=0
 X-Highlighter-Languages=xml,html
 X-Highlighter-Languages-Priority=0



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