[gnome-builder/wip/slaf/xml-pack: 47/56] xml-pack: get position details infos fron nodes tree
- From: Sébastien Lafargue <slafargue src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-builder/wip/slaf/xml-pack: 47/56] xml-pack: get position details infos fron nodes tree
- Date: Thu, 13 Jul 2017 12:22:58 +0000 (UTC)
commit c953ef0126fda9326c92c5289ec544d24b04d75f
Author: Sebastien Lafargue <slafargue gnome org>
Date: Sun Jul 9 16:05:49 2017 +0200
xml-pack: get position details infos fron nodes tree
plugins/xml-pack/ide-xml-service.c | 198 +++++++++++++++++++++++++++++++---
plugins/xml-pack/ide-xml-utils.c | 208 ++++++++++++++++++++++++++++++++++++
plugins/xml-pack/ide-xml-utils.h | 33 ++++++
plugins/xml-pack/meson.build | 2 +
4 files changed, 425 insertions(+), 16 deletions(-)
---
diff --git a/plugins/xml-pack/ide-xml-service.c b/plugins/xml-pack/ide-xml-service.c
index 6eab2a4..f05c0cc 100644
--- a/plugins/xml-pack/ide-xml-service.c
+++ b/plugins/xml-pack/ide-xml-service.c
@@ -28,6 +28,7 @@
#include "ide-xml-schema-cache-entry.h"
#include "ide-xml-tree-builder.h"
#include "ide-xml-types.h"
+#include "ide-xml-utils.h"
#include "ide-xml-service.h"
#include "ide-xml-tree-builder.h"
@@ -627,6 +628,161 @@ position_state_free (PositionState *state)
g_object_unref (state->buffer);
}
+static inline gboolean
+skip_whitespaces (const gchar **cursor)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+
+ g_assert (cursor != NULL && *cursor != NULL);
+
+ while ((ch = g_utf8_get_char (*cursor)) && g_unichar_isspace (ch))
+ *cursor = g_utf8_next_char (*cursor);
+
+ return (p != *cursor);
+}
+
+static inline void
+skip_all_name (const gchar **cursor)
+{
+ gunichar ch;
+
+ g_assert (cursor != NULL && *cursor != NULL);
+
+ while ((ch = g_utf8_get_char (*cursor)) && !g_unichar_isspace (ch))
+ *cursor = g_utf8_next_char (*cursor);
+}
+
+static IdeXmlPositionDetail
+get_detail (IdeXmlSymbolNode *node,
+ const gchar *prefix,
+ gunichar next_ch,
+ gchar **name,
+ gchar **value,
+ gchar *quote)
+{
+ IdeXmlPositionDetail detail;
+ const gchar *cursor, *start;
+ const gchar *name_start;
+ gsize name_size;
+ gboolean has_spaces = FALSE;
+
+ g_assert (IDE_IS_XML_SYMBOL_NODE (node));
+ g_assert (prefix != NULL);
+ g_assert (value != NULL);
+
+ *name = NULL;
+ *value = NULL;
+ *quote = 0;
+
+ cursor = prefix;
+ detail = IDE_XML_POSITION_DETAIL_IN_NAME;
+ if (!ide_xml_utils_skip_element_name (&cursor))
+ return IDE_XML_POSITION_DETAIL_NONE;
+
+ if (*cursor == 0)
+ {
+ if (!g_unichar_isspace (next_ch) && next_ch != '<' && next_ch != '>')
+ return IDE_XML_POSITION_DETAIL_NONE;
+ else
+ {
+ *name = g_strdup (prefix);
+ return detail;
+ }
+ }
+
+ detail = IDE_XML_POSITION_DETAIL_IN_ATTRIBUTE_NAME;
+ /* Whitespaces after the element name */
+ skip_whitespaces (&cursor);
+ if (*cursor == 0)
+ return detail;
+
+ while (TRUE)
+ {
+ *quote = 0;
+ start = cursor;
+ /* Attribute name */
+ if (!ide_xml_utils_skip_attribute_name (&cursor))
+ continue;
+
+ if (*cursor == 0)
+ {
+ if (!g_unichar_isspace (next_ch) && next_ch != '=')
+ return IDE_XML_POSITION_DETAIL_NONE;
+
+ *name = g_strndup (start, cursor - start);
+ return detail;
+ }
+
+ name_start = start;
+ name_size = cursor - start;
+ /* Whitespaces between the name and the = */
+ skip_whitespaces (&cursor);
+ if (*cursor == 0)
+ return detail;
+
+ if (*cursor != '=')
+ continue;
+ else
+ cursor++;
+
+ /* Whitespaces after the = */
+ /* TODO: at this point we need to add quoted around the value */
+ detail = IDE_XML_POSITION_DETAIL_IN_ATTRIBUTE_VALUE;
+ skip_whitespaces (&cursor);
+ if (*cursor == 0)
+ {
+ *name = g_strndup (name_start, name_size);
+ return detail;
+ }
+
+ *quote = *cursor;
+ start = ++cursor;
+ if (*quote != '"' && *quote != '\'')
+ {
+ *quote = 0;
+ if (!g_unichar_isspace(*(cursor -1)))
+ {
+ skip_all_name (&cursor);
+ if (*cursor == 0)
+ return IDE_XML_POSITION_DETAIL_NONE;
+
+ skip_whitespaces (&cursor);
+ if (*cursor == 0)
+ return IDE_XML_POSITION_DETAIL_IN_ATTRIBUTE_NAME;
+ }
+
+ continue;
+ }
+
+ /* Attribute value */
+ if (!ide_xml_utils_skip_attribute_value (&cursor, *quote))
+ {
+ *name = g_strndup (name_start, name_size);
+ *value = g_strndup (start, cursor - start);
+ return detail;
+ }
+
+ detail = IDE_XML_POSITION_DETAIL_IN_ATTRIBUTE_NAME;
+ /* Whitespaces after the attribute value */
+ if (skip_whitespaces (&cursor))
+ has_spaces = TRUE;
+
+ if (*cursor == 0)
+ {
+ *quote = 0;
+ return (has_spaces) ? IDE_XML_POSITION_DETAIL_IN_ATTRIBUTE_NAME : IDE_XML_POSITION_DETAIL_NONE;
+ }
+
+ if (!has_spaces)
+ {
+ skip_all_name (&cursor);
+ if (*cursor == 0)
+ return IDE_XML_POSITION_DETAIL_NONE;
+ }
+ };
+}
+
static IdeXmlPosition *
get_position (IdeXmlService *self,
IdeXmlAnalysis *analysis,
@@ -636,7 +792,8 @@ get_position (IdeXmlService *self,
{
IdeXmlPosition *position;
IdeXmlSymbolNode *root_node;
- IdeXmlSymbolNode *current_node, *child_node, *candidate_node;
+ IdeXmlSymbolNode *current_node, *child_node;
+ IdeXmlSymbolNode *candidate_node = NULL;
IdeXmlSymbolNode *previous_node = NULL;
IdeXmlSymbolNode *previous_sibling_node = NULL;
IdeXmlSymbolNode *next_sibling_node = NULL;
@@ -644,11 +801,15 @@ get_position (IdeXmlService *self,
IdeXmlPositionKind candidate_kind;
IdeXmlPositionDetail detail = IDE_XML_POSITION_DETAIL_NONE;
g_autofree gchar *prefix = NULL;
+ g_autofree gchar *detail_name = NULL;
+ g_autofree gchar *detail_value = NULL;
GtkTextIter start, end;
+ gunichar next_ch = 0;
gint start_line, start_line_offset;
guint n_children;
gint child_pos = -1;
gint n = 0;
+ gchar quote = 0;
gboolean has_prefix = FALSE;
g_assert (IDE_IS_XML_SERVICE (self));
@@ -673,14 +834,12 @@ loop:
case IDE_XML_SYMBOL_NODE_RELATIVE_POSITION_IN_START_TAG:
candidate_node = child_node;
candidate_kind = IDE_XML_POSITION_KIND_IN_START_TAG;
- detail = IDE_XML_POSITION_DETAIL_IN_NAME;
has_prefix = TRUE;
goto result;
case IDE_XML_SYMBOL_NODE_RELATIVE_POSITION_IN_END_TAG:
candidate_node = child_node;
candidate_kind = IDE_XML_POSITION_KIND_IN_END_TAG;
- detail = IDE_XML_POSITION_DETAIL_IN_NAME;
has_prefix = TRUE;
goto result;
@@ -703,7 +862,8 @@ loop:
break;
case IDE_XML_SYMBOL_NODE_RELATIVE_POSITION_IN_CONTENT:
- current_node = previous_node = child_node;
+ candidate_node = current_node = previous_node = child_node;
+ candidate_kind = IDE_XML_POSITION_KIND_IN_CONTENT;
goto loop;
case IDE_XML_POSITION_KIND_UNKNOW:
@@ -720,16 +880,16 @@ result:
candidate_node = root_node;
candidate_kind = IDE_XML_POSITION_KIND_IN_CONTENT;
}
- else if (candidate_kind == IDE_XML_POSITION_KIND_IN_CONTENT &&
- previous_node != NULL &&
- ide_xml_symbol_node_get_state (previous_node) == IDE_XML_SYMBOL_NODE_STATE_NOT_CLOSED)
+ else if (candidate_kind == IDE_XML_POSITION_KIND_IN_CONTENT)
{
- candidate_node = previous_node;
- /* TODO: fetch detail and more infos */
- /* TODO: detect the IN_END_TAG case */
- candidate_kind = IDE_XML_POSITION_KIND_IN_START_TAG;
- detail = IDE_XML_POSITION_DETAIL_IN_NAME;
- has_prefix = TRUE;
+ if (previous_node != NULL &&
+ ide_xml_symbol_node_get_state (previous_node) == IDE_XML_SYMBOL_NODE_STATE_NOT_CLOSED)
+ {
+ candidate_node = previous_node;
+ /* TODO: detect the IN_END_TAG case */
+ candidate_kind = IDE_XML_POSITION_KIND_IN_START_TAG;
+ has_prefix = TRUE;
+ }
}
if (has_prefix)
@@ -741,13 +901,19 @@ result:
if (gtk_text_iter_get_char (&start) == '<')
gtk_text_iter_forward_char (&start);
+ next_ch = gtk_text_iter_get_char (&end);
if (!gtk_text_iter_equal (&start, &end))
- prefix = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ {
+ prefix = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+ detail = get_detail (candidate_node, prefix, next_ch, &detail_name, &detail_value, "e);
+ }
+ else
+ detail = IDE_XML_POSITION_DETAIL_IN_NAME;
}
if (candidate_kind == IDE_XML_POSITION_KIND_IN_CONTENT)
{
- position = ide_xml_position_new (candidate_node, prefix, candidate_kind, detail);
+ position = ide_xml_position_new (candidate_node, prefix, candidate_kind, detail, detail_name,
detail_value, quote);
ide_xml_position_set_analysis (position, analysis);
ide_xml_position_set_child_pos (position, child_pos);
}
@@ -757,7 +923,7 @@ result:
child_node = candidate_node;
candidate_node = ide_xml_symbol_node_get_parent (child_node);
- position = ide_xml_position_new (candidate_node, prefix, candidate_kind, detail);
+ position = ide_xml_position_new (candidate_node, prefix, candidate_kind, detail, detail_name,
detail_value, quote);
ide_xml_position_set_analysis (position, analysis);
ide_xml_position_set_child_node (position, child_node);
}
diff --git a/plugins/xml-pack/ide-xml-utils.c b/plugins/xml-pack/ide-xml-utils.c
new file mode 100644
index 0000000..b76ad6d
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-utils.c
@@ -0,0 +1,208 @@
+/* ide-xml-utils.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-utils.h"
+
+static inline gboolean
+is_name_start_char (gunichar ch)
+{
+ return ((ch >= 'A' && ch <= 'Z') ||
+ (ch >= 'a' && ch <= 'z') ||
+ ch == ':' ||
+ ch == '_' ||
+ (ch >= 0xC0 && ch <= 0xD6) ||
+ (ch >= 0xD8 && ch <= 0xF6) ||
+ (ch >= 0xF8 && ch <= 0x2FF) ||
+ (ch >= 0x370 && ch <= 0x37D) ||
+ (ch >= 0x37F && ch <= 0x1FFF) ||
+ (ch >= 0x200C && ch <= 0x200D) ||
+ (ch >= 0x2070 && ch <= 0x218F) ||
+ (ch >= 0x2C00 && ch <= 0x2FEF) ||
+ (ch >= 0x3001 && ch <= 0xD7FF) ||
+ (ch >= 0xF900 && ch <= 0xFDCF) ||
+ (ch >= 0xFDF0 && ch <= 0xFFFD) ||
+ (ch >= 0x10000 && ch <= 0xEFFFF));
+}
+
+static inline gboolean
+is_name_char (gunichar ch)
+{
+ return (is_name_start_char (ch) ||
+ ch == '-' ||
+ ch == '.' ||
+ (ch >= '0' && ch <= '9') ||
+ ch == 0xB7 ||
+ (ch >= 0x300 && ch <= 0x36F) ||
+ (ch >= 0x203F && ch <= 0x2040));
+}
+
+/* Return TRUE if we found spaces */
+static inline gboolean
+skip_whitespaces (const gchar **cursor)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+
+ g_assert (cursor != NULL && *cursor != NULL);
+
+ while ((ch = g_utf8_get_char (*cursor)) && g_unichar_isspace (ch))
+ *cursor = g_utf8_next_char (*cursor);
+
+ return (p != *cursor);
+}
+
+static void
+jump_to_next_attribute (const gchar **cursor)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+ gchar term;
+ gboolean has_spaces = FALSE;
+
+ while ((ch = g_utf8_get_char (p)))
+ {
+ if (g_unichar_isspace (ch))
+ {
+ skip_whitespaces (&p);
+ break;
+ }
+
+ if (ch == '=')
+ break;
+
+ p = g_utf8_next_char (p);
+ }
+
+ if (ch != '=')
+ {
+ *cursor = p;
+ return;
+ }
+
+ p++;
+ if (skip_whitespaces (&p))
+ has_spaces = TRUE;
+
+ if (ch == '"' || ch == '\'')
+ {
+ term = ch;
+ while ((ch = g_utf8_get_char (p)) && ch != term)
+ p = g_utf8_next_char (p);
+
+ if (ch == term)
+ {
+ p++;
+ skip_whitespaces (&p);
+ }
+ }
+ else if (!has_spaces)
+ {
+ while ((ch = g_utf8_get_char (p)) && !g_unichar_isspace (ch))
+ p = g_utf8_next_char (p);
+ }
+
+ *cursor = p;
+}
+
+/* Return FALSE if not valid */
+gboolean
+ide_xml_utils_skip_element_name (const gchar **cursor)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+
+ g_return_val_if_fail (cursor != NULL, FALSE);
+
+ if (!(ch = g_utf8_get_char (p)))
+ return TRUE;
+
+ if (!is_name_start_char (ch))
+ return (g_unichar_isspace (ch));
+
+ p = g_utf8_next_char (p);
+ while ((ch = g_utf8_get_char (p)))
+ {
+ if (!is_name_char (ch))
+ {
+ *cursor = p;
+ return g_unichar_isspace (ch);
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ *cursor = p;
+ return TRUE;
+}
+
+/* Return FALSE at the end of the string */
+gboolean
+ide_xml_utils_skip_attribute_value (const gchar **cursor,
+ gchar term)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+
+ g_return_val_if_fail (cursor != NULL && *cursor != NULL, FALSE);
+
+ while ((ch = g_utf8_get_char (p)) && ch != term)
+ p = g_utf8_next_char (p);
+
+ if (ch == term)
+ p++;
+
+ *cursor = p;
+ return (ch != 0);
+}
+
+/* Return FALSE if not valid */
+gboolean
+ide_xml_utils_skip_attribute_name (const gchar **cursor)
+{
+ const gchar *p = *cursor;
+ gunichar ch;
+
+ g_return_val_if_fail (cursor != NULL, FALSE);
+
+ if (!(ch = g_utf8_get_char (p)))
+ return TRUE;
+
+ if (!is_name_start_char (ch))
+ return (g_unichar_isspace (ch));
+
+ p = g_utf8_next_char (p);
+ while ((ch = g_utf8_get_char (p)))
+ {
+ if (!is_name_char (ch))
+ {
+ *cursor = p;
+ if (g_unichar_isspace (ch) || ch == '=')
+ return TRUE;
+ else
+ {
+ jump_to_next_attribute (cursor);
+ return FALSE;
+ }
+ }
+
+ p = g_utf8_next_char (p);
+ }
+
+ *cursor = p;
+ return TRUE;
+}
diff --git a/plugins/xml-pack/ide-xml-utils.h b/plugins/xml-pack/ide-xml-utils.h
new file mode 100644
index 0000000..c027c83
--- /dev/null
+++ b/plugins/xml-pack/ide-xml-utils.h
@@ -0,0 +1,33 @@
+/* ide-xml-utils.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_UTILS_H
+#define IDE_XML_UTILS_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+gboolean ide_xml_utils_skip_attribute_name (const gchar **cursor);
+gboolean ide_xml_utils_skip_attribute_value (const gchar **cursor,
+ gchar term);
+gboolean ide_xml_utils_skip_element_name (const gchar **cursor);
+
+G_END_DECLS
+
+#endif /* IDE_XML_UTILS_H */
diff --git a/plugins/xml-pack/meson.build b/plugins/xml-pack/meson.build
index 7e6bf7c..eaf8cdc 100644
--- a/plugins/xml-pack/meson.build
+++ b/plugins/xml-pack/meson.build
@@ -49,6 +49,8 @@ xml_pack_sources = [
'ide-xml-tree-builder.h',
'ide-xml-tree-builder-utils.c',
'ide-xml-tree-builder-utils-private.h',
+ 'ide-xml-utils.c',
+ 'ide-xml-utils.c',
'ide-xml-validator.c',
'ide-xml-validator.h',
'ide-xml.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]