[gnome-builder/wip/slaf/colored-build-output: 29/36] xml-pack: add diagnostics



commit 0cbeb4afd24ca3a3fa3b9ca64f28be8df8e43485
Author: Sebastien Lafargue <slafargue gnome org>
Date:   Thu Feb 2 00:07:40 2017 +0100

    xml-pack: add diagnostics

 libide/diagnostics/ide-diagnostic-provider.c       |   11 +-
 libide/diagnostics/ide-diagnostic-provider.h       |    2 +
 libide/diagnostics/ide-diagnostics-manager.c       |    3 +
 libide/langserv/ide-langserv-diagnostic-provider.c |    1 +
 plugins/clang/ide-clang-diagnostic-provider.c      |    1 +
 plugins/gettext/ide-gettext-diagnostic-provider.c  |    1 +
 .../ide-gca-diagnostic-provider.c                  |    1 +
 plugins/xml-pack/Makefile.am                       |    4 +
 plugins/xml-pack/ide-xml-analysis.c                |  134 ++++++
 plugins/xml-pack/ide-xml-analysis.h                |   59 +++
 plugins/xml-pack/ide-xml-diagnostic-provider.c     |  139 +++++++
 plugins/xml-pack/ide-xml-diagnostic-provider.h     |   36 ++
 plugins/xml-pack/ide-xml-sax.c                     |   12 +
 plugins/xml-pack/ide-xml-sax.h                     |    5 +-
 plugins/xml-pack/ide-xml-service.c                 |  435 ++++++++++++++------
 plugins/xml-pack/ide-xml-service.h                 |   16 +-
 plugins/xml-pack/ide-xml-symbol-resolver.c         |    7 +-
 plugins/xml-pack/ide-xml-tree-builder-generic.c    |    6 +-
 plugins/xml-pack/ide-xml-tree-builder-generic.h    |   11 +-
 plugins/xml-pack/ide-xml-tree-builder-ui.c         |  139 ++++++-
 plugins/xml-pack/ide-xml-tree-builder-ui.h         |   12 +-
 plugins/xml-pack/ide-xml-tree-builder.c            |   37 ++-
 plugins/xml-pack/ide-xml-tree-builder.h            |    3 +-
 plugins/xml-pack/xml-pack-plugin.c                 |    2 +
 plugins/xml-pack/xml-pack.plugin                   |    2 +
 25 files changed, 901 insertions(+), 178 deletions(-)
---
diff --git a/libide/diagnostics/ide-diagnostic-provider.c b/libide/diagnostics/ide-diagnostic-provider.c
index 03a4801..cf4dd7d 100644
--- a/libide/diagnostics/ide-diagnostic-provider.c
+++ b/libide/diagnostics/ide-diagnostic-provider.c
@@ -18,6 +18,7 @@
 
 #define G_LOG_DOMAIN "ide-diagnostic-provider"
 
+#include "buffers/ide-buffer.h"
 #include "ide-context.h"
 #include "ide-debug.h"
 
@@ -58,9 +59,11 @@ ide_diagnostic_provider_default_init (IdeDiagnosticProviderInterface *iface)
 
 }
 
+/* If the file does not match a loaded buffer, buffer is %NULL */
 void
 ide_diagnostic_provider_diagnose_async  (IdeDiagnosticProvider *self,
                                          IdeFile               *file,
+                                         IdeBuffer             *buffer,
                                          GCancellable          *cancellable,
                                          GAsyncReadyCallback    callback,
                                          gpointer               user_data)
@@ -69,9 +72,15 @@ ide_diagnostic_provider_diagnose_async  (IdeDiagnosticProvider *self,
 
   g_return_if_fail (IDE_IS_DIAGNOSTIC_PROVIDER (self));
   g_return_if_fail (IDE_IS_FILE (file));
+  g_return_if_fail (IDE_IS_BUFFER (buffer) || buffer == NULL);
   g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
 
-  IDE_DIAGNOSTIC_PROVIDER_GET_IFACE (self)->diagnose_async (self, file, cancellable, callback, user_data);
+  IDE_DIAGNOSTIC_PROVIDER_GET_IFACE (self)->diagnose_async (self,
+                                                            file,
+                                                            buffer,
+                                                            cancellable,
+                                                            callback,
+                                                            user_data);
 
   IDE_EXIT;
 }
diff --git a/libide/diagnostics/ide-diagnostic-provider.h b/libide/diagnostics/ide-diagnostic-provider.h
index a297618..919c765 100644
--- a/libide/diagnostics/ide-diagnostic-provider.h
+++ b/libide/diagnostics/ide-diagnostic-provider.h
@@ -35,6 +35,7 @@ struct _IdeDiagnosticProviderInterface
                                       IdeContext             *context);
   void            (*diagnose_async)  (IdeDiagnosticProvider  *self,
                                       IdeFile                *file,
+                                      IdeBuffer              *buffer,
                                       GCancellable           *cancellable,
                                       GAsyncReadyCallback     callback,
                                       gpointer                user_data);
@@ -46,6 +47,7 @@ struct _IdeDiagnosticProviderInterface
 
 void            ide_diagnostic_provider_diagnose_async   (IdeDiagnosticProvider  *self,
                                                           IdeFile                *file,
+                                                          IdeBuffer              *buffer,
                                                           GCancellable           *cancellable,
                                                           GAsyncReadyCallback     callback,
                                                           gpointer                user_data);
diff --git a/libide/diagnostics/ide-diagnostics-manager.c b/libide/diagnostics/ide-diagnostics-manager.c
index f463e5f..ab7e0d6 100644
--- a/libide/diagnostics/ide-diagnostics-manager.c
+++ b/libide/diagnostics/ide-diagnostics-manager.c
@@ -412,6 +412,7 @@ ide_diagnostics_group_diagnose_foreach (IdeExtensionSetAdapter *adapter,
   IdeDiagnosticsManager *self = user_data;
   IdeDiagnosticsGroup *group;
   IdeContext *context;
+  g_autoptr (IdeBuffer) buffer = NULL;
   g_autoptr(IdeFile) file = NULL;
 
   IDE_ENTRY;
@@ -439,8 +440,10 @@ ide_diagnostics_group_diagnose_foreach (IdeExtensionSetAdapter *adapter,
   }
 #endif
 
+  buffer = g_weak_ref_get (&group->buffer_wr);
   ide_diagnostic_provider_diagnose_async (provider,
                                           file,
+                                          buffer,
                                           NULL,
                                           ide_diagnostics_group_diagnose_cb,
                                           g_object_ref (self));
diff --git a/libide/langserv/ide-langserv-diagnostic-provider.c 
b/libide/langserv/ide-langserv-diagnostic-provider.c
index 295c54e..a006475 100644
--- a/libide/langserv/ide-langserv-diagnostic-provider.c
+++ b/libide/langserv/ide-langserv-diagnostic-provider.c
@@ -72,6 +72,7 @@ ide_langserv_diagnostic_provider_get_diagnostics_cb (GObject      *object,
 static void
 ide_langserv_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
                                                  IdeFile               *file,
+                                                 IdeBuffer             *buffer,
                                                  GCancellable          *cancellable,
                                                  GAsyncReadyCallback    callback,
                                                  gpointer               user_data)
diff --git a/plugins/clang/ide-clang-diagnostic-provider.c b/plugins/clang/ide-clang-diagnostic-provider.c
index 80682a0..503193a 100644
--- a/plugins/clang/ide-clang-diagnostic-provider.c
+++ b/plugins/clang/ide-clang-diagnostic-provider.c
@@ -124,6 +124,7 @@ ide_clang_diagnostic_provider_diagnose__file_find_other_cb (GObject      *object
 static void
 ide_clang_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
                                               IdeFile               *file,
+                                              IdeBuffer             *buffer,
                                               GCancellable          *cancellable,
                                               GAsyncReadyCallback    callback,
                                               gpointer               user_data)
diff --git a/plugins/gettext/ide-gettext-diagnostic-provider.c 
b/plugins/gettext/ide-gettext-diagnostic-provider.c
index e46eeec..b745a77 100644
--- a/plugins/gettext/ide-gettext-diagnostic-provider.c
+++ b/plugins/gettext/ide-gettext-diagnostic-provider.c
@@ -195,6 +195,7 @@ get_diagnostics_cb (GObject      *source_object,
 static void
 ide_gettext_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
                                                 IdeFile               *file,
+                                                IdeBuffer             *buffer,
                                                 GCancellable          *cancellable,
                                                 GAsyncReadyCallback    callback,
                                                 gpointer               user_data)
diff --git a/plugins/gnome-code-assistance/ide-gca-diagnostic-provider.c 
b/plugins/gnome-code-assistance/ide-gca-diagnostic-provider.c
index ff36e9b..95f7384 100644
--- a/plugins/gnome-code-assistance/ide-gca-diagnostic-provider.c
+++ b/plugins/gnome-code-assistance/ide-gca-diagnostic-provider.c
@@ -404,6 +404,7 @@ cleanup:
 static void
 ide_gca_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
                                             IdeFile               *file,
+                                            IdeBuffer             *buffer,
                                             GCancellable          *cancellable,
                                             GAsyncReadyCallback    callback,
                                             gpointer               user_data)
