[gnome-builder/wip/slaf/xml-pack: 2/11] xml-pack: get the matching nodes in the rng tree
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/slaf/xml-pack: 2/11] xml-pack: get the matching nodes in the rng tree
- Date: Tue, 27 Jun 2017 21:52:23 +0000 (UTC)
commit 5320a87ac43c3828fbfd49f7420deb33d8565057
Author: Sebastien Lafargue <slafargue gnome org>
Date: Sun May 28 11:42:59 2017 +0200
xml-pack: get the matching nodes in the rng tree
One more step closer to getting some completion items.
Here we now know for a document node, what are the
corresponding nodes in the parsed rng schema.
plugins/xml-pack/ide-xml-completion-provider.c | 146 +++++++++++++++++++++++-
plugins/xml-pack/ide-xml-rng-define.c | 73 ++++++++++++-
plugins/xml-pack/ide-xml-rng-define.h | 28 +++--
plugins/xml-pack/ide-xml-symbol-node.c | 9 ++
plugins/xml-pack/ide-xml-symbol-node.h | 1 +
plugins/xml-pack/ide-xml-tree-builder.c | 5 +-
6 files changed, 240 insertions(+), 22 deletions(-)
---
diff --git a/plugins/xml-pack/ide-xml-completion-provider.c b/plugins/xml-pack/ide-xml-completion-provider.c
index 6f4ab6a..c862511 100644
--- a/plugins/xml-pack/ide-xml-completion-provider.c
+++ b/plugins/xml-pack/ide-xml-completion-provider.c
@@ -21,8 +21,11 @@
#include <libpeas/peas.h>
#include "ide-xml-completion-provider.h"
+
+#include "ide.h"
#include "ide-xml-path.h"
#include "ide-xml-position.h"
+#include "ide-xml-schema-cache-entry.h"
#include "ide-xml-service.h"
struct _IdeXmlCompletionProvider
@@ -84,15 +87,143 @@ get_path (IdeXmlSymbolNode *node,
current = ide_xml_symbol_node_get_parent (current);
}
- if (current == root_node)
- ide_xml_path_prepend_node (path, current);
- else
+ if (current != root_node)
g_warning ("partial path, we don't reach the root node");
return path;
}
static void
+move_candidates (GPtrArray *array,
+ GPtrArray *sub_array)
+{
+ if (sub_array->len == 0)
+ return;
+
+ for (gint i = 0; i < sub_array->len; ++i)
+ g_ptr_array_add (array, g_ptr_array_index (sub_array, i));
+
+ g_ptr_array_remove_range (sub_array, 0, sub_array->len);
+}
+
+static void
+get_matching_nodes (IdeXmlPath *path,
+ gint index,
+ IdeXmlRngDefine *define,
+ GPtrArray *candidates)
+{
+ IdeXmlSymbolNode *node;
+ IdeXmlRngDefine *child;
+ IdeXmlRngDefineType type;
+ gint current_index;
+
+ g_assert (path != NULL);
+ g_assert (define != NULL);
+ g_assert (candidates != NULL);
+
+ if (define == NULL)
+ return;
+
+ node = g_ptr_array_index (path->nodes, index);
+
+ while (define != NULL)
+ {
+ child = NULL;
+ current_index = index;
+ type = define->type;
+
+ switch (type)
+ {
+ case IDE_XML_RNG_DEFINE_ELEMENT:
+ if (ide_xml_rng_define_is_nameclass_match (define, node))
+ {
+ ++current_index;
+ child = define->content;
+ }
+
+ break;
+
+ case IDE_XML_RNG_DEFINE_NOOP:
+ case IDE_XML_RNG_DEFINE_NOTALLOWED:
+ case IDE_XML_RNG_DEFINE_TEXT:
+ case IDE_XML_RNG_DEFINE_DATATYPE:
+ case IDE_XML_RNG_DEFINE_VALUE:
+ case IDE_XML_RNG_DEFINE_EMPTY:
+ case IDE_XML_RNG_DEFINE_ATTRIBUTE:
+ case IDE_XML_RNG_DEFINE_START:
+ case IDE_XML_RNG_DEFINE_PARAM:
+ case IDE_XML_RNG_DEFINE_EXCEPT:
+ case IDE_XML_RNG_DEFINE_LIST:
+ break;
+
+ case IDE_XML_RNG_DEFINE_DEFINE:
+ case IDE_XML_RNG_DEFINE_REF:
+ case IDE_XML_RNG_DEFINE_PARENTREF:
+ case IDE_XML_RNG_DEFINE_EXTERNALREF:
+ child = define->content;
+ break;
+
+ case IDE_XML_RNG_DEFINE_ZEROORMORE:
+ case IDE_XML_RNG_DEFINE_ONEORMORE:
+ case IDE_XML_RNG_DEFINE_OPTIONAL:
+ case IDE_XML_RNG_DEFINE_CHOICE:
+ case IDE_XML_RNG_DEFINE_GROUP:
+ case IDE_XML_RNG_DEFINE_INTERLEAVE:
+ child = define->content;
+ break;
+
+ default:
+ g_assert_not_reached ();
+ }
+
+ if (current_index == path->nodes->len)
+ g_ptr_array_add (candidates, define);
+ else if (child != NULL)
+ get_matching_nodes (path, current_index, child, candidates);
+
+ define = define->next;
+ }
+}
+
+static GPtrArray *
+get_matching_candidates (IdeXmlCompletionProvider *self,
+ GPtrArray *schemas,
+ IdeXmlPath *path)
+{
+ GPtrArray *candidates;
+ g_autoptr (GPtrArray) candidates_tmp = NULL;
+ g_autoptr (GPtrArray) defines = NULL;
+ IdeXmlSchemaCacheEntry *schema_entry;
+ IdeXmlSchema *schema;
+ IdeXmlRngGrammar *grammar;
+
+ g_assert (IDE_IS_XML_COMPLETION_PROVIDER (self));
+ g_assert (schemas != NULL);
+ g_assert (path != NULL && path->nodes->len > 0);
+
+ candidates = g_ptr_array_new ();
+ candidates_tmp = g_ptr_array_sized_new (16);
+ defines = g_ptr_array_new ();
+
+ for (gint i = 0; i < schemas->len; ++i)
+ {
+ schema_entry = g_ptr_array_index (schemas, i);
+ /* TODO: only RNG for now */
+ if (schema_entry->kind != SCHEMA_KIND_RNG ||
+ schema_entry->state != SCHEMA_STATE_PARSED)
+ continue;
+
+ schema = schema_entry->schema;
+ grammar = schema->top_grammar;
+
+ get_matching_nodes (path, 0, grammar->start_defines, candidates_tmp);
+ move_candidates (candidates, candidates_tmp);
+ }
+
+ return candidates;
+}
+
+static void
populate_cb (GObject *object,
GAsyncResult *result,
gpointer user_data)
@@ -104,11 +235,13 @@ populate_cb (GObject *object,
IdeXmlSymbolNode *root_node, *node;
IdeXmlAnalysis *analysis;
IdeXmlPositionKind kind;
- IdeXmlPath *path;
+ g_autoptr (IdeXmlPath) path = NULL;
GtkSourceCompletionItem *item;
g_autofree gchar *text = NULL;
g_autofree gchar *label = NULL;
g_autoptr (GList) results = NULL;
+ GPtrArray *schemas;
+ g_autoptr (GPtrArray) candidates = NULL;
GError *error = NULL;
g_assert (IDE_IS_XML_COMPLETION_PROVIDER (self));
@@ -116,12 +249,17 @@ populate_cb (GObject *object,
position = ide_xml_service_get_position_from_cursor_finish (service, result, &error);
analysis = ide_xml_position_get_analysis (position);
+ schemas = ide_xml_analysis_get_schemas (analysis);
root_node = ide_xml_analysis_get_root_node (analysis);
node = ide_xml_position_get_node (position);
kind = ide_xml_position_get_kind (position);
path = get_path (node, root_node);
+ if (schemas != NULL)
+ candidates = get_matching_candidates (self, schemas, path);
+
+
text = g_strdup ("xml item text");
label = g_strdup ("xml item label");
item = g_object_new (GTK_SOURCE_TYPE_COMPLETION_ITEM,
diff --git a/plugins/xml-pack/ide-xml-rng-define.c b/plugins/xml-pack/ide-xml-rng-define.c
index 24777df..2e64b17 100644
--- a/plugins/xml-pack/ide-xml-rng-define.c
+++ b/plugins/xml-pack/ide-xml-rng-define.c
@@ -46,6 +46,14 @@ static gchar *type_names [] =
"except"
};
+const gchar *
+ide_xml_rng_define_get_type_name (IdeXmlRngDefine *self)
+{
+ g_return_val_if_fail (self != NULL, NULL);
+
+ return type_names [self->type];
+}
+
static void
dump_tree (IdeXmlRngDefine *self,
gint indent)
@@ -58,8 +66,10 @@ dump_tree (IdeXmlRngDefine *self,
pad = g_strnfill (indent, ' ');
while (def != NULL)
{
- type_name = type_names [def->type];
- if (def->type == IDE_XML_RNG_DEFINE_REF || def->type == IDE_XML_RNG_DEFINE_PARENTREF)
+ type_name = ide_xml_rng_define_get_type_name (def);
+ if (def->type == IDE_XML_RNG_DEFINE_REF ||
+ def->type == IDE_XML_RNG_DEFINE_PARENTREF ||
+ def->type == IDE_XML_RNG_DEFINE_EXTERNALREF)
{
if (def->node != NULL &&
NULL != (name = xmlGetProp (def->node, (const guchar *)"name")))
@@ -218,3 +228,62 @@ ide_xml_rng_define_propagate_parent (IdeXmlRngDefine *self,
last = last->next;
} while (last != NULL);
}
+
+gboolean
+ide_xml_rng_define_is_nameclass_match (IdeXmlRngDefine *define,
+ IdeXmlSymbolNode *node)
+{
+ const gchar *name;
+ const gchar *namespace;
+ IdeXmlRngDefine *nc;
+ IdeXmlRngDefine *content;
+
+ g_assert (IDE_IS_XML_SYMBOL_NODE (node));
+ g_assert (define != NULL);
+
+ name = ide_xml_symbol_node_get_element_name (node);
+ namespace = ide_xml_symbol_node_get_namespace (node);
+
+ if (define->name != NULL && !ide_str_equal0 (name, define->name))
+ return FALSE;
+
+ if (!ide_str_empty0 ((const gchar *)define->ns))
+ {
+ if (namespace == NULL || !ide_str_equal0 (define->ns, namespace))
+ return FALSE;
+ }
+ else if (namespace != NULL && (define->name != NULL || define->ns != NULL))
+ return FALSE;
+
+ if (NULL == (nc = define->name_class))
+ return TRUE;
+
+ if (nc->type == IDE_XML_RNG_DEFINE_EXCEPT)
+ {
+ content = nc->content;
+ while (content != NULL)
+ {
+ if (ide_xml_rng_define_is_nameclass_match (content, node))
+ return FALSE;
+
+ content = content->next;
+ }
+
+ return TRUE;
+ }
+ else if (nc->type == IDE_XML_RNG_DEFINE_CHOICE)
+ {
+ content = define->name_class;
+ while (content != NULL)
+ {
+ if (ide_xml_rng_define_is_nameclass_match (content, node))
+ return TRUE;
+
+ content = content->next;
+ }
+
+ return FALSE;
+ }
+ else
+ g_assert_not_reached ();
+}
diff --git a/plugins/xml-pack/ide-xml-rng-define.h b/plugins/xml-pack/ide-xml-rng-define.h
index 1bf49df..28136e9 100644
--- a/plugins/xml-pack/ide-xml-rng-define.h
+++ b/plugins/xml-pack/ide-xml-rng-define.h
@@ -21,6 +21,7 @@
#include <libxml/tree.h>
#include <glib-object.h>
+#include "ide-xml-symbol-node.h"
G_BEGIN_DECLS
@@ -73,18 +74,21 @@ struct _IdeXmlRngDefine
guint is_ref_simplified : 1;
};
-IdeXmlRngDefine *ide_xml_rng_define_new (xmlNode *node,
- IdeXmlRngDefine *parent,
- const guchar *name,
- IdeXmlRngDefineType type);
-void ide_xml_rng_define_append (IdeXmlRngDefine *self,
- IdeXmlRngDefine *def);
-void ide_xml_rng_define_propagate_parent (IdeXmlRngDefine *self,
- IdeXmlRngDefine *parent);
-IdeXmlRngDefine *ide_xml_rng_define_ref (IdeXmlRngDefine *self);
-void ide_xml_rng_define_unref (IdeXmlRngDefine *self);
-void ide_xml_rng_define_dump_tree (IdeXmlRngDefine *self,
- gboolean recursive);
+IdeXmlRngDefine *ide_xml_rng_define_new (xmlNode *node,
+ IdeXmlRngDefine *parent,
+ const guchar *name,
+ IdeXmlRngDefineType type);
+void ide_xml_rng_define_append (IdeXmlRngDefine *self,
+ IdeXmlRngDefine *def);
+const gchar *ide_xml_rng_define_get_type_name (IdeXmlRngDefine *self);
+gboolean ide_xml_rng_define_is_nameclass_match (IdeXmlRngDefine *define,
+ IdeXmlSymbolNode *node);
+void ide_xml_rng_define_propagate_parent (IdeXmlRngDefine *self,
+ IdeXmlRngDefine *parent);
+IdeXmlRngDefine *ide_xml_rng_define_ref (IdeXmlRngDefine *self);
+void ide_xml_rng_define_unref (IdeXmlRngDefine *self);
+void ide_xml_rng_define_dump_tree (IdeXmlRngDefine *self,
+ gboolean recursive);
G_DEFINE_AUTOPTR_CLEANUP_FUNC (IdeXmlRngDefine, ide_xml_rng_define_unref)
diff --git a/plugins/xml-pack/ide-xml-symbol-node.c b/plugins/xml-pack/ide-xml-symbol-node.c
index d1fc4cc..43a758f 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.c
+++ b/plugins/xml-pack/ide-xml-symbol-node.c
@@ -48,6 +48,7 @@ struct _IdeXmlSymbolNode
gint nb_internal_children;
GFile *file;
gchar **attributes_names;
+ gchar *ns;
NodeRange start_tag;
NodeRange end_tag;
@@ -686,3 +687,11 @@ ide_xml_symbol_node_print (IdeXmlSymbolNode *self,
if (show_value && self->value != NULL)
printf ("\t%s\n", self->value);
}
+
+const gchar *
+ide_xml_symbol_node_get_namespace (IdeXmlSymbolNode *self)
+{
+ g_return_val_if_fail (IDE_IS_XML_SYMBOL_NODE (self), NULL);
+
+ return self->ns;
+}
diff --git a/plugins/xml-pack/ide-xml-symbol-node.h b/plugins/xml-pack/ide-xml-symbol-node.h
index a776c57..cdb5cd3 100644
--- a/plugins/xml-pack/ide-xml-symbol-node.h
+++ b/plugins/xml-pack/ide-xml-symbol-node.h
@@ -54,6 +54,7 @@ void ide_xml_symbol_node_get_end_tag_location (Ide
gint
*end_line,
gint
*end_line_offset,
gsize *size);
+const gchar *ide_xml_symbol_node_get_namespace (IdeXmlSymbolNode *self);
guint ide_xml_symbol_node_get_n_children (IdeXmlSymbolNode *self);
guint ide_xml_symbol_node_get_n_internal_children (IdeXmlSymbolNode *self);
IdeSymbolNode *ide_xml_symbol_node_get_nth_child (IdeXmlSymbolNode *self,
diff --git a/plugins/xml-pack/ide-xml-tree-builder.c b/plugins/xml-pack/ide-xml-tree-builder.c
index 4ed4d8f..b205d6d 100644
--- a/plugins/xml-pack/ide-xml-tree-builder.c
+++ b/plugins/xml-pack/ide-xml-tree-builder.c
@@ -355,10 +355,7 @@ ide_xml_tree_builder_build_tree_cb2 (GObject *object,
if (ide_xml_validator_validate (self->validator, doc, &diagnostics))
printf ("validated\n");
else
- {
- printf ("NOT validated\n");
- entry->state = SCHEMA_STATE_CANT_VALIDATE;
- }
+ printf ("NOT validated\n");
ide_diagnostics_merge (state->analysis->diagnostics, diagnostics);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]