OLD | NEW |
1 #!/usr/bin/env python | 1 #!/usr/bin/env python |
2 # | 2 # |
3 # Copyright 2014 The Chromium Authors. All rights reserved. | 3 # Copyright 2014 The Chromium Authors. All rights reserved. |
4 # Use of this source code is governed by a BSD-style license that can be | 4 # Use of this source code is governed by a BSD-style license that can be |
5 # found in the LICENSE file. | 5 # found in the LICENSE file. |
6 | 6 |
7 import collections | 7 import collections |
8 import re | 8 import re |
9 import optparse | 9 import optparse |
10 import os | 10 import os |
(...skipping 11 matching lines...) Expand all Loading... |
22 'short', 'unsigned short', | 22 'short', 'unsigned short', |
23 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'] | 23 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'] |
24 | 24 |
25 class EnumDefinition(object): | 25 class EnumDefinition(object): |
26 def __init__(self, original_enum_name=None, class_name_override=None, | 26 def __init__(self, original_enum_name=None, class_name_override=None, |
27 enum_package=None, entries=None, fixed_type=None): | 27 enum_package=None, entries=None, fixed_type=None): |
28 self.original_enum_name = original_enum_name | 28 self.original_enum_name = original_enum_name |
29 self.class_name_override = class_name_override | 29 self.class_name_override = class_name_override |
30 self.enum_package = enum_package | 30 self.enum_package = enum_package |
31 self.entries = collections.OrderedDict(entries or []) | 31 self.entries = collections.OrderedDict(entries or []) |
| 32 self.comments = collections.OrderedDict(entries or []) |
32 self.prefix_to_strip = None | 33 self.prefix_to_strip = None |
33 self.fixed_type = fixed_type | 34 self.fixed_type = fixed_type |
34 | 35 |
35 def AppendEntry(self, key, value): | 36 def AppendEntry(self, key, value, comment): |
36 if key in self.entries: | 37 if key in self.entries: |
37 raise Exception('Multiple definitions of key %s found.' % key) | 38 raise Exception('Multiple definitions of key %s found.' % key) |
38 self.entries[key] = value | 39 self.entries[key] = value |
| 40 self.comments[key] = comment |
39 | 41 |
40 @property | 42 @property |
41 def class_name(self): | 43 def class_name(self): |
42 return self.class_name_override or self.original_enum_name | 44 return self.class_name_override or self.original_enum_name |
43 | 45 |
44 def Finalize(self): | 46 def Finalize(self): |
45 self._Validate() | 47 self._Validate() |
46 self._AssignEntryIndices() | 48 self._AssignEntryIndices() |
47 self._StripPrefix() | 49 self._StripPrefix() |
48 | 50 |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
114 def UpdateDefinition(self, definition): | 116 def UpdateDefinition(self, definition): |
115 definition.class_name_override = self._directives.get( | 117 definition.class_name_override = self._directives.get( |
116 DirectiveSet.class_name_override_key, '') | 118 DirectiveSet.class_name_override_key, '') |
117 definition.enum_package = self._directives.get( | 119 definition.enum_package = self._directives.get( |
118 DirectiveSet.enum_package_key) | 120 DirectiveSet.enum_package_key) |
119 definition.prefix_to_strip = self._directives.get( | 121 definition.prefix_to_strip = self._directives.get( |
120 DirectiveSet.prefix_to_strip_key) | 122 DirectiveSet.prefix_to_strip_key) |
121 | 123 |
122 | 124 |
123 class HeaderParser(object): | 125 class HeaderParser(object): |
124 single_line_comment_re = re.compile(r'\s*//') | 126 single_line_comment_re = re.compile(r'\s*//(.*)') |
125 multi_line_comment_start_re = re.compile(r'\s*/\*') | 127 multi_line_comment_start_re = re.compile(r'\s*/\*') |
126 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') | 128 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') |
127 enum_end_re = re.compile(r'^\s*}\s*;\.*$') | 129 enum_end_re = re.compile(r'^\s*}\s*;\.*$') |
128 generator_directive_re = re.compile( | 130 generator_directive_re = re.compile( |
129 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') | 131 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') |
130 multi_line_generator_directive_start_re = re.compile( | 132 multi_line_generator_directive_start_re = re.compile( |
131 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') | 133 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') |
132 multi_line_directive_continuation_re = re.compile( | 134 multi_line_directive_continuation_re = re.compile( |
133 r'^\s*//\s+([\.\w]+)$') | 135 r'^\s*//\s+([\.\w]+)$') |
134 multi_line_directive_end_re = re.compile( | 136 multi_line_directive_end_re = re.compile( |
135 r'^\s*//\s+([\.\w]*)\)$') | 137 r'^\s*//\s+([\.\w]*)\)$') |
136 | 138 |
137 optional_class_or_struct_re = r'(class|struct)?' | 139 optional_class_or_struct_re = r'(class|struct)?' |
138 enum_name_re = r'(\w+)' | 140 enum_name_re = r'(\w+)' |
139 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' | 141 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' |
140 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + | 142 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + |
141 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + | 143 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + |
142 optional_fixed_type_re + '\s*{\s*$') | 144 optional_fixed_type_re + '\s*{\s*$') |
143 | 145 |
144 def __init__(self, lines, path=None): | 146 def __init__(self, lines, path=None): |
145 self._lines = lines | 147 self._lines = lines |
146 self._path = path | 148 self._path = path |
147 self._enum_definitions = [] | 149 self._enum_definitions = [] |
148 self._in_enum = False | 150 self._in_enum = False |
| 151 self._current_comment = [] |
149 self._current_definition = None | 152 self._current_definition = None |
150 self._generator_directives = DirectiveSet() | 153 self._generator_directives = DirectiveSet() |
151 self._multi_line_generator_directive = None | 154 self._multi_line_generator_directive = None |
152 | 155 |
153 def _ApplyGeneratorDirectives(self): | 156 def _ApplyGeneratorDirectives(self): |
154 self._generator_directives.UpdateDefinition(self._current_definition) | 157 self._generator_directives.UpdateDefinition(self._current_definition) |
155 self._generator_directives = DirectiveSet() | 158 self._generator_directives = DirectiveSet() |
156 | 159 |
157 def ParseDefinitions(self): | 160 def ParseDefinitions(self): |
158 for line in self._lines: | 161 for line in self._lines: |
159 self._ParseLine(line) | 162 self._ParseLine(line) |
160 return self._enum_definitions | 163 return self._enum_definitions |
161 | 164 |
162 def _ParseLine(self, line): | 165 def _ParseLine(self, line): |
163 if self._multi_line_generator_directive: | 166 if self._multi_line_generator_directive: |
164 self._ParseMultiLineDirectiveLine(line) | 167 self._ParseMultiLineDirectiveLine(line) |
165 elif not self._in_enum: | 168 elif not self._in_enum: |
166 self._ParseRegularLine(line) | 169 self._ParseRegularLine(line) |
167 else: | 170 else: |
168 self._ParseEnumLine(line) | 171 self._ParseEnumLine(line) |
169 | 172 |
170 def _ParseEnumLine(self, line): | 173 def _ParseEnumLine(self, line): |
171 if HeaderParser.single_line_comment_re.match(line): | 174 comment = HeaderParser.single_line_comment_re.match(line) |
| 175 if comment: |
| 176 self._current_comment.append(comment.groups()[0]) |
172 return | 177 return |
173 if HeaderParser.multi_line_comment_start_re.match(line): | 178 if HeaderParser.multi_line_comment_start_re.match(line): |
| 179 self._current_comment = [] |
174 raise Exception('Multi-line comments in enums are not supported in ' + | 180 raise Exception('Multi-line comments in enums are not supported in ' + |
175 self._path) | 181 self._path) |
176 enum_end = HeaderParser.enum_end_re.match(line) | 182 enum_end = HeaderParser.enum_end_re.match(line) |
177 enum_entry = HeaderParser.enum_line_re.match(line) | 183 enum_entry = HeaderParser.enum_line_re.match(line) |
178 if enum_end: | 184 if enum_end: |
179 self._ApplyGeneratorDirectives() | 185 self._ApplyGeneratorDirectives() |
180 self._current_definition.Finalize() | 186 self._current_definition.Finalize() |
181 self._enum_definitions.append(self._current_definition) | 187 self._enum_definitions.append(self._current_definition) |
182 self._in_enum = False | 188 self._in_enum = False |
183 elif enum_entry: | 189 elif enum_entry: |
184 enum_key = enum_entry.groups()[0] | 190 enum_key = enum_entry.groups()[0] |
185 enum_value = enum_entry.groups()[2] | 191 enum_value = enum_entry.groups()[2] |
186 self._current_definition.AppendEntry(enum_key, enum_value) | 192 self._current_definition.AppendEntry(enum_key, enum_value, |
| 193 self._current_comment) |
| 194 self._current_comment = [] |
187 | 195 |
188 def _ParseMultiLineDirectiveLine(self, line): | 196 def _ParseMultiLineDirectiveLine(self, line): |
189 multi_line_directive_continuation = ( | 197 multi_line_directive_continuation = ( |
190 HeaderParser.multi_line_directive_continuation_re.match(line)) | 198 HeaderParser.multi_line_directive_continuation_re.match(line)) |
191 multi_line_directive_end = ( | 199 multi_line_directive_end = ( |
192 HeaderParser.multi_line_directive_end_re.match(line)) | 200 HeaderParser.multi_line_directive_end_re.match(line)) |
193 | 201 |
194 if multi_line_directive_continuation: | 202 if multi_line_directive_continuation: |
195 value_cont = multi_line_directive_continuation.groups()[0] | 203 value_cont = multi_line_directive_continuation.groups()[0] |
196 self._multi_line_generator_directive[1].append(value_cont) | 204 self._multi_line_generator_directive[1].append(value_cont) |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
252 return output_paths | 260 return output_paths |
253 | 261 |
254 | 262 |
255 def DoParseHeaderFile(path): | 263 def DoParseHeaderFile(path): |
256 with open(path) as f: | 264 with open(path) as f: |
257 return HeaderParser(f.readlines(), path).ParseDefinitions() | 265 return HeaderParser(f.readlines(), path).ParseDefinitions() |
258 | 266 |
259 | 267 |
260 def GenerateOutput(source_path, enum_definition): | 268 def GenerateOutput(source_path, enum_definition): |
261 template = Template(""" | 269 template = Template(""" |
262 // Copyright 2014 The Chromium Authors. All rights reserved. | 270 // Copyright 2015 The Chromium Authors. All rights reserved. |
263 // Use of this source code is governed by a BSD-style license that can be | 271 // Use of this source code is governed by a BSD-style license that can be |
264 // found in the LICENSE file. | 272 // found in the LICENSE file. |
265 | 273 |
266 // This file is autogenerated by | 274 // This file is autogenerated by |
267 // ${SCRIPT_NAME} | 275 // ${SCRIPT_NAME} |
268 // From | 276 // From |
269 // ${SOURCE_PATH} | 277 // ${SOURCE_PATH} |
270 | 278 |
271 package ${PACKAGE}; | 279 package ${PACKAGE}; |
272 | 280 |
273 public class ${CLASS_NAME} { | 281 public class ${CLASS_NAME} { |
274 ${ENUM_ENTRIES} | 282 ${ENUM_ENTRIES} |
275 } | 283 } |
276 """) | 284 """) |
277 | 285 |
278 enum_template = Template(' public static final int ${NAME} = ${VALUE};') | 286 enum_template = Template('${COMMENT} ' |
| 287 'public static final int ${NAME} = ${VALUE};') |
279 enum_entries_string = [] | 288 enum_entries_string = [] |
280 for enum_name, enum_value in enum_definition.entries.iteritems(): | 289 for enum_name, enum_value in enum_definition.entries.iteritems(): |
| 290 enum_comment_string = [] |
| 291 line_separator = '\n' |
| 292 if enum_name in enum_definition.comments and \ |
| 293 enum_definition.comments[enum_name]: |
| 294 line_separator += '\n' |
| 295 enum_comment_string.append(' /**\n') |
| 296 for comment_line in enum_definition.comments[enum_name]: |
| 297 enum_comment_string.append(' *' + comment_line + '\n') |
| 298 enum_comment_string.append(' */\n') |
281 values = { | 299 values = { |
| 300 'COMMENT': ''.join(enum_comment_string), |
282 'NAME': enum_name, | 301 'NAME': enum_name, |
283 'VALUE': enum_value, | 302 'VALUE': enum_value, |
284 } | 303 } |
285 enum_entries_string.append(enum_template.substitute(values)) | 304 enum_entries_string.append(enum_template.substitute(values)) |
286 enum_entries_string = '\n'.join(enum_entries_string) | 305 enum_entries_string = line_separator.join(enum_entries_string) |
287 | 306 |
288 values = { | 307 values = { |
289 'CLASS_NAME': enum_definition.class_name, | 308 'CLASS_NAME': enum_definition.class_name, |
290 'ENUM_ENTRIES': enum_entries_string, | 309 'ENUM_ENTRIES': enum_entries_string, |
291 'PACKAGE': enum_definition.enum_package, | 310 'PACKAGE': enum_definition.enum_package, |
292 'SCRIPT_NAME': GetScriptName(), | 311 'SCRIPT_NAME': GetScriptName(), |
293 'SOURCE_PATH': source_path, | 312 'SOURCE_PATH': source_path, |
294 } | 313 } |
295 return template.substitute(values) | 314 return template.substitute(values) |
296 | 315 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 AssertFilesList(output_paths, options.assert_files_list) | 350 AssertFilesList(output_paths, options.assert_files_list) |
332 | 351 |
333 if options.verbose: | 352 if options.verbose: |
334 print 'Output paths:' | 353 print 'Output paths:' |
335 print '\n'.join(output_paths) | 354 print '\n'.join(output_paths) |
336 | 355 |
337 return ' '.join(output_paths) | 356 return ' '.join(output_paths) |
338 | 357 |
339 if __name__ == '__main__': | 358 if __name__ == '__main__': |
340 DoMain(sys.argv[1:]) | 359 DoMain(sys.argv[1:]) |
OLD | NEW |