[GTK] gtkdoc does not appear in DevHelp
[WebKit-https.git] / Tools / gtk / webkitdom.py
1 #!/usr/bin/env python
2 # Copyright (C) 2013 Igalia S.L.
3 #
4 # This library is free software; you can redistribute it and/or
5 # modify it under the terms of the GNU Lesser General Public
6 # License as published by the Free Software Foundation; either
7 # version 2 of the License, or (at your option) any later version.
8 #
9 # This library is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12 # Lesser General Public License for more details.
13 #
14 # You should have received a copy of the GNU Lesser General Public
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17 # 02110-1301  USA
18
19 import common
20 import errno
21 import os
22 import re
23 import sys
24
25 from ConfigParser import SafeConfigParser
26
27
28 class WebKitDOMDocGenerator(object):
29
30     def __init__(self, symbol_files, file_handle):
31         self._symbol_files = symbol_files
32         self._file_handle = file_handle
33
34     def write_header(self):
35         pass
36
37     def write_section(self, symbol_file):
38         raise NotImplementedError
39
40     def write_footer(self):
41         pass
42
43     def write(self, string):
44         self._file_handle.write(string)
45
46     @staticmethod
47     def is_deprecated_symbol_file(file_path):
48         return 'WebKitDOMDeprecated' in file_path
49
50     def generate(self):
51         self.write_header()
52         for symbol_file in self._symbol_files:
53             if WebKitDOMDocGenerator.is_deprecated_symbol_file(symbol_file):
54                 continue
55             self.write_section(symbol_file)
56         self.write_footer()
57
58
59 class WebKitDOMDocGeneratorSGML(WebKitDOMDocGenerator):
60     def write_header(self):
61         self.write('''<?xml version="1.0"?>
62 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
63                "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
64 <!ENTITY version SYSTEM "version.xml">
65 ]>
66 <book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
67   <bookinfo>
68     <title>WebKitDOMGTK+ Reference Manual</title>
69     <releaseinfo>for WebKitDOMGTK+ &version;</releaseinfo>
70   </bookinfo>
71
72   <chapter>
73     <title>Class Overview</title>
74 ''')
75
76     def write_section(self, symbol_file):
77         basename = os.path.basename(symbol_file)
78         self.write('    <xi:include href="xml/%s"/>\n' % basename.replace(".symbols", ".xml"))
79
80     def write_footer(self):
81         self.write('''  </chapter>
82
83   <index id="index-all">
84     <title>Index</title>
85     <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
86   </index>
87   <index id="api-index-deprecated" role="deprecated">
88     <title>Index of deprecated symbols</title>
89     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
90   </index>
91
92   <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
93 </book>
94 ''')
95
96
97 class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
98     def __init__(self, symbol_files, file_handle):
99         super(WebKitDOMDocGeneratorSections, self).__init__(symbol_files, file_handle)
100
101         self._first_decamelize_re = re.compile('(.)([A-Z][a-z]+)')
102         self._second_decamelize_re = re.compile('([a-z0-9])([A-Z])')
103         self._dom_class_re = re.compile('(^WebKitDOM)(.+)$')
104         self._function_re = re.compile('^.+ (.+)\((.+)\)$')
105         self._constant_re = re.compile('^[A-Z_]+$')
106
107         self.deprecated_symbols = {}
108         for symbol_file in symbol_files:
109             if WebKitDOMDocGenerator.is_deprecated_symbol_file(symbol_file):
110                 self._deprecated_symbols = self._find_deprecated_symbols(symbol_file)
111
112     def _dom_class(self, class_name):
113         return self._dom_class_re.sub(r'\2', class_name)
114
115     def _dom_class_decamelize(self, class_name):
116         s1 = self._first_decamelize_re.sub(r'\1_\2', self._dom_class(class_name))
117         retval = self._second_decamelize_re.sub(r'\1_\2', s1)
118
119         # Fix some exceptions.
120         retval = retval.replace('Web_Kit', 'WebKit')
121         retval = retval.replace('X_Path', 'XPath')
122         retval = retval.replace('HTMLI_Frame', 'HTML_IFrame')
123         retval = retval.replace('HTMLBR', 'HTML_BR')
124         retval = retval.replace('HTMLHR', 'HTML_HR')
125         retval = retval.replace('HTMLLI', 'HTML_LI')
126         retval = retval.replace('HTMLD', 'HTML_D')
127         retval = retval.replace('HTMLO', 'HTML_O')
128         retval = retval.replace('HTMLU', 'HTML_U')
129
130         return retval
131
132     def _find_deprecated_symbols(self, symbol_file):
133         retval = {}
134         f = open(symbol_file, 'r')
135         for line in f.readlines():
136             match = self._function_re.match(line)
137             if not match:
138                 continue
139
140             function = match.group(1)
141             args = match.group(2).split(', ')
142             class_name = args[0].strip('*')
143             retval.setdefault(class_name, []).append(function)
144         f.close()
145
146         return retval
147
148     def _symbol_list(self, symbol_file):
149         retval = []
150         f = open(symbol_file, 'r')
151         for line in f.readlines():
152             match = self._constant_re.match(line)
153             if match:
154                 retval.append(line.strip('\n'))
155                 continue
156
157             match = self._function_re.match(line)
158             if not match or match.group(1).endswith('get_type'):
159                 continue
160             retval.append(match.group(1))
161
162         return retval
163
164     def write_section(self, symbol_file):
165         class_name = os.path.basename(symbol_file).replace(".symbols", "")
166         is_custom = class_name == 'WebKitDOMCustom'
167         is_interface = class_name in ['WebKitDOMEventTarget', 'WebKitDOMNodeFilter', 'WebKitDOMXPathNSResolver']
168         is_object = class_name == 'WebKitDOMObject'
169         self.write('<SECTION>\n')
170         self.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
171         if not is_custom:
172             self.write('%s\n' % class_name)
173         self.write('\n')
174         self.write('\n'.join(self._symbol_list(symbol_file)) + '\n')
175         try:
176             deprecated_functions = self._deprecated_symbols[class_name]
177             self.write('\n'.join(deprecated_functions) + '\n')
178         except KeyError:
179             pass
180         if not is_custom:
181             self.write('\n<SUBSECTION Standard>\n')
182             if is_interface:
183                 self.write('%sIface\n' % class_name)
184             else:
185                 self.write('%sClass\n' % class_name)
186             dom_class = self._dom_class_decamelize(class_name).upper()
187             self.write('WEBKIT_DOM_TYPE_%s\n' % dom_class)
188             self.write('WEBKIT_DOM_%s\n' % dom_class)
189             self.write('WEBKIT_DOM_IS_%s\n' % dom_class)
190             self.write('WEBKIT_DOM_%s_CLASS\n' % dom_class)
191             if is_interface:
192                 self.write('WEBKIT_DOM_%s_GET_IFACE\n' % dom_class)
193             else:
194                 self.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
195                 self.write('WEBKIT_DOM_%s_GET_CLASS\n' % dom_class)
196             self.write('\n<SUBSECTION Private>\n')
197             if is_object:
198                 self.write('%sPrivate\n' % class_name)
199             self.write('webkit_dom_%s_get_type\n' % dom_class.lower())
200         self.write('</SECTION>\n\n')
201
202     def write_footer(self):
203         self.write('<SECTION>\n')
204         self.write('<FILE>webkitdomdefines</FILE>\n<TITLE>WebKitDOMDefines</TITLE>\n')
205         self.write('<SUBSECTION Private>\n')
206         self.write('WEBKIT_API\nWEBKIT_DEPRECATED\nWEBKIT_DEPRECATED_FOR\n')
207         self.write('</SECTION>\n\n')
208
209
210 def write_doc_files(module_name):
211     doc_dir = common.build_path('DerivedSources', 'webkitdom', 'docs')
212
213     try:
214         os.mkdir(doc_dir)
215     except OSError, e:
216         if e.errno != errno.EEXIST or not os.path.isdir(doc_dir):
217             sys.stderr.write("Could not create doc dir at %s: %s\n" % (doc_dir, str(e)))
218             sys.exit(1)
219
220     with open(os.path.join(doc_dir, '%s-sections.txt' % module_name), 'w') as sections_file:
221         generator = WebKitDOMDocGeneratorSections(get_all_webkitdom_symbol_files(), sections_file)
222         generator.generate()
223     with open(os.path.join(doc_dir, 'webkitdomgtk-docs.sgml'), 'w') as sgml_file:
224         generator = WebKitDOMDocGeneratorSGML(get_all_webkitdom_symbol_files(), sgml_file)
225         generator.generate()
226
227
228 def header_name_list_from_gtkdoc_config_file():
229     config_file = common.build_path('gtkdoc-webkitdom.cfg')
230     if not os.path.isfile(config_file):
231         sys.stderr.write("Could not find config file at %s\n" % config_file)
232         return sys.exit(1)
233
234     config = SafeConfigParser()
235     config.read(config_file)
236     module_name = config.sections()[0]
237     return [os.path.basename(f) for f in str(config.get(module_name, 'headers')).replace(';', ' ').split()]
238
239
240 def get_all_webkitdom_symbol_files():
241     static_symbol_files_path = common.top_level_path('Source', 'WebCore', 'bindings', 'gobject')
242     generated_symbol_files_path = common.build_path('DerivedSources', 'webkitdom')
243
244     symbol_files = []
245     for header_name in header_name_list_from_gtkdoc_config_file():
246         # webkitdomdefines.h doesn't have a corresponding symbols file and webkitdom.symbols is a
247         # file containing the expected symbols results.
248         if header_name in ("webkitdom.h", "webkitdomdefines.h"):
249             continue
250
251         symbol_file = header_name.replace(".h", ".symbols")
252         path = os.path.join(static_symbol_files_path, symbol_file)
253         if os.path.exists(path):
254             symbol_files.append(path)
255             continue
256         path = os.path.join(generated_symbol_files_path, symbol_file)
257         if os.path.exists(path):
258             symbol_files.append(path)
259             continue
260
261     return symbol_files