r3923 - trunk/doxer



Author: timj
Date: 2006-10-01 07:34:30 -0400 (Sun, 01 Oct 2006)
New Revision: 3923

Modified:
   trunk/doxer/ChangeLog
   trunk/doxer/Code2Doxi.py
   trunk/doxer/Data.py
   trunk/doxer/HtmlGenerator.py
   trunk/doxer/qdoxygen.py
   trunk/doxer/qxmlparser.py
Log:
Sun Oct  1 13:09:24 2006  Tim Janik  <timj gtk org>

        * Data.py: extended Parameter for default values and const-ness.
        extended Function for various qualifier bits. extended Struct to
        contain methods and a list of derived types.

        * Code2Doxi.py: write methods out with structures.
        
        * HtmlGenerator.py: fixed parameter/flush_parameters to work at any
        nested level within a section. fixed endless recursion bug in case
        elements nested in parameter descriptions call flush_parameters.

        * qxmlparser.py: for compounds, search for descriptions in the children
        of a node, not the whole subtree of a node, so we don't attribute the
        description of a child element to a prent element. test variables for
        const-ness. parse methods as part of structures. parse class methods.
        parse default values for function arguments.
        parse doxygen namespaces, this seems to lack namespace application to
        symbols defined within the namespace though.

        * qdoxygen.py: do not delete doxyfile in debugging mode.




Modified: trunk/doxer/ChangeLog
===================================================================
--- trunk/doxer/ChangeLog	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/ChangeLog	2006-10-01 11:34:30 UTC (rev 3923)
@@ -1,3 +1,25 @@
+Sun Oct  1 13:09:24 2006  Tim Janik  <timj gtk org>
+
+	* Data.py: extended Parameter for default values and const-ness.
+	extended Function for various qualifier bits. extended Struct to
+	contain methods and a list of derived types.
+
+	* Code2Doxi.py: write methods out with structures.
+	
+	* HtmlGenerator.py: fixed parameter/flush_parameters to work at any
+	nested level within a section. fixed endless recursion bug in case
+	elements nested in parameter descriptions call flush_parameters.
+
+	* qxmlparser.py: for compounds, search for descriptions in the children
+	of a node, not the whole subtree of a node, so we don't attribute the
+	description of a child element to a prent element. test variables for
+	const-ness. parse methods as part of structures. parse class methods.
+	parse default values for function arguments.
+	parse doxygen namespaces, this seems to lack namespace application to
+	symbols defined within the namespace though.
+
+	* qdoxygen.py: do not delete doxyfile in debugging mode.
+
 Sat Apr 22 17:09:50 2006  Tim Janik  <timj gtk org>
 
 	* qdoxygen.py: avoid configuring USE_HTAGS which only doxygen 1.4.4 has.

Modified: trunk/doxer/Code2Doxi.py
===================================================================
--- trunk/doxer/Code2Doxi.py	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/Code2Doxi.py	2006-10-01 11:34:30 UTC (rev 3923)
@@ -206,10 +206,14 @@
         print >>fout, d.doc[0] + '\n'
     if not need_title:
       print >>fout, '@doxer_flush_parameters{}'
+    return not need_title # whether parameters were generated
   def write_structure_synopsis (self, struct, fout):
     struct_anchor = self.construct_object_anchor (struct)
     print >>fout, '@doxer_row'
-    print >>fout, '@doxer_cell{top} ' + self.markup_type ('struct') + self.mspace (1)           # return type column
+    struct_prefix = 'struct'
+    if struct.isclass():
+      struct_prefix = 'class'
+    print >>fout, '@doxer_cell{top} ' + self.markup_type (struct_prefix) + self.mspace (1)      # return type column
     marked_structure = self.markup_structure (struct.name, struct_anchor)                       
     print >>fout, '@doxer_cell{top} ' + marked_structure + ';'                                  # structure name
     print >>fout, '@doxer_done'
@@ -221,17 +225,27 @@
     print >>fout, '@doxer_row'
     print >>fout, '@doxer_cell '
     # print preformatted prototype
