[gtk+] Improve GtkBuilder error reporting



commit 1a312bfa3e32414065a87d7376a9bff8c61f0560
Author: Matthias Clasen <mclasen redhat com>
Date:   Mon Apr 6 20:13:35 2009 -0400

    Improve GtkBuilder error reporting
    
    Make GtkBuilder report an error when it encounters a duplicate id,
    instead of segfaulting later on
---
 docs/reference/gtk/tmpl/gtkbuilder.sgml |    1 +
 gtk/gtkbuilder.h                        |    3 +-
 gtk/gtkbuilderparser.c                  |   36 +++++++++++++++++++++++-------
 gtk/gtkbuilderprivate.h                 |    2 +
 4 files changed, 32 insertions(+), 10 deletions(-)

diff --git a/docs/reference/gtk/tmpl/gtkbuilder.sgml b/docs/reference/gtk/tmpl/gtkbuilder.sgml
index 4353b1d..09ee015 100644
--- a/docs/reference/gtk/tmpl/gtkbuilder.sgml
+++ b/docs/reference/gtk/tmpl/gtkbuilder.sgml
@@ -285,6 +285,7 @@ using #GtkBuilder.
     some attribute value.
 @GTK_BUILDER_ERROR_VERSION_MISMATCH: The input file requires a newer version
     of GTK+.
+ GTK_BUILDER_ERROR_DUPLICATE_ID: An object id occurred twice.
 
 <!-- ##### FUNCTION gtk_builder_new ##### -->
 <para>
diff --git a/gtk/gtkbuilder.h b/gtk/gtkbuilder.h
index 4a11001..0f9224e 100644
--- a/gtk/gtkbuilder.h
+++ b/gtk/gtkbuilder.h
@@ -52,7 +52,8 @@ typedef enum
   GTK_BUILDER_ERROR_INVALID_TAG,
   GTK_BUILDER_ERROR_MISSING_PROPERTY_VALUE,
   GTK_BUILDER_ERROR_INVALID_VALUE,
-  GTK_BUILDER_ERROR_VERSION_MISMATCH
+  GTK_BUILDER_ERROR_VERSION_MISMATCH,
+  GTK_BUILDER_ERROR_DUPLICATE_ID
 } GtkBuilderError;
 
 GQuark gtk_builder_error_quark (void);
diff --git a/gtk/gtkbuilderparser.c b/gtk/gtkbuilderparser.c
index 44b10fa..084c362 100644
--- a/gtk/gtkbuilderparser.c
+++ b/gtk/gtkbuilderparser.c
@@ -298,11 +298,12 @@ is_requested_object (const gchar *object,
 }
 
 static void
-parse_object (ParserData   *data,
-              const gchar  *element_name,
-              const gchar **names,
-              const gchar **values,
-              GError      **error)
+parse_object (GMarkupParseContext  *context,
+              ParserData           *data,
+              const gchar          *element_name,
+              const gchar         **names,
+              const gchar         **values,
+              GError              **error)
 {
   ObjectInfo *object_info;
   ChildInfo* child_info;
@@ -310,6 +311,7 @@ parse_object (ParserData   *data,
   gchar *object_class = NULL;
   gchar *object_id = NULL;
   gchar *constructor = NULL;
+  gint line, line2;
 
   child_info = state_peek_info (data, ChildInfo);
   if (child_info && strcmp (child_info->tag.name, "object") == 0)
@@ -335,10 +337,11 @@ parse_object (ParserData   *data,
           object_class = _get_type_by_symbol (values[i]);
           if (!object_class)
             {
-              g_set_error (error, GTK_BUILDER_ERROR, 
+              g_markup_parse_context_get_position (context, &line, NULL);
+              g_set_error (error, GTK_BUILDER_ERROR,
                            GTK_BUILDER_ERROR_INVALID_TYPE_FUNCTION,
-                           _("Invalid type function: `%s'"),
-                           values[i]);
+                           _("Invalid type function on line %d: '%s'"),
+                           line, values[i]);
               return;
             }
         }
@@ -389,6 +392,19 @@ parse_object (ParserData   *data,
 
   if (child_info)
     object_info->parent = (CommonInfo*)child_info;
+
+  g_markup_parse_context_get_position (context, &line, NULL);
+  line2 = GPOINTER_TO_INT (g_hash_table_lookup (data->object_ids, object_id));
+  if (line2 != 0)
+    {
+      g_set_error (error, GTK_BUILDER_ERROR,
+                   GTK_BUILDER_ERROR_DUPLICATE_ID,
+                           _("Duplicate object id '%s' on line %d (previously on line %d)"),
+                           object_id, line, line2);
+      return;
+    }
+
+  g_hash_table_insert (data->object_ids, object_id, GINT_TO_POINTER (line));
 }
 
 static void
@@ -848,7 +864,7 @@ start_element (GMarkupParseContext *context,
   if (strcmp (element_name, "requires") == 0)
     parse_requires (data, element_name, names, values, error);
   else if (strcmp (element_name, "object") == 0)
-    parse_object (data, element_name, names, values, error);
+    parse_object (context, data, element_name, names, values, error);
   else if (data->requested_objects && !data->inside_requested_object)
     {
       /* If outside a requested object, simply ignore this tag */
@@ -1145,6 +1161,7 @@ _gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
   data->builder = builder;
   data->filename = filename;
   data->domain = g_strdup (domain);
+  data->object_ids = g_hash_table_new (g_str_hash, g_str_equal);
 
   data->requested_objects = NULL;
   if (requested_objs)
@@ -1204,6 +1221,7 @@ _gtk_builder_parser_parse_buffer (GtkBuilder   *builder,
   g_slist_foreach (data->requested_objects, (GFunc) g_free, NULL);
   g_slist_free (data->requested_objects);
   g_free (data->domain);
+  g_hash_table_destroy (data->object_ids);
   g_markup_parse_context_free (data->ctx);
   g_free (data);
 
diff --git a/gtk/gtkbuilderprivate.h b/gtk/gtkbuilderprivate.h
index 8c69630..e633a28 100644
--- a/gtk/gtkbuilderprivate.h
+++ b/gtk/gtkbuilderprivate.h
@@ -101,6 +101,8 @@ typedef struct {
   gboolean inside_requested_object;
   gint requested_object_level;
   gint cur_object_level;
+
+  GHashTable *object_ids;
 } ParserData;
 
 typedef GType (*GTypeGetFunc) (void);



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