]> git.saurik.com Git - wxWidgets.git/blob - docs/doxygen/scripts/doxymlparser.py
Added more conveniently placed 'List of All Members' link on all class doc pages...
[wxWidgets.git] / docs / doxygen / scripts / doxymlparser.py
1 """
2 Name: doxymlparser.py
3 Author: Kevin Ollivier
4 Licence: wxWindows licence
5 """
6
7 __description__ = """
8 Takes the output of Doxygen XML and parses it to retrieve metadata about the classes and methods.
9
10 To create the Doxygen XML files, from the wxWidgets/docs/doxygen directory, do:
11
12 ./regen.sh xml
13
14 To see the results from parsing a particular class, do:
15
16 python doxymlparser.py --report out/xml/classwx_<whatever>.xml
17 """
18
19 #!/usr/bin/env python
20 import optparse
21 import os
22 import string
23
24 import sys
25 import types
26
27 from common import *
28 from xml.dom import minidom
29
30 class ClassDefinition:
31 def __init__(self):
32 self.name = ""
33 self.constructors = []
34 self.destructors = []
35 self.methods = []
36 self.brief_description = ""
37 self.detailed_description = ""
38 self.includes = []
39 self.bases = []
40 self.enums = {}
41
42 def __str__(self):
43 str_repr = """
44 Class: %s
45 Bases: %s
46 Includes: %s
47 Brief Description:
48 %s
49
50 Detailed Description:
51 %s
52 """ % (self.name, string.join(self.bases, ", "), self.includes, self.brief_description, self.detailed_description)
53 str_repr += "Methods:\n"
54
55 for method in self.methods:
56 str_repr += str(method)
57
58 return str_repr
59
60 class MethodDefinition:
61 def __init__(self):
62 self.name = ""
63 self.return_type = ""
64 self.argsstring = ""
65 self.definition = ""
66 self.params = []
67 self.brief_description = ""
68 self.detailed_description = ""
69
70 def __str__(self):
71 str_repr = """
72 Method: %s
73 Return Type: %s
74 Params: %r
75 Prototype: %s
76 Brief Description:
77 %s
78
79 Detailed Description:
80 %s
81 """ % (self.name, self.return_type, self.params, self.definition + self.argsstring, self.brief_description, self.detailed_description)
82 return str_repr
83
84 def getTextValue(node, recursive=False):
85 text = ""
86 for child in node.childNodes:
87 if child.nodeType == child.ELEMENT_NODE and child.nodeName == "ref":
88 text += getTextValue(child)
89 if child.nodeType == child.TEXT_NODE:
90 # Add a space to ensure we have a space between qualifiers and parameter names
91 text += child.nodeValue.strip() + " "
92
93 return text.strip()
94
95 def doxyMLToText(node):
96 return text
97
98 class DoxyMLParser:
99 def __init__(self, verbose = False):
100 self.classes = []
101 self.verbose = verbose
102
103 def find_class(self, name):
104 for aclass in self.classes:
105 if aclass.name == name:
106 return aclass
107
108 return None
109
110 def get_enums_and_functions(self, filename, aclass):
111 file_path = os.path.dirname(filename)
112 enum_filename = os.path.join(file_path, aclass.name[2:] + "_8h.xml")
113 if os.path.exists(enum_filename):
114 root = minidom.parse(enum_filename).documentElement
115 for method in root.getElementsByTagName("memberdef"):
116 if method.getAttribute("kind") == "enum":
117 self.parse_enum(aclass, method, root)
118
119 def is_derived_from_base(self, aclass, abase):
120 base = get_first_value(aclass.bases)
121 while base and base != "":
122
123 if base == abase:
124 return True
125
126 parentclass = self.find_class(base)
127
128 if parentclass:
129 base = get_first_value(parentclass.bases)
130 else:
131 base = None
132
133 return False
134
135 def parse(self, filename):
136 self.xmldoc = minidom.parse(filename).documentElement
137 for node in self.xmldoc.getElementsByTagName("compounddef"):
138 new_class = self.parse_class(node)
139 self.classes.append(new_class)
140 self.get_enums_and_functions(filename, new_class)
141
142 def parse_class(self, class_node):
143 new_class = ClassDefinition()
144 new_class.name = getTextValue(class_node.getElementsByTagName("compoundname")[0])
145 for node in class_node.childNodes:
146 if node.nodeName == "basecompoundref":
147 new_class.bases.append(getTextValue(node))
148 elif node.nodeName == "briefdescription":
149 # let the post-processor determ
150 new_class.brief_description = node.toxml()
151 elif node.nodeName == "detaileddescription":
152 new_class.detailed_description = node.toxml()
153 elif node.nodeName == "includes":
154 new_class.includes.append(getTextValue(node))
155
156 self.parse_methods(new_class, class_node)
157
158 return new_class
159
160 def parse_enum(self, new_class, enum, root):
161 enum_name = ""
162 enum_values = []
163
164 for node in enum.childNodes:
165 if node.nodeName == "name":
166 enum_name = getTextValue(node)
167 elif node.nodeName == "enumvalue":
168 enum_values.append(getTextValue(node.getElementsByTagName("name")[0]))
169
170 new_class.enums[enum_name] = enum_values
171
172 def parse_methods(self, new_class, root):
173 for method in root.getElementsByTagName("memberdef"):
174 new_method = MethodDefinition()
175 for node in method.childNodes:
176 if node.nodeName == "name":
177 new_method.name = getTextValue(node)
178 elif node.nodeName == "type":
179 new_method.return_type = getTextValue(node)
180 elif node.nodeName == "definition":
181 new_method.definition = getTextValue(node)
182 elif node.nodeName == "argsstring":
183 new_method.argsstring = getTextValue(node)
184 elif node.nodeName == "param":
185 param = {}
186 for child in node.childNodes:
187 if child.nodeType == child.ELEMENT_NODE:
188 param[child.nodeName] = getTextValue(child)
189 new_method.params.append(param)
190
191 if self.verbose:
192 print "Adding %s" % (new_method.name + new_method.argsstring)
193
194 if new_method.name == new_class.name:
195 new_class.constructors.append(new_method)
196 elif new_method.name == "~" + new_class.name:
197 new_class.destructors.append(new_method)
198 else:
199 new_class.methods.append(new_method)
200
201 if __name__ == "__main__":
202 option_dict = {
203 "report" : (False, "Print out the classes and methods found by this script."),
204 "verbose" : (False, "Provide status updates and other information."),
205 }
206
207 parser = optparse.OptionParser(usage="usage: %prog [options] <doxyml files to parse>\n" + __description__, version="%prog 1.0")
208
209 for opt in option_dict:
210 default = option_dict[opt][0]
211
212 action = "store"
213 if type(default) == types.BooleanType:
214 action = "store_true"
215 parser.add_option("--" + opt, default=default, action=action, dest=opt, help=option_dict[opt][1])
216
217 options, arguments = parser.parse_args()
218
219 if len(arguments) < 1:
220 parser.print_usage()
221 sys.exit(1)
222
223 doxyparse = DoxyMLParser(verbose = options.verbose)
224 for arg in arguments:
225 doxyparse.parse(arg)
226
227 if options.report:
228 for aclass in doxyparse.classes:
229 print str(aclass)
230