-    print >>fout, '@doxer_preformatted{' + self.markup_type ('struct') + " " + self.markup_structure (struct.name, struct_anchor)
-    print >>fout, "{"
+    struct_prefix = 'struct'
+    if struct.isclass():
+      struct_prefix = 'class'
+    print >>fout, '@doxer_preformatted{' + self.markup_type (struct_prefix) + " " + self.markup_structure (struct.name, struct_anchor)
+    print >>fout, "@{"
     name_type_argstring_anchor_list = [(field.name, field.type, field.argstring, self.construct_object_anchor (struct, field)) for field in struct.members]
     variable_blurb = self.write_variable_list ('  ', name_type_argstring_anchor_list, True)
     if variable_blurb:
       fout.write (variable_blurb)
-    print >>fout, '};}' # closes @doxer_preformatted{}
+    if struct.methods:
+      print >>fout, '}'                         # close @doxer_preformatted{}
+      print >>fout, "@doxer_table{noframe}"
+      for func in struct.methods:
+        self.write_function_synopsis (func, fout, struct)
+      print >>fout, "@doxer_done"
+      print >>fout, '@doxer_preformatted{'      # reopen @doxer_preformatted{}
+    print >>fout, '@};}' # closes @doxer_preformatted{}
     # close prototype scopes
-    print >>fout, '@doxer_done'
-    print >>fout, '@doxer_done'
-    print >>fout, '@doxer_done'
+    print >>fout, '@doxer_done' # close row
+    print >>fout, '@doxer_done' # close table
+    print >>fout, '@doxer_done' # close div
     print >>fout, '@dnl'
     # print docu
     if len (struct.doc) >= 3:
@@ -239,11 +253,23 @@
       print >>fout, struct.doc[0]
     # print arg docu
     self.print_documentables ('', struct.members, fout)
+    # finish parameter description
+    print >>fout, '@doxer_flush_parameters{}'
+    # write method descriptions
+    if struct.methods:
+      print >>fout, '@*'
+      print >>fout, '@doxer_table{noframe}'
+      print >>fout, '@doxer_row'
+      print >>fout, '@doxer_cell @doxer_monospace{    }'
+      print >>fout, '@doxer_cell '
+      for func in struct.methods:
+        print >>fout, '@*'
+        self.write_function_description (func, fout, struct, indent = '')
+      print >>fout, "@doxer_done"
+      print >>fout, "@doxer_done"
     # finish structure description
-    # print >>fout, '\n\n'
-    print >>fout, '@doxer_flush_parameters{}'
     print >>fout, '@doxer_hseparator{}'
-  def write_function_proto (self, func, with_anchor, fout, anchor_parent = None, prefix = ''):
+  def write_function_proto (self, func, with_anchor, fout, anchor_parent = None, prefix = '', indent = '@doxer_monospace{  }'):
     ## self.write_function_proto (func, True, fout, obj, '::')
     if anchor_parent:
       func_anchor = self.construct_object_anchor (anchor_parent, func)
@@ -252,7 +278,7 @@
     # open row
     print >>fout, '@doxer_row'
     # return type
-    rindent = anchor_parent and self.mspace (2) or ''
+    rindent = anchor_parent and indent or ''
     print >>fout, '@doxer_cell{top} ' + rindent + self.markup_type (func.ret_arg.type) + self.mspace (1)
     # function name
     with_anchor = with_anchor and '@doxer_anchor{' + func_anchor + '}' or ''
@@ -275,7 +301,7 @@
     else:
       func_anchor = self.construct_object_anchor (func)
     print >>fout, '@doxer_row'
-    rindent = anchor_parent and '@doxer_monospace{  }' or ''
+    rindent = anchor_parent and self.mspace (2) or ''
     msp = self.mspace (1)
     print >>fout, '@doxer_cell{top} ' + rindent + self.markup_type (func.ret_arg.type) + msp    # return type
     with_anchor = with_anchor and '@doxer_anchor{' + func_anchor + '}' or ''
@@ -299,9 +325,13 @@
     print >>fout, '@doxer_done'
   def write_function_synopsis (self, func, fout, anchor_parent = None, prefix = ''):
     return self.write_function_proto_short (func, False, fout, anchor_parent, prefix)