diff --git a/plugins/xml-pack/Makefile.am b/plugins/xml-pack/Makefile.am
index 78e14f9..bfda967 100644
--- a/plugins/xml-pack/Makefile.am
+++ b/plugins/xml-pack/Makefile.am
@@ -7,6 +7,10 @@ plugin_LTLIBRARIES = libxml-pack-plugin.la
 dist_plugin_DATA = xml-pack.plugin
 
 libxml_pack_plugin_la_SOURCES = \
+       ide-xml-analysis.c \
+       ide-xml-analysis.h \
+       ide-xml-diagnostic-provider.c \
+       ide-xml-diagnostic-provider.h \
        ide-xml-highlighter.c \
        ide-xml-highlighter.h \
        ide-xml-indenter.c \
diff --git a/plugins/xml-pack/ide-xml-analysis.c b/plugins/xml-pack/ide-xml-analysis.c
new file mode 100644
index 0000000..804c564
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-analysis.c
@@ -0,0 +1,134 @@
+/* ide-xml-analysis.c
+ *
+ * Copyright (C) 2017 Sebastien 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/>.
+ */
+#include "ide-xml-analysis.h"
+
+G_DEFINE_BOXED_TYPE (IdeXmlAnalysis, ide_xml_analysis, ide_xml_analysis_ref, ide_xml_analysis_unref)
+
+gint64
+ide_xml_analysis_get_sequence (IdeXmlAnalysis *self)
+{
+  g_return_val_if_fail (self, -1);
+
+  return self->sequence;
+}
+
+/**
+ * ide_xml_analysis_get_diagnostics:
+ * @self: A #IdeXmlAnalysis.
+ *
+ * Returns: (nullable) (transfer none): The #IdeDiagnostics contained by the analysis.
+ *
+ */
+IdeDiagnostics *
+ide_xml_analysis_get_diagnostics (IdeXmlAnalysis *self)
+{
+  g_return_val_if_fail (self, NULL);
+
+  return self->diagnostics;
+}
+
+/**
+ * ide_xml_analysis_get_diagnostics:
+ * @self: A #IdeXmlAnalysis.
+ *
+ * Returns: (nullable) (transfer none): The #IdeXmlSymbolNode root node contained by the analysis.
+ *
+ */
+IdeXmlSymbolNode *
+ide_xml_analysis_get_root_node (IdeXmlAnalysis *self)
+{
+  g_return_val_if_fail (self, NULL);
+
+  return self->root_node;
+}
+
+void
+ide_xml_analysis_set_diagnostics (IdeXmlAnalysis *self,
+                                  IdeDiagnostics *diagnostics)
+{
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (diagnostics != NULL);
+
+  g_clear_pointer (&self->diagnostics, ide_diagnostics_unref);
+  self->diagnostics = ide_diagnostics_ref (diagnostics);
+}
+
+void
+ide_xml_analysis_set_root_node (IdeXmlAnalysis   *self,
+                                IdeXmlSymbolNode *root_node)
+{
+  g_return_if_fail (self != NULL);
+  g_return_if_fail (root_node != NULL);
+
+  g_clear_object (&self->root_node);
+  self->root_node = g_object_ref (root_node);
+}
+
+void
+ide_xml_analysis_set_sequence (IdeXmlAnalysis   *self,
+                               gint64            sequence)
+{
+  g_return_if_fail (self != NULL);
+
+  self->sequence = sequence;
+}
+
+IdeXmlAnalysis *
+ide_xml_analysis_new (gint64 sequence)
+{
+  IdeXmlAnalysis *self;
+
+  self = g_slice_new0 (IdeXmlAnalysis);
+  self->ref_count = 1;
+  self->sequence = sequence;
+
+  return self;
+}
+
+static void
+ide_xml_analysis_free (IdeXmlAnalysis *self)
+{
+  g_assert (self);
+  g_assert_cmpint (self->ref_count, ==, 0);
+
+  g_clear_object (&self->root_node);
+  g_clear_pointer (&self->diagnostics, ide_diagnostics_unref);
+
+  g_slice_free (IdeXmlAnalysis, self);
+}
+
+IdeXmlAnalysis *
+ide_xml_analysis_ref (IdeXmlAnalysis *self)
+{
+  g_return_val_if_fail (self, NULL);
+  g_return_val_if_fail (self->ref_count, NULL);
+
+  g_atomic_int_inc (&self->ref_count);
+
+  return self;
+}
+
+void
+ide_xml_analysis_unref (IdeXmlAnalysis *self)
+{
+  g_return_if_fail (self);
+  g_return_if_fail (self->ref_count);
+
+  if (g_atomic_int_dec_and_test (&self->ref_count))
+    ide_xml_analysis_free (self);
+}
diff --git a/plugins/xml-pack/ide-xml-analysis.h b/plugins/xml-pack/ide-xml-analysis.h
new file mode 100644
index 0000000..ed86908
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-analysis.h
@@ -0,0 +1,59 @@
+/* ide-xml-analysis.h
+ *
+ * Copyright (C) 2017 Sebastien 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_ANALYSIS_H
+#define IDE_XML_ANALYSIS_H
+
+#include "diagnostics/ide-diagnostics.h"
+#include "ide-xml-symbol-node.h"
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_ANALYSIS (ide_xml_analysis_get_type())
+
+typedef struct _IdeXmlAnalysis IdeXmlAnalysis;
+
+struct _IdeXmlAnalysis
+{
+  guint             ref_count;
+  IdeXmlSymbolNode *root_node;
+  IdeDiagnostics   *diagnostics;
+  gint64            sequence;
+};
+
+IdeDiagnostics     *ide_xml_analysis_get_diagnostics     (IdeXmlAnalysis   *self);
+IdeXmlSymbolNode   *ide_xml_analysis_get_root_node       (IdeXmlAnalysis   *self);
+gint64              ide_xml_analysis_get_sequence        (IdeXmlAnalysis   *self);
+void                ide_xml_analysis_set_diagnostics     (IdeXmlAnalysis   *self,
+                                                          IdeDiagnostics   *diagnostics);
+void                ide_xml_analysis_set_root_node       (IdeXmlAnalysis   *self,
+                                                          IdeXmlSymbolNode *root_node);
+void                ide_xml_analysis_set_sequence        (IdeXmlAnalysis   *self,
+                                                          gint64            sequence);
+IdeXmlAnalysis     *ide_xml_analysis_new                 (gint64            sequence);
+IdeXmlAnalysis     *ide_xml_analysis_ref                 (IdeXmlAnalysis   *self);
+void                ide_xml_analysis_unref               (IdeXmlAnalysis   *self);
+
+G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeXmlAnalysis, ide_xml_analysis_unref)
+
+G_END_DECLS
+
+#endif /* IDE_XML_ANALYSIS_H */
+
diff --git a/plugins/xml-pack/ide-xml-diagnostic-provider.c b/plugins/xml-pack/ide-xml-diagnostic-provider.c
new file mode 100644
index 0000000..abcb11b
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-diagnostic-provider.c
@@ -0,0 +1,139 @@
+/* ide-xml-diagnostic-provider.c
+ *
+ * Copyright (C) 2017 Sebastien 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-diagnostic-provider"
+
+#include "ide-xml-service.h"
+
+#include "ide-xml-diagnostic-provider.h"
+
+struct _IdeXmlDiagnosticProvider
+{
+  IdeObject parent_instance;
+};
+
+static void diagnostic_provider_iface_init (IdeDiagnosticProviderInterface *iface);
+
+G_DEFINE_TYPE_EXTENDED (IdeXmlDiagnosticProvider, ide_xml_diagnostic_provider, IDE_TYPE_OBJECT, 0,
+                        G_IMPLEMENT_INTERFACE (IDE_TYPE_DIAGNOSTIC_PROVIDER, diagnostic_provider_iface_init))
+
+static void
+ide_xml_diagnostic_provider_diagnose_cb (GObject      *object,
+                                         GAsyncResult *result,
+                                         gpointer      user_data)
+{
+  IdeXmlService *service = (IdeXmlService *)object;
+  g_autoptr(GTask) task = user_data;
+  IdeDiagnostics *diagnostics;
+  GError *error = NULL;
+
+  IDE_ENTRY;
+
+  if (NULL == (diagnostics = ide_xml_service_get_diagnostics_finish (service, result, &error)))
+    g_task_return_error (task, error);
+  else
+    g_task_return_pointer (task,
+                           ide_diagnostics_ref (diagnostics),
+                           (GDestroyNotify)ide_diagnostics_unref);
+
+  IDE_EXIT;
+}
+
+static void
+ide_xml_diagnostic_provider_diagnose_async (IdeDiagnosticProvider *provider,
+                                            IdeFile               *file,
+                                            IdeBuffer             *buffer,
+                                            GCancellable          *cancellable,
+                                            GAsyncReadyCallback    callback,
+                                            gpointer               user_data)
+{
+  IdeXmlDiagnosticProvider *self = (IdeXmlDiagnosticProvider *)provider;
+  g_autoptr(GTask) task = NULL;
+  IdeXmlService *service;
+  IdeContext *context;
+
+  IDE_ENTRY;
+
+  g_return_if_fail (IDE_IS_XML_DIAGNOSTIC_PROVIDER (self));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_xml_diagnostic_provider_diagnose_async);
+
+  context = ide_object_get_context (IDE_OBJECT (provider));
+  service = ide_context_get_service_typed (context, IDE_TYPE_XML_SERVICE);
+
+  ide_xml_service_get_diagnostics_async (service,
+                                         file,
+                                         buffer,
+                                         cancellable,
+                                         ide_xml_diagnostic_provider_diagnose_cb,
+                                         g_steal_pointer (&task));
+
+  IDE_EXIT;
+}
+
+static IdeDiagnostics *
+ide_xml_diagnostic_provider_diagnose_finish (IdeDiagnosticProvider  *provider,
+                                             GAsyncResult           *result,
+                                             GError                **error)
+{
+  GTask *task = (GTask *)result;
+  IdeDiagnostics *ret;
+
+  IDE_ENTRY;
+
+  g_return_val_if_fail (IDE_IS_XML_DIAGNOSTIC_PROVIDER (provider), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  ret = g_task_propagate_pointer (task, error);
+
+  IDE_RETURN (ret);
+}
+
+IdeXmlDiagnosticProvider *
+ide_xml_diagnostic_provider_new (void)
+{
+  return g_object_new (IDE_TYPE_XML_DIAGNOSTIC_PROVIDER, NULL);
+}
+
+static void
+ide_xml_diagnostic_provider_finalize (GObject *object)
+{
+  G_OBJECT_CLASS (ide_xml_diagnostic_provider_parent_class)->finalize (object);
+}
+
+static void
+ide_xml_diagnostic_provider_class_init (IdeXmlDiagnosticProviderClass *klass)
+{
+  GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+  object_class->finalize = ide_xml_diagnostic_provider_finalize;
+}
+
+static void
+ide_xml_diagnostic_provider_init (IdeXmlDiagnosticProvider *self)
+{
+}
+
+static void
+diagnostic_provider_iface_init (IdeDiagnosticProviderInterface *iface)
+{
+  iface->diagnose_async = ide_xml_diagnostic_provider_diagnose_async;
+  iface->diagnose_finish = ide_xml_diagnostic_provider_diagnose_finish;
+}
diff --git a/plugins/xml-pack/ide-xml-diagnostic-provider.h b/plugins/xml-pack/ide-xml-diagnostic-provider.h
new file mode 100644
index 0000000..3d65547
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-diagnostic-provider.h
@@ -0,0 +1,36 @@
+/* ide-xml-diagnostic-provider.h
+ *
+ * Copyright (C) 2017 Sebastien 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_DIAGNOSTIC_PROVIDER_H
+#define IDE_XML_DIAGNOSTIC_PROVIDER_H
+
+#include <glib-object.h>
+#include <ide.h>
+
+G_BEGIN_DECLS
+
+#define IDE_TYPE_XML_DIAGNOSTIC_PROVIDER (ide_xml_diagnostic_provider_get_type())
+
+G_DECLARE_FINAL_TYPE (IdeXmlDiagnosticProvider, ide_xml_diagnostic_provider, IDE, XML_DIAGNOSTIC_PROVIDER, 
IdeObject)
+
+IdeXmlDiagnosticProvider *ide_xml_diagnostic_provider_new (void);
+
+G_END_DECLS
+
+#endif /* IDE_XML_DIAGNOSTIC_PROVIDER_H */
+
diff --git a/plugins/xml-pack/ide-xml-sax.c b/plugins/xml-pack/ide-xml-sax.c
index 84cec95..c65163e 100644
--- a/plugins/xml-pack/ide-xml-sax.c
+++ b/plugins/xml-pack/ide-xml-sax.c
@@ -125,6 +125,18 @@ ide_xml_sax_set_callback (IdeXmlSax             *self,
       handler->entityDecl = callback;
       break;
 
+    case IDE_XML_SAX_CALLBACK_TYPE_WARNING:
+      handler->warning = callback;
+      break;
+
+    case IDE_XML_SAX_CALLBACK_TYPE_ERROR:
+      handler->error = callback;
+      break;
+
+    case IDE_XML_SAX_CALLBACK_TYPE_FATAL_ERROR:
+      handler->fatalError = callback;
+      break;
+
     default:
       g_assert_not_reached ();
     }
