[gnome-builder/wip/slaf/xml-pack: 549/572] xml-pack: add more internal nodes to the trees



commit 22434efc2d682fa7167d2282eb1892090b353b2b
Author: Sebastien Lafargue <slafargue gnome org>
Date:   Sat Apr 1 11:45:04 2017 +0200

    xml-pack: add more internal nodes to the trees
    
    Previously, we were integrating only needed/visible nodes
    (the ones we need for the symbol tree view)
    
    As a start, we integrate all start elements.
    The final purpose is the be able to match a position
    in the source doc with a node in the tree and
    compare the doc tree with schemas tree for the yet to come
    autocompletion based on schemas.

 plugins/xml-pack/ide-xml-parser.c      |   14 ++-
 plugins/xml-pack/ide-xml-sax.c         |   27 ++++-
 plugins/xml-pack/ide-xml-sax.h         |    4 +-
 plugins/xml-pack/ide-xml-symbol-node.c |  168 +++++++++++++++++++++++++++----
 plugins/xml-pack/ide-xml-symbol-node.h |    3 +
 5 files changed, 183 insertions(+), 33 deletions(-)
---
diff --git a/plugins/xml-pack/ide-xml-parser.c b/plugins/xml-pack/ide-xml-parser.c
index 259d82e..74ffd3c 100644
--- a/plugins/xml-pack/ide-xml-parser.c
+++ b/plugins/xml-pack/ide-xml-parser.c
@@ -172,11 +172,19 @@ ide_xml_parser_state_processing (IdeXmlParser          *self,
     }
 
   depth = ide_xml_sax_get_depth (self->sax_parser);
+  ide_xml_sax_get_location (self->sax_parser, &line, &line_offset, NULL, NULL, &size);
 
   if (node == NULL)
     {
       if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_START_ELEMENT)
-        ide_xml_stack_push (self->stack, element_name, NULL, state->parent_node, depth);
+        {
+          node = ide_xml_symbol_node_new ("internal", NULL, element_name, IDE_SYMBOL_XML_ELEMENT, NULL, 0, 
0, 0);
+          ide_xml_symbol_node_set_location (node, g_object_ref (state->file), line, line_offset, size);
+
+          ide_xml_stack_push (self->stack, element_name, node, state->parent_node, depth);
+          ide_xml_symbol_node_take_internal_child (state->parent_node, node);
+          state->parent_node = node;
+        }
       else if (callback_type == IDE_XML_SAX_CALLBACK_TYPE_END_ELEMENT)
         {
           /* TODO: compare current with popped */
@@ -192,11 +200,11 @@ ide_xml_parser_state_processing (IdeXmlParser          *self,
         }
 
       state->current_depth = depth;
-      state->current_node = NULL;
+      state->current_node = node;
       return;
     }
 