-  def write_function_description (self, func, fout):
-    func_anchor = self.construct_object_anchor (func)
-    self.start_description_section (func.name, func.hint, func_anchor, func.location(), func.doc, fout)
+  def write_function_description (self, func, fout, anchor_parent = None, indent = '@doxer_monospace{  }'):
+    if anchor_parent:
+      func_anchor = self.construct_object_anchor (anchor_parent, func)
+    else:
+      func_anchor = self.construct_object_anchor (func)
+    if not anchor_parent:
+      self.start_description_section (func.name, func.hint, func_anchor, func.location(), func.doc, fout)
     print >>fout, '@doxer_div{doxer-style-prototype}'
     print >>fout, '@doxer_table{noframe}'
     # function prototype
@@ -324,21 +354,21 @@
       print >>fout, '@doxer_done'
     else:
       # self.write_function_proto_short (func, True, fout, obj, '::')
-      self.write_function_proto (func, True, fout)
+      self.write_function_proto (func, True, fout, anchor_parent, '', indent)
     # close prototype scopes
-    print >>fout, '@doxer_done'
-    print >>fout, '@doxer_done'
+    print >>fout, '@doxer_done' # close table
+    print >>fout, '@doxer_done' # close div
     print >>fout, '@dnl'
     # print docu
     if len (func.doc) >= 3:
       print >>fout, '@doxer_line %u "%s"' % (int (func.doc[2]), func.doc[1])
       print >>fout, func.doc[0]
     # print arg docu
-    self.print_documentables ('', func.args, fout)
+    has_args = self.print_documentables ('', func.args, fout)
     # finish function description
-    # print >>fout, '\n\n'
     print >>fout, '@doxer_flush_parameters{}'
-    print >>fout, '@doxer_hseparator{}'
+    if not anchor_parent or has_args or (func.doc and func.doc[0]):
+      print >>fout, '@doxer_hseparator{}'
   def write_channel_proto (self, channel, with_anchor, fout, anchor_parent = None, prefix = ''):
     if anchor_parent:
       channel_anchor = self.construct_object_anchor (anchor_parent, channel)
@@ -388,7 +418,7 @@
     quick_return = not (channels or properties or signals)
     # object header
     print >>fout, '@doxer_row'
-    print >>fout, '@doxer_cell{top} ' + self.markup_type ('class') + self.mspace (1)            # return type column
+    print >>fout, '@doxer_cell{top} ' + self.markup_type ('object') + self.mspace (1)           # return type column
     marked_object = self.markup_structure (obj.name, obj_anchor)
     if quick_return:
       print >>fout, '@doxer_cell{top} ' + marked_object + ';'                                   # object name
@@ -425,7 +455,7 @@
     # object header
     print >>fout, '@doxer_row'
     with_anchor = with_anchor and '@doxer_anchor{' + obj_anchor + '}' or ''
-    class_proto = self.markup_type ('class') + space1 + with_anchor
+    class_proto = self.markup_type ('object') + space1 + with_anchor
     class_proto += self.markup_structure (obj.name, obj_anchor)
     print >>fout, '@doxer_cell{colspan=3} ' + class_proto                                       # object name
     print >>fout, '@doxer_done'

Modified: trunk/doxer/Data.py
===================================================================
--- trunk/doxer/Data.py	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/Data.py	2006-10-01 11:34:30 UTC (rev 3923)
@@ -103,13 +103,17 @@
 class Parameter (Documentable):
   init = None
   argstring = ''
+  default = ''
   label = ''
   group = ''
+  isconst = False
   def __init__ (self, name, type = None):
     self.name = name
     self.type = type
   def set_type (self, type):
     self.type = type
+  def set_const (self, arg):
+    self.isconst = bool (arg)
   def set_label (self, label):
     self.label = label
   def set_init (self, initializer):
@@ -118,6 +122,8 @@
     self.argstring = astring
   def set_group (self, group):
     self.group = group
+  def set_default (self, default):
+    self.default = default
 
 class SrcFile (Documentable):
   preserve_extension = True