diff --git a/plugins/xml-pack/ide-xml-sax.h b/plugins/xml-pack/ide-xml-sax.h
index cf5bf2f..7cb7259 100644
--- a/plugins/xml-pack/ide-xml-sax.h
+++ b/plugins/xml-pack/ide-xml-sax.h
@@ -38,7 +38,10 @@ enum _IdeXmlSaxCallbackType {
   IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT,
   IDE_XML_SAX_CALLBACK_TYPE_END_DOCUMENT,
   IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT,
-  IDE_XML_SAX_CALLBACK_TYPE_ENTITY
+  IDE_XML_SAX_CALLBACK_TYPE_ENTITY,
+  IDE_XML_SAX_CALLBACK_TYPE_WARNING,
+  IDE_XML_SAX_CALLBACK_TYPE_ERROR,
+  IDE_XML_SAX_CALLBACK_TYPE_FATAL_ERROR,
 };
 
 void            ide_xml_sax_clear             (IdeXmlSax              *self);
diff --git a/plugins/xml-pack/ide-xml-service.c b/plugins/xml-pack/ide-xml-service.c
index 140c3d2..c8654b7 100644
--- a/plugins/xml-pack/ide-xml-service.c
+++ b/plugins/xml-pack/ide-xml-service.c
@@ -23,6 +23,7 @@
 #include <gtksourceview/gtksource.h>
 #include <math.h>
 
+#include "ide-xml-analysis.h"
 #include "ide-xml-tree-builder.h"
 
 #include "ide-xml-service.h"
@@ -33,9 +34,9 @@ gboolean _ide_buffer_get_loading (IdeBuffer *self);
 
 struct _IdeXmlService
 {
-  IdeObject         parent_instance;
+  IdeObject          parent_instance;
 
-  EggTaskCache      *trees;
+  EggTaskCache      *analyses;
   IdeXmlTreeBuilder *tree_builder;
   GCancellable      *cancellable;
 };
