[gnome-builder/wip/slaf/xml-pack: 205/254] xml-pack: add more internal nodes to the trees
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/slaf/xml-pack: 205/254] xml-pack: add more internal nodes to the trees
- Date: Thu, 13 Jul 2017 09:06:26 +0000 (UTC)
commit 1c8dba33fb8210e7b680ba3b422b3a424b588656
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]