@@ -174,8 +180,16 @@
   args = ()
   doc_args = ()
   has_ellipsis = False
+  isstatic = False
+  isvirtual = False
+  isinline = False
+  isexplicit = False
+  isconst = False
   def __init__ (self, name):
     self.name = name
+  def set_flags (self, isstatic, isvirtual, isinline, isexplicit, isconst):
+    self.isstatic, self.isvirtual, self.isinline, self.isexplicit, self.isconst = (
+      bool (isstatic), bool (isvirtual), bool (isinline), bool (isexplicit), bool (isconst))
   def add_arg (self, param):
     self.args = list (self.args) + [ param ]
   def add_arg_docu (self, name, text):
@@ -190,10 +204,18 @@
 
 class Struct (Documentable):
   members = ()
+  methods = ()
+  derived = ()
   def __init__ (self, name):
     self.name = name
   def add_member (self, param):
     self.members = list (self.members) + [ param ]
+  def add_method (self, func):
+    self.methods = list (self.methods) + [ func ]
+  def add_derived (self, cls):
+    self.derived = list (self.derived) + [ cls ]
+  def isclass (self):
+    return self.methods != ()
 
 class Channel (Documentable):
   id = 0

Modified: trunk/doxer/HtmlGenerator.py
===================================================================
--- trunk/doxer/HtmlGenerator.py	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/HtmlGenerator.py	2006-10-01 11:34:30 UTC (rev 3923)
@@ -648,8 +648,9 @@
       self.hstream.pop ('dl')
   def doxer_flush_parameters (self, data, transformer, node, environment):
     if not node.flags & Data.SECTIONED:
-      if self.call_stack[-2].flags & Data.SECTIONED:
-        node = self.call_stack[-2]
+      for n in self.call_stack:
+        if n.flags & Data.SECTIONED:
+          node = n # find the last sectioned node
     if not node.flags & Data.SECTIONED or not node.__dict__.has_key ('parameters'):
       return
     self.hstream.push_many (('table', 'tr', 'td'))      # this outer table is needed to avoid horizontal table expansion
@@ -657,7 +658,9 @@
     self.hstream.push ('div', 'class="doxer-style-parameters"')
     self.hstream.push ('table')
     self.hstream.put ('\n')
-    for param in node.parameters:
+    parameter_list = node.parameters
+    del node.parameters
+    for param in parameter_list:
       self.hstream.push ('tr')
       self.hstream.push ('td', 'valign="top"')
       transformer (param, environment, NODE_TITLE)
@@ -674,10 +677,16 @@
     self.hstream.pop ('table')
     self.hstream.pop ('div')
     self.hstream.pop_many (('td', 'tr', 'table'))
-    del node.parameters
   def doxer_parameter (self, data, transformer, node, environment):
-    if self.call_stack[-2].flags & Data.SECTIONED:
-      parent = self.call_stack[-2]
+    if len (self.call_stack) < 2:
+      self.doxer_definition (data, transformer, node, environment)
+      return
+    parent = self.call_stack[-2]
+    if not parent.flags & Data.SECTIONED:
+      for n in self.call_stack:
+        if n.flags & Data.SECTIONED:
+          parent = n # find the last sectioned node
+    if parent.flags & Data.SECTIONED:
       if not parent.__dict__.has_key ('parameters'):
         parent.parameters = []
       parent.parameters += [ node ]

Modified: trunk/doxer/qdoxygen.py
===================================================================
--- trunk/doxer/qdoxygen.py	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/qdoxygen.py	2006-10-01 11:34:30 UTC (rev 3923)
@@ -108,7 +108,8 @@
   del os.environ['DOXER_QCOMMENT_DUMP']
   del os.environ['DOXER_QCOMMENT_CONFIG']
   try:
-    os.remove (tdoxyfile)
+    if not Config.debug:
+      os.remove (tdoxyfile)
   except: pass
   debug ('Asserting result location:', xmlresult)
   assert os.stat (xmlresult)