-  ide_xml_sax_get_location (self->sax_parser, &line, &line_offset, NULL, NULL, &size);
+
   ide_xml_symbol_node_set_location (node, g_object_ref (state->file), line, line_offset, size);
 
   /* TODO: take end elements into account and use:
diff --git a/plugins/xml-pack/ide-xml-sax.c b/plugins/xml-pack/ide-xml-sax.c
index 051990f..18e9e5b 100644
--- a/plugins/xml-pack/ide-xml-sax.c
+++ b/plugins/xml-pack/ide-xml-sax.c
@@ -182,15 +182,16 @@ ide_xml_sax_parse (IdeXmlSax   *self,
 
 static void
 get_tag_location (IdeXmlSax *self,
-                  gint       *line,
-                  gint       *line_offset,
-                  gsize      *size)
+                  gint      *line,
+                  gint      *line_offset,
+                  gsize     *size)
 {
   xmlParserInput *input;
   const gchar *base;
   const gchar *current;
   const gchar *line_start;
   gint start_line_number;
+  gint size_offset = 1;
   gunichar ch;
 
   g_assert (IDE_IS_XML_SAX (self));
@@ -205,8 +206,22 @@ get_tag_location (IdeXmlSax *self,
   current = (const gchar *)input->cur;
   start_line_number = xmlSAX2GetLineNumber (self->context);
 
-  if (g_utf8_get_char (current) == '\n' && current > base)
-    --current;
+  /* Adjust the element size, can be a start, a end or an auto-closed one */
+  if (g_utf8_get_char (current) != '>')
+    {
+      /* Auto-closed start element case */
+      if (g_utf8_get_char (current) == '/' && g_utf8_get_char (current + 1) == '>')
+        {
+          ++current;
+          size_offset = 2;
+        }
+      /* End element case */
+      else if (current > base && g_utf8_get_char (current - 1) == '>')
+        {
+          --current;
+          size_offset = 0;
+        }
+    }
 
   if (g_utf8_get_char (current) != '>')
     {
@@ -244,7 +259,7 @@ get_tag_location (IdeXmlSax *self,
 
   *line = start_line_number;
   *line_offset = (current - line_start) + 1;
-  *size = (const gchar *)input->cur - current;
+  *size = (const gchar *)input->cur - current + size_offset;
 }
 
 gboolean
diff --git a/plugins/xml-pack/ide-xml-sax.h b/plugins/xml-pack/ide-xml-sax.h
index 45a1217..d9c1fa3 100644
--- a/plugins/xml-pack/ide-xml-sax.h
+++ b/plugins/xml-pack/ide-xml-sax.h
@@ -50,8 +50,8 @@ enum _IdeXmlSaxCallbackType {
 void            ide_xml_sax_clear               (IdeXmlSax              *self);
 gint            ide_xml_sax_get_depth           (IdeXmlSax              *self);
 gboolean        ide_xml_sax_get_location        (IdeXmlSax              *self,
-                                                 gint                   *line,
-                                                 gint                   *line_offset,
+                                                 gint                   *start_line,
+                                                 gint                   *start_line_offset,
                                                  gint                   *end_line,
                                                  gint                   *end_line_offset,
                                                  gsize                  *size);
diff --git a/plugins/xml-pack/ide-xml-symbol-node.c b/plugins/xml-pack/ide-xml-symbol-node.c
index e41e04a..ce47604 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.c
+++ b/plugins/xml-pack/ide-xml-symbol-node.c
@@ -21,13 +21,20 @@
 
 #include "ide-xml-symbol-node.h"
 
+typedef struct _NodeEntry
+{
+  IdeXmlSymbolNode *node;
+  guint             is_internal : 1;
+} NodeEntry;
+
 struct _IdeXmlSymbolNode
 {
   IdeSymbolNode             parent_instance;
-  GPtrArray                *children;
-  GPtrArray                *internal_children;
+  GArray                   *children;
   gchar                    *value;
   gchar                    *element_name;
+  gint                      nb_children;
+  gint                      nb_internal_children;
   GFile                    *file;
   gint                      line;
   gint                      line_offset;
@@ -85,8 +92,7 @@ ide_xml_symbol_node_finalize (GObject *object)
 {
   IdeXmlSymbolNode *self = (IdeXmlSymbolNode *)object;
 
-  g_clear_pointer (&self->children, g_ptr_array_unref);
-  g_clear_pointer (&self->internal_children, g_ptr_array_unref);
+  g_clear_pointer (&self->children, g_array_unref);
 
   g_clear_pointer (&self->element_name, g_free);
   g_clear_pointer (&self->value, g_free);
@@ -155,22 +161,111 @@ ide_xml_symbol_node_new (const gchar            *name,
 guint
 ide_xml_symbol_node_get_n_children (IdeXmlSymbolNode *self)
 {
+  NodeEntry *entry;
+  guint nb_children = 0;
+
   g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), 0);
 
-  return self->children != NULL ? self->children->len : 0;
+  if (self->children != NULL)
+    {
+      for (gint n = 0; n < self->children->len; ++n)
+        {
+          entry = &g_array_index (self->children, NodeEntry, n);
+          if (entry->is_internal)
+            {
+              nb_children += ide_xml_symbol_node_get_n_children (entry->node);
+              continue;
+            }
+
+          ++nb_children;
+        }
+    }
+
+  return nb_children;
+}
+
+IdeSymbolNode *
+ide_xml_symbol_node_get_nth_child_deep (IdeXmlSymbolNode *self,
+                                        guint             nth_child,
+                                        guint            *current_pos)
+{
+  IdeSymbolNode *node;
+  NodeEntry *entry;
+
+  g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
+
+  if (self->children == NULL)
+    return NULL;
+
+  for (gint n = 0; n < self->children->len; ++n)
+    {
+      entry = &g_array_index (self->children, NodeEntry, n);
+      if (entry->is_internal)
+        {
+          node = ide_xml_symbol_node_get_nth_child_deep (entry->node, nth_child, current_pos);
+          if (node == NULL)
+            continue;
+
+          return IDE_SYMBOL_NODE (g_object_ref (node));
+        }
+      else
+        node = IDE_SYMBOL_NODE (entry->node);
+
+      if (*current_pos == nth_child)
+        return IDE_SYMBOL_NODE (g_object_ref (node));
+
+      ++(*current_pos);
+    }
+
+  return NULL;
+}
+
+static IdeSymbolNode *
+get_nth_child (IdeXmlSymbolNode *self,
+               guint             nth_child,
+               gboolean          internal)
+{
+  NodeEntry *entry;
+  guint pos = 0;
+
+  if (self->children != NULL)
+    {
+      if (internal)
+        {
+          for (gint n = 0; n < self->children->len; ++n)
+            {
+              entry = &g_array_index (self->children, NodeEntry, n);
+              if (entry->is_internal)
+                {
+                  if (pos == nth_child)
+                    return (IdeSymbolNode *)g_object_ref (entry->node);
+
+                  ++pos;
+                }
+            }
+        }
+      else
+        return ide_xml_symbol_node_get_nth_child_deep (self, nth_child, &pos);
+    }
+
+  return NULL;
 }
 
 IdeSymbolNode *
 ide_xml_symbol_node_get_nth_child (IdeXmlSymbolNode *self,
                                    guint             nth_child)
 {
+  IdeSymbolNode *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));
+  if (NULL == (child = get_nth_child (self, nth_child, FALSE)))
+    {
+      g_warning ("nth child %u is out of bounds", nth_child);
+      return NULL;
+    }
 
-  g_warning ("nth child %u is out of bounds", nth_child);
-  return NULL;
+  return child;
 }
 
 guint
@@ -178,20 +273,53 @@ ide_xml_symbol_node_get_n_internal_children (IdeXmlSymbolNode *self)
 {
   g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), 0);
 
