commit 30ada760e7fa6f819e6027d62b6eddf7db0c716c
Author: Colin Walters <walters@verbum.org>
Date:   Wed Oct 15 18:26:12 2008 -0400

    Move class structs under associated class

diff --git a/girepository/girparser.c b/girepository/girparser.c
index 8e47ec9..766b7ea 100644
--- a/girepository/girparser.c
+++ b/girepository/girparser.c
@@ -43,9 +43,11 @@ typedef enum
   STATE_CLASS,  
   STATE_CLASS_FIELD,
   STATE_CLASS_PROPERTY,
+  STATE_CLASS_STRUCT,
   STATE_INTERFACE,
   STATE_INTERFACE_PROPERTY,   /* 15 */
   STATE_INTERFACE_FIELD,
+  STATE_INTERFACE_STRUCT,
   STATE_IMPLEMENTS, 
   STATE_REQUIRES,
   STATE_BOXED,  
@@ -556,6 +558,9 @@ start_function (GMarkupParseContext *context,
 	       strcmp (element_name, "method") == 0 ||
 	       strcmp (element_name, "callback") == 0);
       break;
+    case STATE_CLASS_STRUCT:
+    case STATE_INTERFACE_STRUCT:
+      return TRUE;
     default:
       break;
     }
@@ -704,6 +709,10 @@ start_parameter (GMarkupParseContext *context,
   const gchar *nullok;
   const gchar *transfer;
   GIrNodeParam *param;
+
+  if (ctx->state == STATE_CLASS_STRUCT ||
+      ctx->state == STATE_INTERFACE_STRUCT)
+    return TRUE;
       
   if (!(strcmp (element_name, "parameter") == 0 &&
 	ctx->state == STATE_FUNCTION_PARAMETERS))
@@ -825,6 +834,9 @@ start_field (GMarkupParseContext *context,
     case STATE_UNION:
     case STATE_INTERFACE:
       break;
+    case STATE_CLASS_STRUCT:
+    case STATE_INTERFACE_STRUCT:
+      return TRUE;
     default:
       return FALSE;
     }
@@ -1436,6 +1448,10 @@ start_type (GMarkupParseContext *context,
   if (!(is_array || is_varargs || (strcmp (element_name, "type") == 0)))
     return FALSE;
 
+  if (ctx->state == STATE_CLASS_STRUCT ||
+      ctx->state == STATE_INTERFACE_STRUCT)
+    return TRUE;
+
   if (ctx->state == STATE_TYPE) 
     {
       ctx->type_depth++;
@@ -1542,6 +1558,10 @@ end_type_top (ParseContext *ctx)
 {
   GIrNodeType *typenode;
 
+  if (ctx->state == STATE_CLASS_STRUCT ||
+      ctx->state == STATE_INTERFACE_STRUCT)
+    goto out;
+
   if (!ctx->type_parameters)
     goto out;
 
@@ -1608,6 +1628,10 @@ end_type_recurse (ParseContext *ctx)
   GList *types;
   GIrNodeType *parent;
 
+  if (ctx->state == STATE_CLASS_STRUCT ||
+      ctx->state == STATE_INTERFACE_STRUCT)
+    return;
+
   parent = (GIrNodeType *) ((GList*)ctx->type_stack->data)->data;
 
   if (parent->tag == GI_TYPE_TAG_ARRAY ||
@@ -1660,6 +1684,11 @@ start_return_value (GMarkupParseContext *context,
 		    ParseContext       *ctx,
 		    GError             **error)
 {
+
+  if (ctx->state == STATE_CLASS_STRUCT ||
+      ctx->state == STATE_INTERFACE_STRUCT)
+    return TRUE;
+
   if (strcmp (element_name, "return-value") == 0 &&
       ctx->state == STATE_FUNCTION)
     {
@@ -1908,8 +1937,20 @@ start_struct (GMarkupParseContext *context,
 	      ParseContext       *ctx,
 	      GError             **error)
 {
-  if (strcmp (element_name, "record") == 0 && 
-      ctx->state == STATE_NAMESPACE)
+  if (strcmp (element_name, "record") != 0)
+    return FALSE;
+  
+  if (ctx->state == STATE_INTERFACE)
+    {
+      state_switch (ctx, STATE_INTERFACE_STRUCT);
+      return TRUE;
+    }
+  if (ctx->state == STATE_CLASS)
+    {
+      state_switch (ctx, STATE_CLASS_STRUCT);
+      return TRUE;
+    }
+  if (ctx->state == STATE_NAMESPACE)
     {
       const gchar *name;
       const gchar *deprecated;
@@ -2450,9 +2491,23 @@ end_element_handler (GMarkupParseContext *context,
 		     GError             **error)
 {
   ParseContext *ctx = user_data;
+  gboolean is_record = strcmp (element_name, "record") == 0;
 
   g_debug ("</%s>", element_name);
 
+  if (ctx->state == STATE_CLASS_STRUCT)
+    {
+      if (is_record)
+	state_switch (ctx, STATE_CLASS);
+      return;
+    }
+  else if (ctx->state == STATE_INTERFACE_STRUCT)
+    {
+      if (is_record)
+	state_switch (ctx, STATE_INTERFACE);
+      return;
+    }
+
   switch (ctx->state)
     {
     case STATE_START:
diff --git a/giscanner/ast.py b/giscanner/ast.py
index 8ee6f7a..60172ad 100644
--- a/giscanner/ast.py
+++ b/giscanner/ast.py
@@ -310,6 +310,7 @@ class Class(Node):
     def __init__(self, name, parent):
         Node.__init__(self, name)
         self.ctype = name
+        self.class_struct = None
         self.parent = parent
         self.methods = []
         self.interfaces = []
diff --git a/giscanner/girwriter.py b/giscanner/girwriter.py
index 1ccbbef..1cd6a0b 100644
--- a/giscanner/girwriter.py
+++ b/giscanner/girwriter.py
@@ -241,6 +241,8 @@ class GIRWriter(XMLWriter):
                 for iface in node.interfaces:
                     self.write_tag('implements', [('name', iface)])
             if isinstance(node, Class):
+                if node.class_struct:
+                    self._write_record(node.class_struct)
                 for method in node.constructors:
                     self._write_constructor(method)
             for method in node.methods:
diff --git a/giscanner/glibtransformer.py b/giscanner/glibtransformer.py
index 8a360b9..a321284 100644
--- a/giscanner/glibtransformer.py
+++ b/giscanner/glibtransformer.py
@@ -466,15 +466,23 @@ class GLibTransformer(object):
         pair_class = self._get_attribute(resolved)
         if pair_class and isinstance(pair_class,
                                      (GLibObject, GLibInterface)):
-            for field in maybe_class.fields[1:]:
-                pair_class.fields.append(field)
+            pair_class.class_struct = maybe_class
+            self._remove_attribute(maybe_class.name)
+            return
+        # This is a floating class structure with no pair - we just delete
+        # it for now.
+        if self._namespace_name not in ('GLib', 'GObject') and \
+                maybe_class.fields and \
+                maybe_class.fields[0].type.name.endswith('Class'):
+            print "Warning: removing floating class structure %r" \
+                % (maybe_class, )
+            self._remove_attribute(maybe_class.name)
             return
         name = self._transformer.strip_namespace_object(maybe_class.name)
         pair_class = self._get_attribute(name)
         if pair_class and isinstance(pair_class,
                                      (GLibObject, GLibInterface)):
-
-            del self._names.names[maybe_class.name]
+            self._remove_attribute(maybe_class.name)
 
     # Introspection
 
diff --git a/tests/scanner/annotation-1.0-expected.gir b/tests/scanner/annotation-1.0-expected.gir
index fb16ff0..3ca3fae 100644
--- a/tests/scanner/annotation-1.0-expected.gir
+++ b/tests/scanner/annotation-1.0-expected.gir
@@ -12,6 +12,11 @@
            parent="GObject.Object"
            glib:type-name="AnnotationObject"
            glib:get-type="annotation_object_get_type">
+      <record name="ObjectClass" c:type="AnnotationObjectClass">
+        <field name="parent_class">
+          <type name="GObject.Class" c:type="GObjectClass"/>
+        </field>
+      </record>
       <method name="method" c:identifier="annotation_object_method">
         <return-value>
           <type name="int" c:type="gint"/>
@@ -172,10 +177,5 @@
         <type name="GObject.Object" c:type="GObject"/>
       </field>
     </class>
-    <record name="ObjectClass" c:type="AnnotationObjectClass">
-      <field name="parent_class">
-        <type name="GObject.Class" c:type="GObjectClass"/>
-      </field>
-    </record>
   </namespace>
 </repository>
diff --git a/tests/scanner/drawable-1.0-expected.gir b/tests/scanner/drawable-1.0-expected.gir
index 54ba700..63864ea 100644
--- a/tests/scanner/drawable-1.0-expected.gir
+++ b/tests/scanner/drawable-1.0-expected.gir
@@ -12,6 +12,11 @@
            parent="GObject.Object"
            glib:type-name="TestDrawable"
            glib:get-type="test_drawable_get_type">
+      <record name="TestDrawableClass" c:type="TestDrawableClass">
+        <field name="parent_class">
+          <type name="GObject.Class" c:type="GObjectClass"/>
+        </field>
+      </record>
       <method name="do_foo" c:identifier="test_drawable_do_foo">
         <return-value>
           <type name="none" c:type="void"/>
@@ -52,15 +57,5 @@
         <type name="GObject.Object" c:type="GObject"/>
       </field>
     </class>
-    <record name="TestDrawableClass" c:type="TestDrawableClass">
-      <field name="parent_class">
-        <type name="GObject.Class" c:type="GObjectClass"/>
-      </field>
-    </record>
-    <record name="TestPixmapObjectClass" c:type="_TestPixmapObjectClass">
-      <field name="parent_class">
-        <type name="TestDrawableClass" c:type="TestDrawableClass"/>
-      </field>
-    </record>
   </namespace>
 </repository>
diff --git a/tests/scanner/foo-1.0-expected.gir b/tests/scanner/foo-1.0-expected.gir
index 23035fe..d8c75dc 100644
--- a/tests/scanner/foo-1.0-expected.gir
+++ b/tests/scanner/foo-1.0-expected.gir
@@ -14,38 +14,31 @@
                c:type="FooInterface"
                glib:type-name="FooInterface"
                glib:get-type="foo_interface_get_type">
-      <callback name="do_foo" c:type="do_foo">
-        <return-value>
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="self">
-            <type name="Interface" c:type="FooInterface*"/>
-          </parameter>
-        </parameters>
-      </callback>
     </interface>
-    <record name="InterfaceIface" c:type="FooInterfaceIface">
-      <field name="parent_iface">
-        <type name="GObject.TypeInterface" c:type="GTypeInterface"/>
-      </field>
-      <callback name="do_foo" c:type="do_foo">
-        <return-value>
-          <type name="none" c:type="void"/>
-        </return-value>
-        <parameters>
-          <parameter name="self">
-            <type name="Interface" c:type="FooInterface*"/>
-          </parameter>
-        </parameters>
-      </callback>
-    </record>
     <class name="Object"
            c:type="FooObject"
            parent="GObject.Object"
            glib:type-name="FooObject"
            glib:get-type="foo_object_get_type">
       <implements name="Interface"/>
+      <record name="ObjectClass" c:type="FooObjectClass">
+        <field name="parent_class">
+          <type name="GObject.Class" c:type="GObjectClass"/>
+        </field>
+        <callback name="virtual_method" c:type="virtual_method">
+          <return-value>
+            <type name="boolean" c:type="gboolean"/>
+          </return-value>
+          <parameters>
+            <parameter name="object">
+              <type name="Object" c:type="FooObject*"/>
+            </parameter>
+            <parameter name="first_param">
+              <type name="int" c:type="int"/>
+            </parameter>
+          </parameters>
+        </callback>
+      </record>
       <constructor name="new" c:identifier="foo_object_new">
         <return-value>
           <type name="Object" c:type="FooObject*"/>
@@ -129,19 +122,6 @@
       <field name="parent_instance">
         <type name="GObject.Object" c:type="GObject"/>
       </field>
-      <callback name="virtual_method" c:type="virtual_method">
-        <return-value>
-          <type name="boolean" c:type="gboolean"/>
-        </return-value>
-        <parameters>
-          <parameter name="object">
-            <type name="Object" c:type="FooObject*"/>
-          </parameter>
-          <parameter name="first_param">
-            <type name="int" c:type="int"/>
-          </parameter>
-        </parameters>
-      </callback>
       <glib:signal name="signal">
         <return-value transfer-ownership="full">
           <type name="utf8" c:type="gchararray"/>
@@ -156,30 +136,17 @@
         </parameters>
       </glib:signal>
     </class>
-    <record name="ObjectClass" c:type="FooObjectClass">
-      <field name="parent_class">
-        <type name="GObject.Class" c:type="GObjectClass"/>
-      </field>
-      <callback name="virtual_method" c:type="virtual_method">
-        <return-value>
-          <type name="boolean" c:type="gboolean"/>
-        </return-value>
-        <parameters>
-          <parameter name="object">
-            <type name="Object" c:type="FooObject*"/>
-          </parameter>
-          <parameter name="first_param">
-            <type name="int" c:type="int"/>
-          </parameter>
-        </parameters>
-      </callback>
-    </record>
     <class name="Subobject"
            c:type="FooSubobject"
            parent="Object"
            glib:type-name="FooSubobject"
            glib:get-type="foo_subobject_get_type">
       <implements name="Interface"/>
+      <record name="SubobjectClass" c:type="FooSubobjectClass">
+        <field name="parent_class">
+          <type name="ObjectClass" c:type="FooObjectClass"/>
+        </field>
+      </record>
       <constructor name="new" c:identifier="foo_subobject_new">
         <return-value>
           <type name="Subobject" c:type="FooSubobject*"/>
@@ -189,11 +156,6 @@
         <type name="Object" c:type="FooObject"/>
       </field>
     </class>
-    <record name="SubobjectClass" c:type="FooSubobjectClass">
-      <field name="parent_class">
-        <type name="ObjectClass" c:type="FooObjectClass"/>
-      </field>
-    </record>
     <function name="init" c:identifier="foo_init">
       <return-value>
         <type name="int" c:type="gint"/>