Modified: trunk/doxer/qxmlparser.py
===================================================================
--- trunk/doxer/qxmlparser.py	2006-10-01 11:32:19 UTC (rev 3922)
+++ trunk/doxer/qxmlparser.py	2006-10-01 11:34:30 UTC (rev 3923)
@@ -88,7 +88,7 @@
     if self.node:
       value = self.node
       self.iter = node_descendants_subtree (self.node)
-      self.node = None
+      self.node = None  # this works for siblings of node, because self.iter is libxml2 depth-first iterator
       return value
     if not self.iter:
       raise StopIteration()
@@ -194,16 +194,24 @@
     fin.close()
     self.comment_dict.update (dict)
   # --- parse descriptions ---
-  def description_parse_and_set (self, xdef, obj, desc_tags = [ "briefdescription", "description", "detaileddescription", "inbodydescription" ], skip_tags = []):
+  def description_parse_and_set (self, xdef, obj, search_subtree = False, desc_tags = [ 'detaileddescription', 'description', 'briefdescription', 'inbodydescription' ], skip_tags = []):
     node_map = dict ( [(dtag, None) for dtag in desc_tags] )
     desc_set = set (desc_tags)
-    # collect all desc_tags in xdef ancestry
-    for dnode in node_subtree (xdef):
-      if dnode.name in desc_set:
-        node_map[dnode.name] = dnode
-        desc_set.remove (dnode.name)
-        if not desc_set:
-          break
+    # collect all desc_tags in xdef subtree
+    if search_subtree:
+      for dnode in node_subtree (xdef):
+        if dnode.name in desc_set:
+          node_map[dnode.name] = dnode
+          desc_set.remove (dnode.name)
+          if not desc_set:
+            break
+    else:
+      for dnode in node_children (xdef):
+        if dnode.name in desc_set:
+          node_map[dnode.name] = dnode
+          desc_set.remove (dnode.name)
+          if not desc_set:
+            break
     # select first non-empty description in order
     for dtag in desc_tags:
       dd_node = node_map[dtag]
@@ -332,44 +340,46 @@
     self.description_parse_and_set (mdef, dv)
     # parse type
     dv.set_type (canonify_type (mdef.xpathEval ("type")[0].content))
+    dv.set_const (re.search (r'\bconst\b[^*&]*$', dv.type))
     # parse remaining argstring
     argstring = node_find_text (mdef, "argsstring")
     argstring = canonify_type (argstring)
     dv.set_argstring (argstring)
-  # --- struct parser ---
-  def parse_struct (self, cdef, rcontainer):
-    # parse struct name
-    name = node_get_leaf_text (cdef, "compoundname")
-    # create struct
-    ds = Data.Struct (name)
-    self.location_parse_and_set (cdef, ds)
-    rcontainer.add_file_member (ds)
-    # parse description
-    self.description_parse_and_set (cdef, ds)
-    # parse members
-    for mdef in node_descendants_by_name (cdef, "memberdef"):
-      kind = mdef.prop ('kind');
-      if kind == 'variable':
-        self.parse_variable (mdef, ds)
-      else:
-        print "qxmlparser.py: Unhandled: %s:" % kind, node_get_leaf_text (mdef, "name")
-  # --- parse function ---
-  def parse_function (self, cdef, rcontainer):
+  # --- parse functions ---
+  def parse_global_function (self, cdef, rcontainer):
     # parse function name
     name = cdef.xpathEval ("name")[0].content
     # create function
     df = Data.Function (name)
     self.location_parse_and_set (cdef, df)
     rcontainer.add_file_member (df)
+    # standard function stuff
+    self.parse_function_def (df, cdef)
+  def parse_class_method (self, cdef, compound):
+    # parse method name
+    name = cdef.xpathEval ("name")[0].content
+    # create function
+    df = Data.Function (name)
+    self.location_parse_and_set (cdef, df)
+    compound.add_method (df)
+    # standard function stuff
+    self.parse_function_def (df, cdef)
+  def parse_function_def (self, df, cdef):
+    # determine kind
+    df.set_flags (cdef.prop ('static') == 'yes',
+                  cdef.prop ('virt') == 'virtual',
+                  cdef.prop ('inline') == 'yes',
+                  cdef.prop ('explicit') == 'yes',
+                  cdef.prop ('const') == 'yes')
     # parse description