-  return self->internal_children != NULL ? self->internal_children->len : 0;
+  return self->nb_internal_children;
 }
 
 IdeSymbolNode *
 ide_xml_symbol_node_get_nth_internal_child (IdeXmlSymbolNode *self,
                                             guint             nth_child)
 {
+  IdeSymbolNode *child;
+
   g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
 
-  if (self->internal_children != NULL && nth_child < self->internal_children->len)
-    return g_object_ref (g_ptr_array_index (self->internal_children, nth_child));
+  if (NULL == (child = get_nth_child (self, nth_child, TRUE)))
+    {
+      g_warning ("nth child %u is out of bounds", nth_child);
+      return NULL;
+    }
 
-  g_warning ("nth child %u is out of bounds", nth_child);
-  return NULL;
+  return child;
+}
+
+static void
+node_entry_free (gpointer data)
+{
+  NodeEntry *node_entry = (NodeEntry *)data;
+
+  g_assert (node_entry->node != NULL);
+
+  g_object_unref (node_entry->node);
+}
+
+static void
+take_child (IdeXmlSymbolNode *self,
+            IdeXmlSymbolNode *child,
+            gboolean          is_internal)
+{
+  NodeEntry node_entry;
+
+  if (self->children == NULL)
+    {
+      self->children = g_array_new (FALSE, TRUE, sizeof (NodeEntry));
+      g_array_set_clear_func (self->children, node_entry_free);
+    }
+
+  node_entry.node = child;
+  node_entry.is_internal = is_internal;
+
+  g_array_append_val (self->children, node_entry);
 }
 
 void
@@ -201,10 +329,8 @@ ide_xml_symbol_node_take_child (IdeXmlSymbolNode *self,
   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);
+  take_child (self, child, FALSE);
+  ++self->nb_children;
 }
 
 void
@@ -214,10 +340,8 @@ ide_xml_symbol_node_take_internal_child (IdeXmlSymbolNode *self,
   g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (self));
   g_return_if_fail (IDE_IS_XML_SYMBOL_NODE (child));
 
-  if (self->internal_children == NULL)
-    self->internal_children = g_ptr_array_new_with_free_func (g_object_unref);
-
-  g_ptr_array_add (self->internal_children, child);
+  take_child (self, child, TRUE);
+  ++self->nb_internal_children;
 }
 
 void
diff --git a/plugins/xml-pack/ide-xml-symbol-node.h b/plugins/xml-pack/ide-xml-symbol-node.h
index b1a8e3b..d1130c4 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.h
+++ b/plugins/xml-pack/ide-xml-symbol-node.h
@@ -50,6 +50,9 @@ guint                     ide_xml_symbol_node_get_n_children                (Ide
 guint                     ide_xml_symbol_node_get_n_internal_children       (IdeXmlSymbolNode       *self);
 IdeSymbolNode            *ide_xml_symbol_node_get_nth_child                 (IdeXmlSymbolNode       *self,
                                                                              guint                   
nth_child);
+IdeSymbolNode            *ide_xml_symbol_node_get_nth_child_deep            (IdeXmlSymbolNode       *self,
+                                                                             guint                   
nth_child,
+                                                                             guint                  
*current_pos);
 IdeSymbolNode            *ide_xml_symbol_node_get_nth_internal_child        (IdeXmlSymbolNode       *self,
                                                                              guint                   
nth_child);
 const gchar              *ide_xml_symbol_node_get_value                     (IdeXmlSymbolNode       *self);


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