[GTK] ShadowRoot API was removed in r164131
[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 os
21 import re
22 import sys
23
24 from ConfigParser import SafeConfigParser
25
26
27 class WebKitDOMDocGenerator(object):
28
29     DELETED_CLASSES = [
30         "WebKitDOMBarInfo",
31         "WebKitDOMHTMLPropertiesCollection",
32         "WebKitDOMMemoryInfo",
33         "WebKitDOMMicroDataItemValue",
34         "WebKitDOMPropertyNodeList",
35         "WebKitDOMShadowRoot"]
36
37     def __init__(self, symbol_files, file_handle):
38         self._symbol_files = symbol_files
39         self._file_handle = file_handle
40
41     def write_header(self):
42         pass
43
44     def write_section(self, symbol_file):
45         raise NotImplementedError
46
47     def write_deleted_classes(self):
48         raise NotImplementedError
49
50     def write_footer(self):
51         pass
52
53     def write(self, string):
54         self._file_handle.write(string)
55
56     @staticmethod
57     def is_deprecated_symbol_file(file_path):
58         return 'WebKitDOMDeprecated' in file_path
59
60     def generate(self):
61         self.write_header()
62         for symbol_file in self._symbol_files:
63             if WebKitDOMDocGenerator.is_deprecated_symbol_file(symbol_file):
64                 continue
65             self.write_section(symbol_file)
66         self.write_deleted_classes()
67         self.write_footer()
68
69
70 class WebKitDOMDocGeneratorSGML(WebKitDOMDocGenerator):
71     def write_header(self):
72         self.write('''<?xml version="1.0"?>
73 <!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
74                "http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" [
75 <!ENTITY version SYSTEM "version.xml">
76 ]>
77 <book id="index" xmlns:xi="http://www.w3.org/2003/XInclude">
78   <bookinfo>
79     <title>WebKitDOMGTK+ Reference Manual</title>
80     <releaseinfo>for WebKitDOMGTK+ &version;</releaseinfo>
81   </bookinfo>
82
83   <chapter>
84     <title>Class Overview</title>
85 ''')
86
87     def write_section(self, symbol_file):
88         basename = os.path.basename(symbol_file)
89         self.write('    <xi:include href="xml/%s"/>\n' % basename.replace(".symbols", ".xml"))
90
91     def write_deleted_classes(self):
92         for class_name in self.DELETED_CLASSES:
93             self.write('    <xi:include href="xml/%s.xml"/>\n' % class_name)
94
95     def write_footer(self):
96         self.write('''  </chapter>
97
98   <index id="index-all">
99     <title>Index</title>
100     <xi:include href="xml/api-index-full.xml"><xi:fallback /></xi:include>
101   </index>
102   <index id="api-index-deprecated" role="deprecated">
103     <title>Index of deprecated symbols</title>
104     <xi:include href="xml/api-index-deprecated.xml"><xi:fallback /></xi:include>
105   </index>
106
107   <xi:include href="xml/annotation-glossary.xml"><xi:fallback /></xi:include>
108 </book>
109 ''')
110
111
112 class WebKitDOMDocGeneratorSections(WebKitDOMDocGenerator):
113     def __init__(self, symbol_files, file_handle):
114         super(WebKitDOMDocGeneratorSections, self).__init__(symbol_files, file_handle)
115
116         self._first_decamelize_re = re.compile('(.)([A-Z][a-z]+)')
117         self._second_decamelize_re = re.compile('([a-z0-9])([A-Z])')
118         self._dom_class_re = re.compile('(^WebKitDOM)(.+)$')
119         self._function_re = re.compile('^.+ (.+)\((.+)\)$')
120
121         self.deprecated_symbosl = {}
122         for symbol_file in symbol_files:
123             if WebKitDOMDocGenerator.is_deprecated_symbol_file(symbol_file):
124                 self._deprecated_symbols = self._find_deprecated_symbols(symbol_file)
125                 break
126
127     def _dom_class(self, class_name):
128         return self._dom_class_re.sub(r'\2', class_name)
129
130     def _dom_class_decamelize(self, class_name):
131         s1 = self._first_decamelize_re.sub(r'\1_\2', self._dom_class(class_name))
132         retval = self._second_decamelize_re.sub(r'\1_\2', s1)
133
134         # Fix some exceptions.
135         retval = retval.replace('Web_Kit', 'WebKit')
136         retval = retval.replace('X_Path', 'XPath')
137         retval = retval.replace('HTMLI_Frame', 'HTML_IFrame')
138
139         return retval
140
141     def _deleted_class(self, function):
142         for deleted_class in self.DELETED_CLASSES:
143             decamelized = 'webkit_dom_%s' % self._dom_class_decamelize(deleted_class).lower()
144             if function.startswith(decamelized):
145                 return deleted_class
146         return None
147
148     def _find_deprecated_symbols(self, symbol_file):
149         retval = {}
150         f = open(symbol_file, 'r')
151         for line in f.readlines():
152             match = self._function_re.match(line)
153             if not match:
154                 continue
155
156             function = match.group(1)
157             args = match.group(2).split(', ')
158             class_name = args[0].strip('*')
159             if class_name == 'void':
160                 class_name = self._deleted_class(function)
161
162             retval.setdefault(class_name, []).append(function)
163
164         return retval
165
166     def _symbol_list(self, symbol_file):
167         retval = []
168         f = open(symbol_file, 'r')
169         for line in f.readlines():
170             match = self._function_re.match(line)
171             if not match or match.group(1).endswith('get_type'):
172                 continue
173             retval.append(match.group(1))
174
175         return retval
176
177     def write_section(self, symbol_file):
178         class_name = os.path.basename(symbol_file).replace(".symbols", "")
179         is_custom = class_name == 'WebKitDOMCustom'
180         is_interface = class_name == 'WebKitDOMEventTarget'
181         is_object = class_name == 'WebKitDOMObject'
182         self.write('<SECTION>\n')
183         self.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
184         if not is_custom:
185             self.write('%s\n' % class_name)
186         self.write('\n')
187         self.write('\n'.join(self._symbol_list(symbol_file)) + '\n')
188         try:
189             deprecated_functions = self._deprecated_symbols[class_name]
190             self.write('\n'.join(deprecated_functions) + '\n')
191         except KeyError:
192             pass
193         if not is_custom:
194             self.write('\n<SUBSECTION Standard>\n')
195             self.write('%sClass\n' % class_name)
196             dom_class = self._dom_class_decamelize(class_name).upper()
197             self.write('WEBKIT_TYPE_DOM_%s\n' % dom_class)
198             self.write('WEBKIT_DOM_%s\n' % dom_class)
199             if is_object:
200                 self.write('WEBKIT_IS_DOM_%s\n' % dom_class)
201             else:
202                 self.write('WEBKIT_DOM_IS_%s\n' % dom_class)
203             self.write('WEBKIT_DOM_%s_CLASS\n' % dom_class)
204             if is_interface:
205                 self.write('WEBKIT_DOM_%s_GET_IFACE\n' % dom_class)
206             else:
207                 if is_object:
208                     self.write('WEBKIT_IS_DOM_%s_CLASS\n' % dom_class)
209                 else:
210                     self.write('WEBKIT_DOM_IS_%s_CLASS\n' % dom_class)
211                 self.write('WEBKIT_DOM_%s_GET_CLASS\n' % dom_class)
212             self.write('\n<SUBSECTION Private>\n')
213             if is_object:
214                 self.write('%sPrivate\n' % class_name)
215             self.write('webkit_dom_%s_get_type\n' % dom_class.lower())
216         self.write('</SECTION>\n\n')
217
218     def write_deleted_classes(self):
219         for class_name in self.DELETED_CLASSES:
220             self.write('<SECTION>\n')
221             self.write('<FILE>%s</FILE>\n<TITLE>%s</TITLE>\n' % (class_name, class_name))
222             self.write('\n'.join([name for name in self._deprecated_symbols[class_name] if not name.endswith('get_type')]) + '\n')
223             self.write('\n<SUBSECTION Private>\n')
224             self.write('webkit_dom_%s_get_type\n' % self._dom_class_decamelize(class_name).lower())
225             self.write('</SECTION>\n\n')
226
227     def write_footer(self):
228         self.write('<SECTION>\n')
229         self.write('<FILE>webkitdomdefines</FILE>\n<TITLE>WebKitDOMDefines</TITLE>\n')
230         self.write('<SUBSECTION Private>\n')
231         self.write('WEBKIT_API\nWEBKIT_DEPRECATED\nWEBKIT_DEPRECATED_FOR\n')
232         self.write('</SECTION>\n\n')
233
234
235 def write_doc_files():
236     doc_dir = common.build_path('DerivedSources', 'webkitdom', 'docs')
237
238     try:
239         os.mkdir(doc_dir)
240     except:
241         pass  # Commonly happens if the directory already exists.
242
243     with open(os.path.join(doc_dir, 'webkitdomgtk-sections.txt'), 'w') as sections_file:
244         generator = WebKitDOMDocGeneratorSections(get_all_webkitdom_symbol_files(), sections_file)
245         generator.generate()
246     with open(os.path.join(doc_dir, 'webkitdomgtk-docs.sgml'), 'w') as sgml_file:
247         generator = WebKitDOMDocGeneratorSGML(get_all_webkitdom_symbol_files(), sgml_file)
248         generator.generate()
249
250
251 def header_name_list_from_gtkdoc_config_file():
252     config_file = common.build_path('gtkdoc-webkitdom.cfg')
253     if not os.path.isfile(config_file):
254         sys.stderr.write("Could not find config file at %s\n" % config_file)
255         return sys.exit(1)
256
257     config = SafeConfigParser()
258     config.read(config_file)
259     module_name = config.sections()[0]
260     return [os.path.basename(f) for f in str(config.get(module_name, 'headers')).replace(';', ' ').split()]
261
262
263 def get_all_webkitdom_symbol_files():
264     static_symbol_files_path = common.top_level_path('Source', 'WebCore', 'bindings', 'gobject')
265     generated_symbol_files_path = common.build_path('DerivedSources', 'webkitdom')
266
267     symbol_files = []
268     for header_name in header_name_list_from_gtkdoc_config_file():
269         # webkitdomdefines.h doesn't have a corresponding symbols file and webkitdom.symbols is a
270         # file containing the expected symbols results.
271         if header_name in ("webkitdom.h", "webkitdomdefines.h"):
272             continue
273
274         symbol_file = header_name.replace(".h", ".symbols")
275         path = os.path.join(static_symbol_files_path, symbol_file)
276         if os.path.exists(path):
277             symbol_files.append(path)
278             continue
279         path = os.path.join(generated_symbol_files_path, symbol_file)
280         if os.path.exists(path):
281             symbol_files.append(path)
282             continue
283         sys.stderr.write("Could not find symbol file for header: %s\n" % header_name)
284         sys.exit(1)
285
286     return symbol_files