Chromium Code Reviews| 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 from datetime import date | 8 from datetime import date |
| 9 import re | 9 import re |
| 10 import optparse | 10 import optparse |
| 11 import os | 11 import os |
| 12 from string import Template | 12 from string import Template |
| 13 import sys | 13 import sys |
| 14 import textwrap | 14 import textwrap |
| 15 import zipfile | 15 import zipfile |
| 16 | 16 |
| 17 from util import build_utils | 17 from util import build_utils |
| 18 | 18 |
| 19 # List of C++ types that are compatible with the Java code generated by this | 19 # List of C++ types that are compatible with the Java code generated by this |
| 20 # script. | 20 # script. |
| 21 # | 21 # |
| 22 # This script can parse .idl files however, at present it ignores special | 22 # This script can parse .idl files however, at present it ignores special |
| 23 # rules such as [cpp_enum_prefix_override="ax_attr"]. | 23 # rules such as [cpp_enum_prefix_override="ax_attr"]. |
| 24 ENUM_FIXED_TYPE_WHITELIST = ['char', 'unsigned char', | 24 ENUM_FIXED_TYPE_WHITELIST = ['char', 'unsigned char', |
| 25 'short', 'unsigned short', | 25 'short', 'unsigned short', |
| 26 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'] | 26 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t'] |
| 27 | 27 |
| 28 class EnumDefinition(object): | 28 class EnumDefinition(object): |
| 29 def __init__(self, original_enum_name=None, class_name_override=None, | 29 def __init__(self, original_enum_name=None, class_name_override=None, |
| 30 enum_package=None, entries=None, fixed_type=None): | 30 enum_package=None, entries=None, comments=None, fixed_type=None): |
| 31 self.original_enum_name = original_enum_name | 31 self.original_enum_name = original_enum_name |
| 32 self.class_name_override = class_name_override | 32 self.class_name_override = class_name_override |
| 33 self.enum_package = enum_package | 33 self.enum_package = enum_package |
| 34 self.entries = collections.OrderedDict(entries or []) | 34 self.entries = collections.OrderedDict(entries or []) |
| 35 self.comments = collections.OrderedDict(comments or []) | |
| 35 self.prefix_to_strip = None | 36 self.prefix_to_strip = None |
| 36 self.fixed_type = fixed_type | 37 self.fixed_type = fixed_type |
| 37 | 38 |
| 38 def AppendEntry(self, key, value): | 39 def AppendEntry(self, key, value): |
| 39 if key in self.entries: | 40 if key in self.entries: |
| 40 raise Exception('Multiple definitions of key %s found.' % key) | 41 raise Exception('Multiple definitions of key %s found.' % key) |
| 41 self.entries[key] = value | 42 self.entries[key] = value |
| 42 | 43 |
| 44 def AppendEntryComment(self, key, value): | |
| 45 if key in self.comments: | |
| 46 raise Exception('Multiple definitions of key %s found.' % key) | |
| 47 self.comments[key] = value | |
| 48 | |
| 43 @property | 49 @property |
| 44 def class_name(self): | 50 def class_name(self): |
| 45 return self.class_name_override or self.original_enum_name | 51 return self.class_name_override or self.original_enum_name |
| 46 | 52 |
| 47 def Finalize(self): | 53 def Finalize(self): |
| 48 self._Validate() | 54 self._Validate() |
| 49 self._AssignEntryIndices() | 55 self._AssignEntryIndices() |
| 50 self._StripPrefix() | 56 self._StripPrefix() |
| 51 | 57 |
| 52 def _Validate(self): | 58 def _Validate(self): |
| (...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 117 def UpdateDefinition(self, definition): | 123 def UpdateDefinition(self, definition): |
| 118 definition.class_name_override = self._directives.get( | 124 definition.class_name_override = self._directives.get( |
| 119 DirectiveSet.class_name_override_key, '') | 125 DirectiveSet.class_name_override_key, '') |
| 120 definition.enum_package = self._directives.get( | 126 definition.enum_package = self._directives.get( |
| 121 DirectiveSet.enum_package_key) | 127 DirectiveSet.enum_package_key) |
| 122 definition.prefix_to_strip = self._directives.get( | 128 definition.prefix_to_strip = self._directives.get( |
| 123 DirectiveSet.prefix_to_strip_key) | 129 DirectiveSet.prefix_to_strip_key) |
| 124 | 130 |
| 125 | 131 |
| 126 class HeaderParser(object): | 132 class HeaderParser(object): |
| 127 single_line_comment_re = re.compile(r'\s*//') | 133 single_line_comment_re = re.compile(r'\s*//\s*([^\n]+)') |
| 128 multi_line_comment_start_re = re.compile(r'\s*/\*') | 134 multi_line_comment_start_re = re.compile(r'\s*/\*') |
| 129 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') | 135 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') |
| 130 enum_end_re = re.compile(r'^\s*}\s*;\.*$') | 136 enum_end_re = re.compile(r'^\s*}\s*;\.*$') |
| 131 generator_directive_re = re.compile( | 137 generator_directive_re = re.compile( |
| 132 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') | 138 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') |
| 133 multi_line_generator_directive_start_re = re.compile( | 139 multi_line_generator_directive_start_re = re.compile( |
| 134 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') | 140 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') |
| 135 multi_line_directive_continuation_re = re.compile( | 141 multi_line_directive_continuation_re = re.compile( |
| 136 r'^\s*//\s+([\.\w]+)$') | 142 r'^\s*//\s+([\.\w]+)$') |
| 137 multi_line_directive_end_re = re.compile( | 143 multi_line_directive_end_re = re.compile( |
| 138 r'^\s*//\s+([\.\w]*)\)$') | 144 r'^\s*//\s+([\.\w]*)\)$') |
| 139 | 145 |
| 140 optional_class_or_struct_re = r'(class|struct)?' | 146 optional_class_or_struct_re = r'(class|struct)?' |
| 141 enum_name_re = r'(\w+)' | 147 enum_name_re = r'(\w+)' |
| 142 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' | 148 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' |
| 143 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + | 149 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + |
| 144 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + | 150 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + |
| 145 optional_fixed_type_re + '\s*{\s*$') | 151 optional_fixed_type_re + '\s*{\s*$') |
| 146 | 152 |
| 147 def __init__(self, lines, path=None): | 153 def __init__(self, lines, path=None): |
| 148 self._lines = lines | 154 self._lines = lines |
| 149 self._path = path | 155 self._path = path |
| 150 self._enum_definitions = [] | 156 self._enum_definitions = [] |
| 151 self._in_enum = False | 157 self._in_enum = False |
| 152 self._current_definition = None | 158 self._current_definition = None |
| 159 self._current_comments = [] | |
| 153 self._generator_directives = DirectiveSet() | 160 self._generator_directives = DirectiveSet() |
| 154 self._multi_line_generator_directive = None | 161 self._multi_line_generator_directive = None |
| 155 | 162 |
| 156 def _ApplyGeneratorDirectives(self): | 163 def _ApplyGeneratorDirectives(self): |
| 157 self._generator_directives.UpdateDefinition(self._current_definition) | 164 self._generator_directives.UpdateDefinition(self._current_definition) |
| 158 self._generator_directives = DirectiveSet() | 165 self._generator_directives = DirectiveSet() |
| 159 | 166 |
| 160 def ParseDefinitions(self): | 167 def ParseDefinitions(self): |
| 161 for line in self._lines: | 168 for line in self._lines: |
| 162 self._ParseLine(line) | 169 self._ParseLine(line) |
| 163 return self._enum_definitions | 170 return self._enum_definitions |
| 164 | 171 |
| 165 def _ParseLine(self, line): | 172 def _ParseLine(self, line): |
| 166 if self._multi_line_generator_directive: | 173 if self._multi_line_generator_directive: |
| 167 self._ParseMultiLineDirectiveLine(line) | 174 self._ParseMultiLineDirectiveLine(line) |
| 168 elif not self._in_enum: | 175 elif not self._in_enum: |
| 169 self._ParseRegularLine(line) | 176 self._ParseRegularLine(line) |
| 170 else: | 177 else: |
| 171 self._ParseEnumLine(line) | 178 self._ParseEnumLine(line) |
| 172 | 179 |
| 173 def _ParseEnumLine(self, line): | 180 def _ParseEnumLine(self, line): |
| 174 if HeaderParser.single_line_comment_re.match(line): | 181 if HeaderParser.single_line_comment_re.match(line): |
| 182 enum_comment = HeaderParser.single_line_comment_re.match(line).groups()[0] | |
|
agrieve
2016/08/03 23:09:53
nit: Avoid calling match() twice using a variable.
xunjieli
2016/08/04 13:54:22
Done.
| |
| 183 if len(self._current_comments) > 0: | |
| 184 self._current_comments.append(' ') | |
|
agrieve
2016/08/03 23:09:53
nit: Could you just use ' '.join() later on rather
xunjieli
2016/08/04 13:54:22
Done. Ah, you are right! I didn't thought about th
| |
| 185 self._current_comments.append(enum_comment) | |
| 175 return | 186 return |
| 176 if HeaderParser.multi_line_comment_start_re.match(line): | 187 if HeaderParser.multi_line_comment_start_re.match(line): |
| 177 raise Exception('Multi-line comments in enums are not supported in ' + | 188 raise Exception('Multi-line comments in enums are not supported in ' + |
| 178 self._path) | 189 self._path) |
| 179 enum_end = HeaderParser.enum_end_re.match(line) | 190 enum_end = HeaderParser.enum_end_re.match(line) |
| 180 enum_entry = HeaderParser.enum_line_re.match(line) | 191 enum_entry = HeaderParser.enum_line_re.match(line) |
| 181 if enum_end: | 192 if enum_end: |
| 182 self._ApplyGeneratorDirectives() | 193 self._ApplyGeneratorDirectives() |
| 183 self._current_definition.Finalize() | 194 self._current_definition.Finalize() |
| 184 self._enum_definitions.append(self._current_definition) | 195 self._enum_definitions.append(self._current_definition) |
| 185 self._in_enum = False | 196 self._in_enum = False |
| 186 elif enum_entry: | 197 elif enum_entry: |
| 187 enum_key = enum_entry.groups()[0] | 198 enum_key = enum_entry.groups()[0] |
| 188 enum_value = enum_entry.groups()[2] | 199 enum_value = enum_entry.groups()[2] |
| 189 self._current_definition.AppendEntry(enum_key, enum_value) | 200 self._current_definition.AppendEntry(enum_key, enum_value) |
| 201 if self._current_comments: | |
| 202 self._current_definition.AppendEntryComment( | |
| 203 enum_key, ''.join(self._current_comments)) | |
| 204 self._current_comments = [] | |
| 190 | 205 |
| 191 def _ParseMultiLineDirectiveLine(self, line): | 206 def _ParseMultiLineDirectiveLine(self, line): |
| 192 multi_line_directive_continuation = ( | 207 multi_line_directive_continuation = ( |
| 193 HeaderParser.multi_line_directive_continuation_re.match(line)) | 208 HeaderParser.multi_line_directive_continuation_re.match(line)) |
| 194 multi_line_directive_end = ( | 209 multi_line_directive_end = ( |
| 195 HeaderParser.multi_line_directive_end_re.match(line)) | 210 HeaderParser.multi_line_directive_end_re.match(line)) |
| 196 | 211 |
| 197 if multi_line_directive_continuation: | 212 if multi_line_directive_continuation: |
| 198 value_cont = multi_line_directive_continuation.groups()[0] | 213 value_cont = multi_line_directive_continuation.groups()[0] |
| 199 self._multi_line_generator_directive[1].append(value_cont) | 214 self._multi_line_generator_directive[1].append(value_cont) |
| (...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 282 """) | 297 """) |
| 283 | 298 |
| 284 enum_template = Template(' public static final int ${NAME} = ${VALUE};') | 299 enum_template = Template(' public static final int ${NAME} = ${VALUE};') |
| 285 enum_entries_string = [] | 300 enum_entries_string = [] |
| 286 enum_names = [] | 301 enum_names = [] |
| 287 for enum_name, enum_value in enum_definition.entries.iteritems(): | 302 for enum_name, enum_value in enum_definition.entries.iteritems(): |
| 288 values = { | 303 values = { |
| 289 'NAME': enum_name, | 304 'NAME': enum_name, |
| 290 'VALUE': enum_value, | 305 'VALUE': enum_value, |
| 291 } | 306 } |
| 307 enum_comments = enum_definition.comments.get(enum_name) | |
| 308 if enum_comments: | |
| 309 enum_comments_indent = ' * ' | |
| 310 comments_line_wrapper = textwrap.TextWrapper( | |
| 311 initial_indent = enum_comments_indent, | |
|
agrieve
2016/08/03 23:09:53
nit: no spaces around = for arguments. initial_in
xunjieli
2016/08/04 13:54:22
Done.
| |
| 312 subsequent_indent = enum_comments_indent, | |
| 313 width = 100) | |
| 314 enum_entries_string.append(' /**') | |
| 315 enum_entries_string.append( | |
| 316 '\n'.join(comments_line_wrapper.wrap(enum_comments))) | |
| 317 enum_entries_string.append(' */') | |
| 292 enum_entries_string.append(enum_template.substitute(values)) | 318 enum_entries_string.append(enum_template.substitute(values)) |
| 293 enum_names.append(enum_name) | 319 enum_names.append(enum_name) |
| 294 enum_entries_string = '\n'.join(enum_entries_string) | 320 enum_entries_string = '\n'.join(enum_entries_string) |
| 295 | 321 |
| 296 enum_names_indent = ' ' * 6 | 322 enum_names_indent = ' ' * 6 |
| 297 wrapper = textwrap.TextWrapper(initial_indent = enum_names_indent, | 323 wrapper = textwrap.TextWrapper(initial_indent = enum_names_indent, |
| 298 subsequent_indent = enum_names_indent, | 324 subsequent_indent = enum_names_indent, |
| 299 width = 100) | 325 width = 100) |
| 300 enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names))) | 326 enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names))) |
| 301 | 327 |
| (...skipping 83 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 385 if options.verbose: | 411 if options.verbose: |
| 386 print 'Output paths:' | 412 print 'Output paths:' |
| 387 print '\n'.join(output_paths) | 413 print '\n'.join(output_paths) |
| 388 | 414 |
| 389 # Used by GYP. | 415 # Used by GYP. |
| 390 return ' '.join(output_paths) | 416 return ' '.join(output_paths) |
| 391 | 417 |
| 392 | 418 |
| 393 if __name__ == '__main__': | 419 if __name__ == '__main__': |
| 394 DoMain(sys.argv[1:]) | 420 DoMain(sys.argv[1:]) |
| OLD | NEW |