X-Git-Url: https://git.saurik.com/wxWidgets.git/blobdiff_plain/3fee01e962eba38f03914b2f2b9175b230275b01..4e735ed6a6973429c5964c30825862a10949619c:/docs/doxygen/scripts/doxymlparser.py?ds=sidebyside diff --git a/docs/doxygen/scripts/doxymlparser.py b/docs/doxygen/scripts/doxymlparser.py new file mode 100755 index 0000000000..414cf988d2 --- /dev/null +++ b/docs/doxygen/scripts/doxymlparser.py @@ -0,0 +1,233 @@ +""" +Name: doxymlparser.py +Author: Kevin Ollivier +License: wxWidgets License +""" + +__description__ = """ +Takes the output of Doxygen XML and parses it to retrieve metadata about the classes and methods. + +To create the Doxygen XML files, from the wxWidgets/docs/doxygen directory, do: + +./regen.sh xml + +To see the results from parsing a particular class, do: + +python doxymlparser.py --report out/xml/classwx_.xml +""" + +#!/usr/bin/env python +import optparse +import os +import string + +import sys +import types +from xml.dom import minidom + +option_dict = { + "report" : (False, "Print out the classes and methods found by this script."), + "verbose" : (False, "Provide status updates and other information."), + } + +parser = optparse.OptionParser(usage="usage: %prog [options] \n" + __description__, version="%prog 1.0") + +for opt in option_dict: + default = option_dict[opt][0] + + action = "store" + if type(default) == types.BooleanType: + action = "store_true" + parser.add_option("--" + opt, default=default, action=action, dest=opt, help=option_dict[opt][1]) + +options, arguments = parser.parse_args() + +def get_first_value(alist): + if len(alist) > 0: + return alist[0] + else: + return "" + +class ClassDefinition: + def __init__(self): + self.name = "" + self.constructors = [] + self.destructors = [] + self.methods = [] + self.brief_description = "" + self.detailed_description = "" + self.includes = [] + self.bases = [] + self.enums = {} + + def __str__(self): + str_repr = """ +Class: %s +Bases: %s +Includes: %s +Brief Description: +%s + +Detailed Description: +%s +""" % (self.name, string.join(self.bases, ", "), self.includes, self.brief_description, self.detailed_description) + str_repr += "Methods:\n" + + for method in self.methods: + str_repr += str(method) + + return str_repr + +class MethodDefinition: + def __init__(self): + self.name = "" + self.return_type = "" + self.argsstring = "" + self.definition = "" + self.params = [] + self.brief_description = "" + self.detailed_description = "" + + def __str__(self): + str_repr = """ +Method: %s +Return Type: %s +Params: %r +Prototype: %s +Brief Description: +%s + +Detailed Description: +%s +""" % (self.name, self.return_type, self.params, self.definition + self.argsstring, self.brief_description, self.detailed_description) + return str_repr + +def getTextValue(node, recursive=False): + text = "" + for child in node.childNodes: + if child.nodeType == child.ELEMENT_NODE and child.nodeName == "ref": + text += getTextValue(child) + if child.nodeType == child.TEXT_NODE: + # Add a space to ensure we have a space between qualifiers and parameter names + text += child.nodeValue.strip() + " " + + return text.strip() + +def doxyMLToText(node): + return text + +class DoxyMLParser: + def __init__(self): + self.classes = [] + + def find_class(self, name): + for aclass in self.classes: + if aclass.name == name: + return aclass + + return None + + def get_enums_and_functions(self, filename, aclass): + file_path = os.path.dirname(filename) + enum_filename = os.path.join(file_path, aclass.name[2:] + "_8h.xml") + if os.path.exists(enum_filename): + root = minidom.parse(enum_filename).documentElement + for method in root.getElementsByTagName("memberdef"): + if method.getAttribute("kind") == "enum": + self.parse_enum(aclass, method, root) + + def is_derived_from_base(self, aclass, abase): + base = get_first_value(aclass.bases) + while base and base != "": + + if base == abase: + return True + + parentclass = self.find_class(base) + + if parentclass: + base = get_first_value(parentclass.bases) + else: + base = None + + return False + + def parse(self, filename): + self.xmldoc = minidom.parse(filename).documentElement + for node in self.xmldoc.getElementsByTagName("compounddef"): + new_class = self.parse_class(node) + self.classes.append(new_class) + self.get_enums_and_functions(filename, new_class) + + def parse_class(self, class_node): + new_class = ClassDefinition() + new_class.name = getTextValue(class_node.getElementsByTagName("compoundname")[0]) + for node in class_node.childNodes: + if node.nodeName == "basecompoundref": + new_class.bases.append(getTextValue(node)) + elif node.nodeName == "briefdescription": + # let the post-processor determ + new_class.brief_description = node.toxml() + elif node.nodeName == "detaileddescription": + new_class.detailed_description = node.toxml() + elif node.nodeName == "includes": + new_class.includes.append(getTextValue(node)) + + self.parse_methods(new_class, class_node) + + return new_class + + def parse_enum(self, new_class, enum, root): + enum_name = "" + enum_values = [] + + for node in enum.childNodes: + if node.nodeName == "name": + enum_name = getTextValue(node) + elif node.nodeName == "enumvalue": + enum_values.append(getTextValue(node.getElementsByTagName("name")[0])) + + new_class.enums[enum_name] = enum_values + + def parse_methods(self, new_class, root): + for method in root.getElementsByTagName("memberdef"): + new_method = MethodDefinition() + for node in method.childNodes: + if node.nodeName == "name": + new_method.name = getTextValue(node) + elif node.nodeName == "type": + new_method.return_type = getTextValue(node) + elif node.nodeName == "definition": + new_method.definition = getTextValue(node) + elif node.nodeName == "argsstring": + new_method.argsstring = getTextValue(node) + elif node.nodeName == "param": + param = {} + for child in node.childNodes: + if child.nodeType == child.ELEMENT_NODE: + param[child.nodeName] = getTextValue(child) + new_method.params.append(param) + + if options.verbose: + print "Adding %s" % (new_method.name + new_method.argsstring) + + if new_method.name == new_class.name: + new_class.constructors.append(new_method) + elif new_method.name == "~" + new_class.name: + new_class.destructors.append(new_method) + else: + new_class.methods.append(new_method) + +if __name__ == "__main__": + if len(arguments) < 1: + parser.print_usage() + sys.exit(1) + + doxyparse = DoxyMLParser() + for arg in arguments: + doxyparse.parse(arg) + + if options.report: + for aclass in doxyparse.classes: + print str(aclass) +