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