-    self.description_parse_and_set (cdef, df, skip_tags = [ "parameterlist", "simplesect" ])
+    self.description_parse_and_set (cdef, df, search_subtree = True, skip_tags = [ "parameterlist", "simplesect" ])
     # parse return type
     dr = Data.Parameter ('', canonify_type (cdef.xpathEval ("type")[0].content))
     df.set_ret_arg (dr)
     # parse return type description
     for child in node_descendants_by_name (cdef, "simplesect"):
       if child.prop ('kind') == 'return':
-        self.description_parse_and_set (child, dr, [ 'simplesect' ])
+        self.description_parse_and_set (child, dr, search_subtree = True, desc_tags = [ 'simplesect' ])
         break
     # parse arguments
     for a in cdef.xpathEval ("param"):
@@ -385,6 +395,10 @@
       if aname:
         # create argument
         da = Data.Parameter (aname, atype)
+        try:    dval = node_get_leaf_text (a, 'defval')
+        except: dval = ''
+        if dval:
+          da.set_default (dval)
         df.add_arg (da)
     # parse documentation arguments
     plist = node_find (cdef, "parameterlist")
@@ -399,11 +413,36 @@
           da = Data.Parameter (aname)
           print "qxmlparser.py: Debug2: "
           df.add_doc_arg (da)
-          self.description_parse_and_set (pitem, da, [ "parameterdescription" ])
+          self.description_parse_and_set (pitem, da, search_subtree = True, desc_tags = [ "parameterdescription" ])
+  # --- struct parser ---
+  def parse_struct (self, cdef, rcontainer):
+    # parse struct name
+    name = node_get_leaf_text (cdef, "compoundname")
+    # create struct
+    ds = Data.Struct (name)
+    self.location_parse_and_set (cdef, ds)
+    rcontainer.add_file_member (ds)
+    # parse description
+    self.description_parse_and_set (cdef, ds)
+    # parse derived classes list
+    for ddef in node_descendants_by_name (cdef, "derivedcompoundref"):
+      dname = node_find_text (ddef, 'derivedcompoundref')
+      protection = ddef.prop ('prot')
+      isvirtual  = ddef.prop ('virtual')
+      ds.add_derived (dname)
+    # parse methods and variable members
+    for mdef in node_descendants_by_name (cdef, "memberdef"):
+      kind = mdef.prop ('kind');
+      if kind == 'variable':
+        self.parse_variable (mdef, ds)
+      elif kind == 'function':
+        self.parse_class_method (mdef, ds)
+      else:
+        print "qxmlparser.py: Unhandled: %s:" % kind, name + "::" + node_get_leaf_text (mdef, "name")
   # --- parse dirs and files ---
   def parse_dir (self, cdef, dummy):           # parse XML dir (compounddef)
     name = node_get_leaf_text (cdef, "compoundname");
-  def parse_file (self, cdef, dummy):          # parse XML file (compounddef)
+  def parse_file_or_namespace (self, cdef, dummy): # parse XML file/namespace (compounddef)
     name = node_get_leaf_text (cdef, "compoundname");
     file_desc = self.parse_xml_description (cdef)
     if file_desc:
@@ -414,7 +453,7 @@
       { "define"	: self.parse_define,
         "enum"  	: self.parse_enum,
         "typedef"	: self.parse_typedef,
-        "function"      : self.parse_function,
+        "function"      : self.parse_global_function,
         "variable"      : self.parse_export_variable,
       } [kind] (node, self)
   def parse_export_variable (self, mdef, dummy): # parse XML variable (memberdef)
@@ -425,9 +464,11 @@
       kind = cdef.prop ("kind");
       try:
         parser = {
-          "file"        : self.parse_file,
+          "file"        : self.parse_file_or_namespace,
+          "namespace"   : self.parse_file_or_namespace,
           "dir"         : self.parse_dir,
           "struct"      : self.parse_struct,
+          "class"       : self.parse_struct,
         } [kind]
       except:
         def print_compound (node, dummy):




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