@@ -52,18 +53,17 @@ ide_xml_service_build_tree_cb2 (GObject      *object,
 {
   IdeXmlTreeBuilder *tree_builder = (IdeXmlTreeBuilder *)object;
   g_autoptr(GTask) task = user_data;
-  IdeXmlSymbolNode *root_node;
+  g_autoptr(IdeXmlAnalysis) analysis = NULL;
   GError *error = NULL;
 
   g_assert (IDE_IS_XML_TREE_BUILDER (tree_builder));
   g_assert (G_IS_TASK (result));
   g_assert (G_IS_TASK (task));
 
-  root_node = ide_xml_tree_builder_build_tree_finish (tree_builder, result, &error);
-  if (root_node == NULL)
+  if (NULL == (analysis = ide_xml_tree_builder_build_tree_finish (tree_builder, result, &error)))
     g_task_return_error (task, error);
   else
-    g_task_return_pointer (task, root_node, g_object_unref);
+    g_task_return_pointer (task, g_steal_pointer (&analysis), (GDestroyNotify)ide_xml_analysis_unref);
 }
 
 static void
@@ -79,13 +79,13 @@ ide_xml_service_build_tree_cb (EggTaskCache  *cache,
 
   IDE_ENTRY;
 
+  g_assert (EGG_IS_TASK_CACHE (cache));
   g_assert (IDE_IS_XML_SERVICE (self));
-  g_assert (key != NULL);
-  g_assert (IDE_IS_FILE ((IdeFile *)key));
+  g_assert (IDE_IS_FILE (ifile));
   g_assert (G_IS_TASK (task));
 
-  gfile = ide_file_get_file (ifile);
-  if (!gfile || !(path = g_file_get_path (gfile)))
+  if (NULL == (gfile = ide_file_get_file (ifile)) ||
+      NULL == (path = g_file_get_path (gfile)))
     {
       g_task_return_new_error (task,
                                G_IO_ERROR,
@@ -94,7 +94,6 @@ ide_xml_service_build_tree_cb (EggTaskCache  *cache,
       return;
     }
 
-  printf ("tree path:%s\n", path);
   ide_xml_tree_builder_build_tree_async (self->tree_builder,
                                          gfile,
                                          g_task_get_cancellable (task),
@@ -105,42 +104,23 @@ ide_xml_service_build_tree_cb (EggTaskCache  *cache,
 }
 
 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)
+ide_xml_service_get_analysis_cb (GObject      *object,
+                                 GAsyncResult *result,
+                                 gpointer      user_data)
 {
   EggTaskCache *cache = (EggTaskCache *)object;
   g_autoptr(GTask) task = user_data;
-  IdeXmlSymbolNode *ret;
+  g_autoptr(IdeXmlAnalysis) analysis = NULL;
   GError *error = NULL;
 
   g_assert (EGG_IS_TASK_CACHE (cache));
   g_assert (G_IS_TASK (result));
   g_assert (G_IS_TASK (task));
 
-  if (!(ret = egg_task_cache_get_finish (cache, result, &error)))
+  if (NULL == (analysis = 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, ret, g_object_unref);
-    }
+    g_task_return_pointer (task, g_steal_pointer (&analysis), (GDestroyNotify)ide_xml_analysis_unref);
 }
 
 typedef struct
@@ -157,88 +137,48 @@ ide_xml_service__buffer_loaded_cb (IdeBuffer *buffer,
                                    TaskState *state)
 {
   IdeXmlService *self = (IdeXmlService *)state->self;
-  g_autoptr(GTask) task = state->task;
 
   g_assert (IDE_IS_XML_SERVICE (self));
-  g_assert (G_IS_TASK (task));
+  g_assert (G_IS_TASK (state->task));
   g_assert (state->cancellable == NULL || G_IS_CANCELLABLE (state->cancellable));
   g_assert (IDE_IS_FILE (state->ifile));
   g_assert (IDE_IS_BUFFER (state->buffer));
 
-  printf ("buffer loaded\n");
-
-  egg_task_cache_get_async (self->trees,
+  egg_task_cache_get_async (self->analyses,
                             state->ifile,
                             TRUE,
                             state->cancellable,
-                            ide_xml_service_get_root_node_cb,
-                            g_steal_pointer (&task));
+                            ide_xml_service_get_analysis_cb,
+                            g_steal_pointer (&state->task));
 
   g_object_unref (state->buffer);
   g_object_unref (state->ifile);
   g_slice_free (TaskState, state);
 }
 
-/**
- * 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.
- *
- * The xml service is meant to be used with buffers, that is,
- * by extension, loaded views.
- */
-void
-ide_xml_service_get_root_node_async (IdeXmlService       *self,
-                                     IdeFile             *file,
-                                     IdeBuffer           *buffer,
-                                     gint64               min_serial,
-                                     GCancellable        *cancellable,
-                                     GAsyncReadyCallback  callback,
-                                     gpointer             user_data)
+static void
+ide_xml_service_get_analysis_async (IdeXmlService       *self,
+                                    IdeFile             *ifile,
+                                    IdeBuffer           *buffer,
+                                    GCancellable        *cancellable,
+                                    GAsyncReadyCallback  callback,
+                                    gpointer             user_data)
 {
-  IdeXmlSymbolNode *cached;
   g_autoptr(GTask) task = NULL;
   IdeContext *context;
   IdeBufferManager *manager;
   GFile *gfile;
 
-  g_return_if_fail (IDE_IS_XML_SERVICE (self));
-  g_return_if_fail (IDE_IS_FILE (file));
-  g_return_if_fail (IDE_IS_BUFFER (buffer));
-  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (IDE_IS_FILE (ifile));
+  g_assert (IDE_IS_BUFFER (buffer));
+  g_assert (cancellable == NULL || G_IS_CANCELLABLE (cancellable));
 
   task = g_task_new (self, cancellable, callback, user_data);
   context = ide_object_get_context (IDE_OBJECT (self));
-
-  if (min_serial == 0)
-    {
-      IdeUnsavedFiles *unsaved_files;
-
-      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");
   manager = ide_context_get_buffer_manager (context);
-  gfile = ide_file_get_file (file);
+  gfile = ide_file_get_file (ifile);
+
   if (!ide_buffer_manager_has_file (manager, gfile))
     {
       TaskState *state;
@@ -257,7 +197,7 @@ ide_xml_service_get_root_node_async (IdeXmlService       *self,
       state->self = self;
       state->task = g_steal_pointer (&task);
       state->cancellable = cancellable;
-      state->ifile = g_object_ref (file);
+      state->ifile = g_object_ref (ifile);
       state->buffer = g_object_ref (buffer);
 
       g_signal_connect (buffer,
@@ -266,14 +206,119 @@ ide_xml_service_get_root_node_async (IdeXmlService       *self,
                         state);
     }
   else
-    egg_task_cache_get_async (self->trees,
-                              file,
+    egg_task_cache_get_async (self->analyses,
+                              ifile,
                               TRUE,
                               cancellable,
-                              ide_xml_service_get_root_node_cb,
+                              ide_xml_service_get_analysis_cb,
                               g_steal_pointer (&task));
 }
 
+IdeXmlAnalysis *
+ide_xml_service_get_analysis_finish (IdeXmlService  *self,
+                                     GAsyncResult   *result,
+                                     GError        **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
+  g_return_val_if_fail (G_IS_TASK (task), NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_xml_service_get_root_node_cb (GObject      *object,
+                                  GAsyncResult *result,
+                                  gpointer      user_data)
+{
+  IdeXmlService *self = (IdeXmlService *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(IdeXmlAnalysis) analysis = NULL;
+  IdeXmlSymbolNode *root_node;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (G_IS_TASK (result));
+  g_assert (G_IS_TASK (task));
+
+  if (NULL == (analysis = ide_xml_service_get_analysis_finish (self, result, &error)))
+    g_task_return_error (task, error);
+  else
+    {
+      root_node = g_object_ref (ide_xml_analysis_get_root_node (analysis));
+      g_task_return_pointer (task, root_node, 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.
+ *
+ * The xml service is meant to be used with buffers, that is,
+ * by extension, loaded views.
+ */
+void
+ide_xml_service_get_root_node_async (IdeXmlService       *self,
+                                     IdeFile             *ifile,
+                                     IdeBuffer           *buffer,
+                                     GCancellable        *cancellable,
+                                     GAsyncReadyCallback  callback,
+                                     gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  IdeXmlAnalysis *cached;
+
+  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+  g_return_if_fail (IDE_IS_FILE (ifile));
+  g_return_if_fail (IDE_IS_BUFFER (buffer));
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  /*
+   * If we have a cached analysis with a valid root_node,
+   * and it is new enough, then re-use it.
+   */
+  if (NULL != (cached = egg_task_cache_peek (self->analyses, ifile)))
+    {
+      IdeContext *context;
+      IdeUnsavedFiles *unsaved_files;
+      IdeUnsavedFile *uf;
+      IdeXmlSymbolNode *root_node;
+      GFile *gfile;
+
+      gfile = ide_file_get_file (ifile);
+      context = ide_object_get_context (IDE_OBJECT (self));
+      unsaved_files = ide_context_get_unsaved_files (context);
+
+      if (NULL != (uf = ide_unsaved_files_get_unsaved_file (unsaved_files, gfile)) &&
+          ide_xml_analysis_get_sequence (cached) == ide_unsaved_file_get_sequence (uf))
+        {
+          root_node = g_object_ref (ide_xml_analysis_get_root_node (cached));
+          g_assert (IDE_IS_XML_SYMBOL_NODE (root_node));
+
+          g_task_return_pointer (task, root_node, g_object_unref);
+          return;
+        }
+    }
+
+  ide_xml_service_get_analysis_async (self,
+                                      ifile,
+                                      buffer,
+                                      cancellable,
+                                      ide_xml_service_get_root_node_cb,
+                                      g_steal_pointer (&task));
+}
+
 /**
  * ide_xml_service_get_root_node_finish:
  *
@@ -291,6 +336,121 @@ ide_xml_service_get_root_node_finish (IdeXmlService  *self,
 
   g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
   g_return_val_if_fail (G_IS_TASK (result), NULL);
+  g_return_val_if_fail (error != NULL, NULL);
+
+  return g_task_propagate_pointer (task, error);
+}
+
+static void
+ide_xml_service_get_diagnostics_cb (GObject      *object,
+                                    GAsyncResult *result,
+                                    gpointer      user_data)
+{
+  IdeXmlService  *self = (IdeXmlService *)object;
+  g_autoptr(GTask) task = user_data;
+  g_autoptr(IdeXmlAnalysis) analysis = NULL;
+  IdeDiagnostics *diagnostics;
+  GError *error = NULL;
+
+  g_assert (IDE_IS_XML_SERVICE (self));
+  g_assert (G_IS_TASK (result));
+  g_assert (G_IS_TASK (task));
+
+  if (NULL == (analysis = ide_xml_service_get_analysis_finish (self, result, &error)))
+    g_task_return_error (task, error);
+  else
+    {
+      diagnostics = ide_diagnostics_ref (ide_xml_analysis_get_diagnostics (analysis));
+      g_task_return_pointer (task, diagnostics, (GDestroyNotify)ide_diagnostics_unref);
+    }
+}
+
+/**
+ * ide_xml_service_get_diagnostics_async:
+ *
+ * This function is used to asynchronously retrieve the diagnostics
+ * for a particular file.
+ *
+ * If the analysis is up to date, then no parsing will occur and the
+ * existing diagnostics will be used.
+ *
+ * If the analysis is out of date, then the source file(s) will be
+ * parsed asynchronously.
+ *
+ * The xml service is meant to be used with buffers, that is,
+ * by extension, loaded views.
+ */
+void
+ide_xml_service_get_diagnostics_async (IdeXmlService       *self,
+                                       IdeFile             *ifile,
+                                       IdeBuffer           *buffer,
+                                       GCancellable        *cancellable,
+                                       GAsyncReadyCallback  callback,
+                                       gpointer             user_data)
+{
+  g_autoptr(GTask) task = NULL;
+  IdeXmlAnalysis *cached;
+
+  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+  g_return_if_fail (IDE_IS_FILE (ifile));
+  g_return_if_fail (IDE_IS_BUFFER (buffer) || buffer == NULL);
+  g_return_if_fail (!cancellable || G_IS_CANCELLABLE (cancellable));
+
+  task = g_task_new (self, cancellable, callback, user_data);
+
+  /*
+   * If we have a cached analysis with some diagnostics,
+   * and it is new enough, then re-use it.
+   */
+  if (NULL != (cached = egg_task_cache_peek (self->analyses, ifile)))
+    {
+      IdeContext *context;
+      IdeUnsavedFiles *unsaved_files;
+      IdeUnsavedFile *uf;
+      IdeDiagnostics *diagnostics;
+      GFile *gfile;
+
+      gfile = ide_file_get_file (ifile);
+      context = ide_object_get_context (IDE_OBJECT (self));
+      unsaved_files = ide_context_get_unsaved_files (context);
+
+      if (NULL != (uf = ide_unsaved_files_get_unsaved_file (unsaved_files, gfile)) &&
+          ide_xml_analysis_get_sequence (cached) == ide_unsaved_file_get_sequence (uf))
+        {
+          diagnostics = ide_diagnostics_ref (ide_xml_analysis_get_diagnostics (cached));
+          g_assert (diagnostics != NULL);
+
+          g_task_return_pointer (task, diagnostics, (GDestroyNotify)ide_diagnostics_unref);
+          return;
+        }
+    }
+
+  ide_xml_service_get_analysis_async (self,
+                                      ifile,
+                                      buffer,
+                                      cancellable,
+                                      ide_xml_service_get_diagnostics_cb,
+                                      g_steal_pointer (&task));
+}
+
+/**
+ * ide_xml_service_get_diagnostics_finish:
+ *
+ * Completes an asychronous request to get the diagnostics for a given file.
+ * See ide_xml_service_get_diagnostics_async() for more information.
+ *
+ * Returns: (transfer full): An #IdeDiagnostics or %NULL on failure.
+ */
+IdeDiagnostics *
+ide_xml_service_get_diagnostics_finish (IdeXmlService  *self,
+                                        GAsyncResult   *result,
+                                        GError        **error)
+{
+  GTask *task = (GTask *)result;
+
+  g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
+  g_return_val_if_fail (G_IS_TASK (result), NULL);
+  g_return_val_if_fail (error != NULL, NULL);
 
   return g_task_propagate_pointer (task, error);
 }
@@ -300,28 +460,18 @@ ide_xml_service_context_loaded (IdeService *service)
 {
   IdeXmlService *self = (IdeXmlService *)service;
   IdeContext *context;
-  IdeBufferManager *buffer_manager;
 
   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);
 
   if (self->tree_builder == NULL)
     self->tree_builder = g_object_new (IDE_TYPE_XML_TREE_BUILDER,
                                        "context", context,
                                        NULL);
 
-  /* TODO: schedule caching of open views trees */
-
   IDE_EXIT;
 }
 
@@ -330,20 +480,20 @@ ide_xml_service_start (IdeService *service)
 {
   IdeXmlService *self = (IdeXmlService *)service;
 
-  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+  g_assert (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");
+  self->analyses = egg_task_cache_new ((GHashFunc)ide_file_hash,
+                                       (GEqualFunc)ide_file_equal,
+                                       g_object_ref,
+                                       g_object_unref,
+                                       (GBoxedCopyFunc)ide_xml_analysis_ref,
+                                       (GBoxedFreeFunc)ide_xml_analysis_unref,
+                                       DEFAULT_EVICTION_MSEC,
+                                       ide_xml_service_build_tree_cb,
+                                       self,
+                                       NULL);
+
+  egg_task_cache_set_name (self->analyses, "xml analysis cache");
 }
 
 static void
@@ -351,13 +501,13 @@ ide_xml_service_stop (IdeService *service)
 {
   IdeXmlService *self = (IdeXmlService *)service;
 
-  g_return_if_fail (IDE_IS_XML_SERVICE (self));
+  g_assert (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);
+  g_clear_object (&self->analyses);
 }
 
 static void
@@ -367,10 +517,8 @@ ide_xml_service_finalize (GObject *object)
 
   IDE_ENTRY;
 
- ide_xml_service_stop (IDE_SERVICE (self));
-
-  if (self->tree_builder != NULL)
-    g_clear_object (&self->tree_builder);
+  ide_xml_service_stop (IDE_SERVICE (self));
+  g_clear_object (&self->tree_builder);
 
   G_OBJECT_CLASS (ide_xml_service_parent_class)->finalize (object);
 
@@ -418,14 +566,41 @@ _ide_xml_service_register_type (GTypeModule *module)
  */
 IdeXmlSymbolNode *
 ide_xml_service_get_cached_root_node (IdeXmlService *self,
-                                      GFile         *file)
+                                      GFile         *gfile)
 {
+  IdeXmlAnalysis *analysis;
   IdeXmlSymbolNode *cached;
 
   g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
-  g_return_val_if_fail (IDE_IS_FILE (file), NULL);
+  g_return_val_if_fail (IDE_IS_FILE (gfile), NULL);
+
+  if (NULL != (analysis = egg_task_cache_peek (self->analyses, gfile)) &&
+      NULL != (cached = ide_xml_analysis_get_root_node (analysis)))
+    return g_object_ref (cached);
+
+  return NULL;
+}
+
+/**
+ * ide_xml_service_get_cached_diagnostics:
+ *
+ * Gets the #IdeDiagnostics for the corresponding file.
+ *
+ * Returns: (transfer NULL): A #IdeDiagnostics.
+ */
+IdeDiagnostics *
+ide_xml_service_get_cached_diagnostics (IdeXmlService *self,
+                                        GFile         *gfile)
+{
+  IdeXmlAnalysis *analysis;
+  IdeDiagnostics *cached;
+
+  g_return_val_if_fail (IDE_IS_XML_SERVICE (self), NULL);
+  g_return_val_if_fail (IDE_IS_FILE (gfile), NULL);
 
-  cached = egg_task_cache_peek (self->trees, file);
+  if (NULL != (analysis = egg_task_cache_peek (self->analyses, gfile)) &&
+      NULL != (cached = ide_xml_analysis_get_diagnostics (analysis)))
+    return ide_diagnostics_ref (cached);
 
-  return cached ? g_object_ref (cached) : NULL;
+  return NULL;
 }
diff --git a/plugins/xml-pack/ide-xml-service.h b/plugins/xml-pack/ide-xml-service.h
index d0bdd17..1897155 100644
--- a/plugins/xml-pack/ide-xml-service.h
+++ b/plugins/xml-pack/ide-xml-service.h
@@ -30,12 +30,22 @@ G_BEGIN_DECLS
 
 G_DECLARE_FINAL_TYPE (IdeXmlService, ide_xml_service, IDE, XML_SERVICE, IdeObject)
 
+IdeDiagnostics     *ide_xml_service_get_cached_diagnostics    (IdeXmlService        *self,
+                                                               GFile                *gfile);
 IdeXmlSymbolNode   *ide_xml_service_get_cached_root_node      (IdeXmlService        *self,
-                                                               GFile                *file);
+                                                               GFile                *gfile);
+IdeDiagnostics     *ide_xml_service_get_diagnostics_finish    (IdeXmlService        *self,
+                                                               GAsyncResult         *result,
+                                                               GError              **error);
+void                ide_xml_service_get_diagnostics_async     (IdeXmlService        *self,
+                                                               IdeFile              *ifile,
+                                                               IdeBuffer            *buffer,
+                                                               GCancellable         *cancellable,
+                                                               GAsyncReadyCallback   callback,
+                                                               gpointer              user_data);
 void                ide_xml_service_get_root_node_async       (IdeXmlService        *self,
-                                                               IdeFile              *file,
+                                                               IdeFile              *ifile,
                                                                IdeBuffer            *buffer,
-                                                               gint64                min_serial,
                                                                GCancellable         *cancellable,
                                                                GAsyncReadyCallback   callback,
                                                                gpointer              user_data);
diff --git a/plugins/xml-pack/ide-xml-symbol-resolver.c b/plugins/xml-pack/ide-xml-symbol-resolver.c
index ad375b1..40f6559 100644
--- a/plugins/xml-pack/ide-xml-symbol-resolver.c
+++ b/plugins/xml-pack/ide-xml-symbol-resolver.c
@@ -49,6 +49,7 @@ ide_xml_symbol_resolver_lookup_symbol_async (IdeSymbolResolver   *resolver,
   g_assert (location != NULL);
 
   task = g_task_new (self, cancellable, callback, user_data);
+  g_task_set_source_tag (task, ide_xml_symbol_resolver_lookup_symbol_async);
 
   g_task_return_new_error (task,
                            G_IO_ERROR,
@@ -78,7 +79,7 @@ ide_xml_symbol_resolver_get_symbol_tree_cb (GObject      *object,
 {
   IdeXmlService *service = (IdeXmlService *)object;
   g_autoptr(GTask) task = user_data;
-  IdeXmlSymbolNode *root_node;
+  g_autoptr(IdeXmlSymbolNode) root_node = NULL;
   IdeXmlSymbolTree *symbol_tree;
   GError *error = NULL;
 
@@ -124,18 +125,16 @@ ide_xml_symbol_resolver_get_symbol_tree_async (IdeSymbolResolver   *resolver,
 
   task = g_task_new (self, cancellable, callback, user_data);
   g_task_set_task_data (task, g_object_ref (file), g_object_unref);
+  g_task_set_source_tag (task, ide_xml_symbol_resolver_get_symbol_tree_async);
 
   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,
                                        buffer,
-                                       0,
                                        cancellable,
                                        ide_xml_symbol_resolver_get_symbol_tree_cb,
                                        g_object_ref (task));
diff --git a/plugins/xml-pack/ide-xml-tree-builder-generic.c b/plugins/xml-pack/ide-xml-tree-builder-generic.c
index 7ed2f72..211e3a3 100644
--- a/plugins/xml-pack/ide-xml-tree-builder-generic.c
+++ b/plugins/xml-pack/ide-xml-tree-builder-generic.c
@@ -36,7 +36,7 @@ create_node_from_reader (XmlReader *reader)
                                   file, line, line_offset);
 }
 
-IdeXmlSymbolNode *
+IdeXmlAnalysis *
 ide_xml_tree_builder_generic_create (IdeXmlTreeBuilder *self,
                                      IdeXmlSax         *parser,
                                      GFile             *file,
@@ -44,7 +44,7 @@ ide_xml_tree_builder_generic_create (IdeXmlTreeBuilder *self,
                                      gsize              size)
 {
   IdeXmlStack *stack;
-  IdeXmlSymbolNode *root_node = NULL;
+  IdeXmlAnalysis *analysis = NULL;
   IdeXmlSymbolNode *parent_node;
   IdeXmlSymbolNode *current_node;
   IdeXmlSymbolNode *previous_node = NULL;
@@ -111,5 +111,5 @@ ide_xml_tree_builder_generic_create (IdeXmlTreeBuilder *self,
 
   /* stack_destroy (stack); */
 
-  return root_node;
+  return analysis;
 }
diff --git a/plugins/xml-pack/ide-xml-tree-builder-generic.h b/plugins/xml-pack/ide-xml-tree-builder-generic.h
index 70b57c3..c30bf27 100644
--- a/plugins/xml-pack/ide-xml-tree-builder-generic.h
+++ b/plugins/xml-pack/ide-xml-tree-builder-generic.h
@@ -21,6 +21,7 @@
 
 #include <glib.h>
 
+#include "ide-xml-analysis.h"
 #include "ide-xml-sax.h"
 #include "ide-xml-symbol-node.h"
 #include "ide-xml-tree-builder.h"
@@ -28,11 +29,11 @@
 
 G_BEGIN_DECLS
 
-IdeXmlSymbolNode *ide_xml_tree_builder_generic_create (IdeXmlTreeBuilder *self,
-                                                       IdeXmlSax         *parser,
-                                                       GFile             *file,
-                                                       const gchar       *data,
-                                                       gsize              size);
+IdeXmlAnalysis *ide_xml_tree_builder_generic_create (IdeXmlTreeBuilder *self,
+                                                     IdeXmlSax         *parser,
+                                                     GFile             *file,
+                                                     const gchar       *data,
+                                                     gsize              size);
 
 G_END_DECLS
 
diff --git a/plugins/xml-pack/ide-xml-tree-builder-ui.c b/plugins/xml-pack/ide-xml-tree-builder-ui.c
index dcf921e..32a9777 100644
--- a/plugins/xml-pack/ide-xml-tree-builder-ui.c
+++ b/plugins/xml-pack/ide-xml-tree-builder-ui.c
@@ -35,6 +35,8 @@ typedef struct _ParserState
   IdeXmlSax         *parser;
   IdeXmlStack       *stack;
   GFile             *file;
+  IdeXmlAnalysis    *analysis;
+  GPtrArray         *diagnostics_array;
   IdeXmlSymbolNode  *root_node;
   IdeXmlSymbolNode  *parent_node;
   IdeXmlSymbolNode  *current_node;
@@ -45,9 +47,12 @@ typedef struct _ParserState
 static void
 parser_state_free (ParserState *state)
 {
+  g_clear_pointer (&state->analysis, ide_xml_analysis_unref);
+  g_clear_pointer (&state->diagnostics_array, g_ptr_array_unref);
   g_clear_object (&state->stack);
   g_clear_object (&state->file);
   g_clear_object (&state->parser);
+  g_clear_object (&state->root_node);
 }
 
 static void
@@ -58,7 +63,7 @@ state_processing (ParserState           *state,
                   gboolean               is_internal)
 {
   IdeXmlSymbolNode *parent_node;
-  IdeXmlSymbolNode *popped_node;
+  IdeXmlSymbolNode *popped_node G_GNUC_UNUSED;
   g_autofree gchar *popped_element_name = NULL;
   gint line;
   gint line_offset;
@@ -157,7 +162,7 @@ start_element_sax_cb (ParserState    *state,
                       const xmlChar **attributes)
 {
   IdeXmlTreeBuilder *self = (IdeXmlTreeBuilder *)state->self;
-  g_autoptr (GString) string = NULL;
+  g_autoptr(GString) string = NULL;
   g_autofree gchar *label = NULL;
   const gchar *value = NULL;
   IdeXmlSymbolNode *node = NULL;
@@ -328,6 +333,97 @@ end_element_sax_cb (ParserState    *state,
   state_processing (state, (const gchar *)name, NULL, IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT, FALSE);
 }
 
+static IdeDiagnostic *
+create_diagnostic (ParserState            *state,
+                   const gchar            *msg,
+                   IdeDiagnosticSeverity   severity)
+{
+  IdeContext *context;
+  IdeDiagnostic *diagnostic;
+  g_autoptr(IdeSourceLocation) loc = NULL;
+  g_autoptr(IdeFile) ifile = NULL;
+  gint line;
+  gint line_offset;
+
+  context = ide_object_get_context (IDE_OBJECT (state->self));
+
+  ide_xml_sax_get_position (state->parser, &line, &line_offset);
+  ifile = ide_file_new (context, state->file);
+  loc = ide_source_location_new (ifile,
+                                 line - 1,
+                                 line_offset - 1,
+                                 0);
+
+  diagnostic = ide_diagnostic_new (severity, msg, loc);
+
+  return diagnostic;
+}
+
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wformat-nonliteral"
+
+static void
+warning_sax_cb (ParserState    *state,
+                const xmlChar  *name,
+                ...)
+{
+  IdeXmlTreeBuilder *self = (IdeXmlTreeBuilder *)state->self;
+  IdeDiagnostic *diagnostic;
+  g_autofree gchar *msg = NULL;
+  va_list var_args;
+
+  g_assert (IDE_IS_XML_TREE_BUILDER (self));
+
+  va_start (var_args, name);
+  msg = g_strdup_vprintf ((const gchar *)name, var_args);
+  va_end (var_args);
+
+  diagnostic = create_diagnostic (state, msg, IDE_DIAGNOSTIC_WARNING);
+  g_ptr_array_add (state->diagnostics_array, diagnostic);
+}
+
+static void
+error_sax_cb (ParserState    *state,
+              const xmlChar  *name,
+              ...)
+{
+  IdeXmlTreeBuilder *self = (IdeXmlTreeBuilder *)state->self;
+  IdeDiagnostic *diagnostic;
+  g_autofree gchar *msg = NULL;
+  va_list var_args;
+
+  g_assert (IDE_IS_XML_TREE_BUILDER (self));
+
+  va_start (var_args, name);
+  msg = g_strdup_vprintf ((const gchar *)name, var_args);
+  va_end (var_args);
+
+  diagnostic = create_diagnostic (state, msg, IDE_DIAGNOSTIC_ERROR);
+  g_ptr_array_add (state->diagnostics_array, diagnostic);
+}
+
+static void
+fatal_error_sax_cb (ParserState    *state,
+                    const xmlChar  *name,
+                    ...)
+{
+  IdeXmlTreeBuilder *self = (IdeXmlTreeBuilder *)state->self;
+  IdeDiagnostic *diagnostic;
+  g_autofree gchar *msg = NULL;
+  va_list var_args;
+
+  g_assert (IDE_IS_XML_TREE_BUILDER (self));
+
+  va_start (var_args, name);
+  msg = g_strdup_vprintf ((const gchar *)name, var_args);
+  va_end (var_args);
+
+  diagnostic = create_diagnostic (state, msg, IDE_DIAGNOSTIC_FATAL);
+  g_ptr_array_add (state->diagnostics_array, diagnostic);
+}
+
+#pragma GCC diagnostic pop
+
 static void
 characters_sax_cb (ParserState    *state,
                    const xmlChar  *name,
@@ -375,7 +471,7 @@ node_post_processing_collect_style_classes (IdeXmlTreeBuilder *self,
                                             IdeXmlSymbolNode  *node)
 {
   IdeXmlSymbolNode *child;
-  g_autoptr (GString) label = NULL;
+  g_autoptr(GString) label = NULL;
   gint n_children;
 
   g_assert (IDE_IS_XML_SYMBOL_NODE (node));
@@ -407,14 +503,17 @@ node_post_processing_add_label (IdeXmlTreeBuilder *self,
                                 IdeXmlSymbolNode  *node)
 {
   const gchar *value;
-  g_autoptr (GString) name = NULL;
+  g_autoptr(GString) name = NULL;
   g_autofree gchar *label = NULL;
 
   g_assert (IDE_IS_XML_SYMBOL_NODE (node));
 
   if (NULL != (value = get_menu_attribute_value (node, "label")))
     {
-      name = g_string_new (NULL);
+      g_object_get (node, "name", &label, NULL);
+      name = g_string_new (label);
+      g_free (label);
+
       label = ide_xml_tree_builder_get_color_tag (self, "label", COLOR_TAG_LABEL, TRUE, TRUE, TRUE);
 
       g_string_append (name, label);
@@ -452,16 +551,16 @@ ide_xml_tree_builder_post_processing (IdeXmlTreeBuilder *self,
 
       if (ide_str_equal0 (element_name, "style"))
         node_post_processing_collect_style_classes (self, node);
-      else if (ide_str_equal0 (element_name, "item"))
-        node_post_processing_add_label (self, node);
-      else if (ide_str_equal0 (element_name, "submenu"))
+      else if (ide_str_equal0 (element_name, "item") ||
+               ide_str_equal0 (element_name, "submenu") ||
+               ide_str_equal0 (element_name, "section"))
         node_post_processing_add_label (self, node);
     }
 
   return TRUE;
 }
 
-IdeXmlSymbolNode *
+IdeXmlAnalysis *
 ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
                                 IdeXmlSax         *parser,
                                 GFile             *file,
@@ -469,7 +568,8 @@ ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
                                 gsize              length)
 {
   ParserState *state;
-  IdeXmlSymbolNode *root_node;
+  IdeXmlAnalysis *analysis;
+  g_autoptr(IdeDiagnostics) diagnostics = NULL;
   g_autofree gchar *uri = NULL;
 
   g_return_val_if_fail (IDE_IS_XML_SAX (parser), NULL);
@@ -482,6 +582,7 @@ ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
   state->parser = g_object_ref (parser);
   state->stack = ide_xml_stack_new ();
   state->file = g_object_ref (file);
+  state->diagnostics_array = g_ptr_array_new_with_free_func ((GDestroyNotify)ide_diagnostic_unref);
   state->build_state = BUILD_STATE_NORMAL;
 
   ide_xml_sax_clear (parser);
@@ -489,16 +590,26 @@ ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
   ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT, end_element_sax_cb);
   ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_CHAR, characters_sax_cb);
 
+  ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_WARNING, warning_sax_cb);
+  ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_ERROR, error_sax_cb);
+  ide_xml_sax_set_callback (parser, IDE_XML_SAX_CALLBACK_TYPE_FATAL_ERROR, fatal_error_sax_cb);
+
+  state->analysis = ide_xml_analysis_new (-1);
   state->root_node = ide_xml_symbol_node_new ("root", NULL, "root", IDE_SYMBOL_NONE, NULL, 0, 0);
+  ide_xml_analysis_set_root_node (state->analysis, state->root_node);
+
   state->parent_node = state->root_node;
   ide_xml_stack_push (state->stack, "root", state->root_node, NULL, 0);
 
   uri = g_file_get_uri (file);
   ide_xml_sax_parse (parser, data, length, uri, state);
 
-  root_node = state->root_node;
-  parser_state_free (state);
+  ide_xml_tree_builder_post_processing (self, state->root_node);
 
-  ide_xml_tree_builder_post_processing (self, root_node);
-  return root_node;
+  analysis = g_steal_pointer (&state->analysis);
+  diagnostics = ide_diagnostics_new (g_steal_pointer (&state->diagnostics_array));
+  ide_xml_analysis_set_diagnostics (analysis, diagnostics);
+
+  parser_state_free (state);
+  return analysis;
 }
diff --git a/plugins/xml-pack/ide-xml-tree-builder-ui.h b/plugins/xml-pack/ide-xml-tree-builder-ui.h
index 1bb71c2..b570f5b 100644
--- a/plugins/xml-pack/ide-xml-tree-builder-ui.h
+++ b/plugins/xml-pack/ide-xml-tree-builder-ui.h
@@ -20,7 +20,9 @@
 #define IDE_XML_TREE_BUILDER_UI_H
 
 #include <glib.h>
+#include <ide.h>
 
+#include "ide-xml-analysis.h"
 #include "ide-xml-sax.h"
 #include "ide-xml-symbol-node.h"
 #include "ide-xml-tree-builder.h"
@@ -28,11 +30,11 @@
 
 G_BEGIN_DECLS
 
-IdeXmlSymbolNode *ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
-                                                  IdeXmlSax         *parser,
-                                                  GFile             *file,
-                                                  const gchar       *data,
-                                                  gsize              length);
+IdeXmlAnalysis *ide_xml_tree_builder_ui_create (IdeXmlTreeBuilder *self,
+                                                IdeXmlSax         *parser,
+                                                GFile             *file,
+                                                const gchar       *data,
+                                                gsize              length);
 
 G_END_DECLS
 
diff --git a/plugins/xml-pack/ide-xml-tree-builder.c b/plugins/xml-pack/ide-xml-tree-builder.c
index dd8aedc..78d90d5 100644
--- a/plugins/xml-pack/ide-xml-tree-builder.c
+++ b/plugins/xml-pack/ide-xml-tree-builder.c
@@ -67,6 +67,7 @@ typedef struct{
   IdeXmlSax *parser;
   GBytes    *content;
   GFile     *file;
+  gint64     sequence;
 } BuilderState;
 
 static void
@@ -81,11 +82,15 @@ G_DEFINE_TYPE (IdeXmlTreeBuilder, ide_xml_tree_builder, IDE_TYPE_OBJECT)
 
 static GBytes *
 ide_xml_tree_builder_get_file_content (IdeXmlTreeBuilder *self,
-                                       GFile             *file)
+                                       GFile             *file,
+                                       gint64            *sequence)
 {
   IdeContext *context;
   IdeBufferManager *manager;
+  IdeUnsavedFiles *unsaved_files;
+  IdeUnsavedFile *uf;
   IdeBuffer *buffer;
+  gint64 sequence_tmp = -1;
   GBytes *content = NULL;
 
   g_assert (IDE_IS_XML_TREE_BUILDER (self));
@@ -94,10 +99,17 @@ ide_xml_tree_builder_get_file_content (IdeXmlTreeBuilder *self,
   context = ide_object_get_context (IDE_OBJECT (self));
   manager = ide_context_get_buffer_manager (context);
 
-  printf ("found buffer:%p\n", ide_buffer_manager_find_buffer (manager, file));
-
   if (NULL != (buffer = ide_buffer_manager_find_buffer (manager, file)))
-    content = ide_buffer_get_content (buffer);
+    {
+      content = ide_buffer_get_content (buffer);
+
+      unsaved_files = ide_context_get_unsaved_files (context);
+      if (NULL != (uf = ide_unsaved_files_get_unsaved_file (unsaved_files, file)))
+        sequence_tmp = ide_unsaved_file_get_sequence (uf);
+    }
+
+  if (sequence != NULL)
+    *sequence = sequence_tmp;
 
   return content;
 }
@@ -135,7 +147,7 @@ build_tree_worker (GTask        *task,
 {
   IdeXmlTreeBuilder *self = (IdeXmlTreeBuilder *)source_object;
   BuilderState *state = (BuilderState *)task_data;
-  IdeXmlSymbolNode *root_node = NULL;
+  IdeXmlAnalysis *analysis = NULL;
   const gchar *data;
   gsize size;
 
@@ -147,11 +159,11 @@ build_tree_worker (GTask        *task,
   data = g_bytes_get_data (state->content, &size);
 
   if (ide_xml_tree_builder_file_is_ui (state->file, data, size))
-    root_node = ide_xml_tree_builder_ui_create (self, state->parser, state->file, data, size);
+    analysis = ide_xml_tree_builder_ui_create (self, state->parser, state->file, data, size);
   else
-    root_node = ide_xml_tree_builder_generic_create (self, state->parser, state->file, data, size);
+    analysis = ide_xml_tree_builder_generic_create (self, state->parser, state->file, data, size);
 
-  if (root_node == NULL)
+  if (analysis == NULL)
     {
       g_task_return_new_error (task,
                                G_IO_ERROR,
@@ -160,7 +172,8 @@ build_tree_worker (GTask        *task,
       return;
     }
 
-  g_task_return_pointer (task, root_node, g_object_unref);
+  ide_xml_analysis_set_sequence (analysis, state->sequence);
+  g_task_return_pointer (task, analysis, (GDestroyNotify)ide_xml_analysis_unref);
 }
 
 void
@@ -173,6 +186,7 @@ ide_xml_tree_builder_build_tree_async (IdeXmlTreeBuilder   *self,
   g_autoptr(GTask) task = NULL;
   BuilderState *state;
   GBytes *content = NULL;
+  gint64 sequence;
 
   g_return_if_fail (IDE_IS_XML_TREE_BUILDER (self));
   g_return_if_fail (G_IS_FILE (file));
@@ -181,7 +195,7 @@ ide_xml_tree_builder_build_tree_async (IdeXmlTreeBuilder   *self,
   task = g_task_new (self, cancellable, callback, user_data);
   g_task_set_source_tag (task, ide_xml_tree_builder_build_tree_async);
 
-  if (NULL == (content = ide_xml_tree_builder_get_file_content (self, file)))
+  if (NULL == (content = ide_xml_tree_builder_get_file_content (self, file, &sequence)))
     {
       g_task_return_new_error (task,
                                G_IO_ERROR,
@@ -194,12 +208,13 @@ ide_xml_tree_builder_build_tree_async (IdeXmlTreeBuilder   *self,
   state->parser = ide_xml_sax_new ();
   state->content = content;
   state->file = g_object_ref (file);
+  state->sequence = sequence;
 
   g_task_set_task_data (task, state, (GDestroyNotify)builder_state_free);
   g_task_run_in_thread (task, build_tree_worker);
 }
 
-IdeXmlSymbolNode *
+IdeXmlAnalysis *
 ide_xml_tree_builder_build_tree_finish (IdeXmlTreeBuilder  *self,
                                         GAsyncResult       *result,
                                         GError            **error)
diff --git a/plugins/xml-pack/ide-xml-tree-builder.h b/plugins/xml-pack/ide-xml-tree-builder.h
index 3a968d0..d903dab 100644
--- a/plugins/xml-pack/ide-xml-tree-builder.h
+++ b/plugins/xml-pack/ide-xml-tree-builder.h
@@ -19,6 +19,7 @@
 #ifndef IDE_XML_TREE_BUILDER_H
 #define IDE_XML_TREE_BUILDER_H
 
+#include "ide-xml-analysis.h"
 #include "ide-xml-symbol-node.h"
 
 #include <glib-object.h>
@@ -46,7 +47,7 @@ void                 ide_xml_tree_builder_build_tree_async       (IdeXmlTreeBuil
                                                                   GCancellable          *cancellable,
                                                                   GAsyncReadyCallback    callback,
                                                                   gpointer               user_data);
-IdeXmlSymbolNode    *ide_xml_tree_builder_build_tree_finish      (IdeXmlTreeBuilder     *self,
+IdeXmlAnalysis      *ide_xml_tree_builder_build_tree_finish      (IdeXmlTreeBuilder     *self,
                                                                   GAsyncResult          *result,
                                                                   GError               **error);
 gchar               *ide_xml_tree_builder_get_color_tag          (IdeXmlTreeBuilder     *self,
diff --git a/plugins/xml-pack/xml-pack-plugin.c b/plugins/xml-pack/xml-pack-plugin.c
index 2732265..8d69507 100644
--- a/plugins/xml-pack/xml-pack-plugin.c
+++ b/plugins/xml-pack/xml-pack-plugin.c
@@ -18,6 +18,7 @@
 
 #include <libpeas/peas.h>
 
+#include "ide-xml-diagnostic-provider.h"
 #include "ide-xml-highlighter.h"
 #include "ide-xml-indenter.h"
 #include "ide-xml-service.h"
@@ -36,6 +37,7 @@ peas_register_types (PeasObjectModule *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_DIAGNOSTIC_PROVIDER, 
IDE_TYPE_XML_DIAGNOSTIC_PROVIDER);
   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);
diff --git a/plugins/xml-pack/xml-pack.plugin b/plugins/xml-pack/xml-pack.plugin
index f1b03f4..20a6d9b 100644
--- a/plugins/xml-pack/xml-pack.plugin
+++ b/plugins/xml-pack/xml-pack.plugin
@@ -11,3 +11,5 @@ X-Symbol-Resolver-Languages=xml,html
 X-Symbol-Resolver-Languages-Priority=0
 X-Highlighter-Languages=xml,html
 X-Highlighter-Languages-Priority=0
+X-Diagnostic-Provider-Languages=xml,html
+X-Diagnostic-Provider-Languages-Priority=0


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