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, comments=None, fixed_type=None): | 30 enum_package=None, entries=None, comments=None, fixed_type=None, |
| 31 class_comment=None): | |
| 31 self.original_enum_name = original_enum_name | 32 self.original_enum_name = original_enum_name |
| 32 self.class_name_override = class_name_override | 33 self.class_name_override = class_name_override |
| 33 self.enum_package = enum_package | 34 self.enum_package = enum_package |
| 34 self.entries = collections.OrderedDict(entries or []) | 35 self.entries = collections.OrderedDict(entries or []) |
| 35 self.comments = collections.OrderedDict(comments or []) | 36 self.comments = collections.OrderedDict(comments or []) |
| 36 self.prefix_to_strip = None | 37 self.prefix_to_strip = None |
| 37 self.fixed_type = fixed_type | 38 self.fixed_type = fixed_type |
| 39 self.class_comment = class_comment | |
| 38 | 40 |
| 39 def AppendEntry(self, key, value): | 41 def AppendEntry(self, key, value): |
| 40 if key in self.entries: | 42 if key in self.entries: |
| 41 raise Exception('Multiple definitions of key %s found.' % key) | 43 raise Exception('Multiple definitions of key %s found.' % key) |
| 42 self.entries[key] = value | 44 self.entries[key] = value |
| 43 | 45 |
| 44 def AppendEntryComment(self, key, value): | 46 def AppendEntryComment(self, key, value): |
| 45 if key in self.comments: | 47 if key in self.comments: |
| 46 raise Exception('Multiple definitions of key %s found.' % key) | 48 raise Exception('Multiple definitions of key %s found.' % key) |
| 47 self.comments[key] = value | 49 self.comments[key] = value |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 98 else: | 100 else: |
| 99 stripped_value = v | 101 stripped_value = v |
| 100 entries[stripped_key] = stripped_value | 102 entries[stripped_key] = stripped_value |
| 101 | 103 |
| 102 self.entries = entries | 104 self.entries = entries |
| 103 | 105 |
| 104 class DirectiveSet(object): | 106 class DirectiveSet(object): |
| 105 class_name_override_key = 'CLASS_NAME_OVERRIDE' | 107 class_name_override_key = 'CLASS_NAME_OVERRIDE' |
| 106 enum_package_key = 'ENUM_PACKAGE' | 108 enum_package_key = 'ENUM_PACKAGE' |
| 107 prefix_to_strip_key = 'PREFIX_TO_STRIP' | 109 prefix_to_strip_key = 'PREFIX_TO_STRIP' |
| 110 class_comment_key = 'CLASS_COMMENT' | |
| 108 | 111 |
| 109 known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key] | 112 known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key, |
| 113 class_comment_key] | |
| 110 | 114 |
| 111 def __init__(self): | 115 def __init__(self): |
| 112 self._directives = {} | 116 self._directives = {} |
| 113 | 117 |
| 114 def Update(self, key, value): | 118 def Update(self, key, value): |
| 115 if key not in DirectiveSet.known_keys: | 119 if key not in DirectiveSet.known_keys: |
| 116 raise Exception("Unknown directive: " + key) | 120 raise Exception("Unknown directive: " + key) |
| 117 self._directives[key] = value | 121 self._directives[key] = value |
| 118 | 122 |
| 119 @property | 123 @property |
| 120 def empty(self): | 124 def empty(self): |
| 121 return len(self._directives) == 0 | 125 return len(self._directives) == 0 |
| 122 | 126 |
| 123 def UpdateDefinition(self, definition): | 127 def UpdateDefinition(self, definition): |
| 124 definition.class_name_override = self._directives.get( | 128 definition.class_name_override = self._directives.get( |
| 125 DirectiveSet.class_name_override_key, '') | 129 DirectiveSet.class_name_override_key, '') |
| 126 definition.enum_package = self._directives.get( | 130 definition.enum_package = self._directives.get( |
| 127 DirectiveSet.enum_package_key) | 131 DirectiveSet.enum_package_key) |
| 128 definition.prefix_to_strip = self._directives.get( | 132 definition.prefix_to_strip = self._directives.get( |
| 129 DirectiveSet.prefix_to_strip_key) | 133 DirectiveSet.prefix_to_strip_key) |
| 134 definition.class_comment = self._directives.get( | |
| 135 DirectiveSet.class_comment_key, '') | |
| 130 | 136 |
| 131 | 137 |
| 132 class HeaderParser(object): | 138 class HeaderParser(object): |
| 133 single_line_comment_re = re.compile(r'\s*//\s*([^\n]+)') | 139 single_line_comment_re = re.compile(r'\s*//\s*([^\n]+)') |
| 134 multi_line_comment_start_re = re.compile(r'\s*/\*') | 140 multi_line_comment_start_re = re.compile(r'\s*/\*') |
| 135 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') | 141 enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?') |
| 136 enum_end_re = re.compile(r'^\s*}\s*;\.*$') | 142 enum_end_re = re.compile(r'^\s*}\s*;\.*$') |
| 137 generator_directive_re = re.compile( | 143 generator_directive_re = re.compile( |
| 138 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') | 144 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$') |
| 139 multi_line_generator_directive_start_re = re.compile( | 145 multi_line_generator_directive_start_re = re.compile( |
| 140 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') | 146 r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*\(([\.\w]*)$') |
| 141 multi_line_directive_continuation_re = re.compile( | 147 multi_line_directive_continuation_re = re.compile( |
| 142 r'^\s*//\s+([\.\w]+)$') | 148 r'^\s*//\s+([\.\w]+)$') |
| 143 multi_line_directive_end_re = re.compile( | 149 multi_line_directive_end_re = re.compile( |
| 144 r'^\s*//\s+([\.\w]*)\)$') | 150 r'^\s*//\s+([\.\w]*)\)$') |
| 151 class_comment_directive_start_re = re.compile( | |
| 152 r'^\s*//\s+GENERATED_JAVA_(\w+)_BEGIN\s*:$') | |
| 153 class_comment_directive_continuation_re = re.compile( | |
| 154 r'^\s*//(.*)$') | |
| 155 class_comment_directive_end_re = re.compile( | |
| 156 r'^\s*//\s+GENERATED_JAVA_(\w+)_END$') | |
| 145 | 157 |
| 146 optional_class_or_struct_re = r'(class|struct)?' | 158 optional_class_or_struct_re = r'(class|struct)?' |
| 147 enum_name_re = r'(\w+)' | 159 enum_name_re = r'(\w+)' |
| 148 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' | 160 optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?' |
| 149 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + | 161 enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' + |
| 150 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + | 162 optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' + |
| 151 optional_fixed_type_re + '\s*{\s*$') | 163 optional_fixed_type_re + '\s*{\s*$') |
| 152 | 164 |
| 153 def __init__(self, lines, path=None): | 165 def __init__(self, lines, path=None): |
| 154 self._lines = lines | 166 self._lines = lines |
| 155 self._path = path | 167 self._path = path |
| 156 self._enum_definitions = [] | 168 self._enum_definitions = [] |
| 157 self._in_enum = False | 169 self._in_enum = False |
| 158 self._current_definition = None | 170 self._current_definition = None |
| 159 self._current_comments = [] | 171 self._current_comments = [] |
| 160 self._generator_directives = DirectiveSet() | 172 self._generator_directives = DirectiveSet() |
| 161 self._multi_line_generator_directive = None | 173 self._multi_line_generator_directive = None |
| 174 self._class_comment_directive = None | |
| 162 | 175 |
| 163 def _ApplyGeneratorDirectives(self): | 176 def _ApplyGeneratorDirectives(self): |
| 164 self._generator_directives.UpdateDefinition(self._current_definition) | 177 self._generator_directives.UpdateDefinition(self._current_definition) |
| 165 self._generator_directives = DirectiveSet() | 178 self._generator_directives = DirectiveSet() |
| 166 | 179 |
| 167 def ParseDefinitions(self): | 180 def ParseDefinitions(self): |
| 168 for line in self._lines: | 181 for line in self._lines: |
| 169 self._ParseLine(line) | 182 self._ParseLine(line) |
| 170 return self._enum_definitions | 183 return self._enum_definitions |
| 171 | 184 |
| 172 def _ParseLine(self, line): | 185 def _ParseLine(self, line): |
| 173 if self._multi_line_generator_directive: | 186 if self._class_comment_directive: |
| 187 self._ParseClassCommentDirectiveLine(line) | |
| 188 elif self._multi_line_generator_directive: | |
| 174 self._ParseMultiLineDirectiveLine(line) | 189 self._ParseMultiLineDirectiveLine(line) |
| 175 elif not self._in_enum: | 190 elif not self._in_enum: |
| 176 self._ParseRegularLine(line) | 191 self._ParseRegularLine(line) |
| 177 else: | 192 else: |
| 178 self._ParseEnumLine(line) | 193 self._ParseEnumLine(line) |
| 179 | 194 |
| 180 def _ParseEnumLine(self, line): | 195 def _ParseEnumLine(self, line): |
| 181 enum_comment = HeaderParser.single_line_comment_re.match(line) | 196 enum_comment = HeaderParser.single_line_comment_re.match(line) |
| 182 if enum_comment: | 197 if enum_comment: |
| 183 self._current_comments.append(enum_comment.groups()[0]) | 198 self._current_comments.append(enum_comment.groups()[0]) |
| (...skipping 10 matching lines...) Expand all Loading... | |
| 194 self._in_enum = False | 209 self._in_enum = False |
| 195 elif enum_entry: | 210 elif enum_entry: |
| 196 enum_key = enum_entry.groups()[0] | 211 enum_key = enum_entry.groups()[0] |
| 197 enum_value = enum_entry.groups()[2] | 212 enum_value = enum_entry.groups()[2] |
| 198 self._current_definition.AppendEntry(enum_key, enum_value) | 213 self._current_definition.AppendEntry(enum_key, enum_value) |
| 199 if self._current_comments: | 214 if self._current_comments: |
| 200 self._current_definition.AppendEntryComment( | 215 self._current_definition.AppendEntryComment( |
| 201 enum_key, ' '.join(self._current_comments)) | 216 enum_key, ' '.join(self._current_comments)) |
| 202 self._current_comments = [] | 217 self._current_comments = [] |
| 203 | 218 |
| 219 def _ParseClassCommentDirectiveLine(self, line): | |
| 220 class_comment_directive_continuation = ( | |
| 221 HeaderParser.class_comment_directive_continuation_re.match(line)) | |
| 222 class_comment_directive_end = ( | |
| 223 HeaderParser.class_comment_directive_end_re.match(line)) | |
| 224 | |
| 225 if class_comment_directive_end: | |
| 226 directive_name = self._class_comment_directive[0] | |
| 227 directive_value = "".join(self._class_comment_directive[1]) | |
| 228 self._class_comment_directive = None | |
| 229 self._generator_directives.Update(directive_name, directive_value) | |
| 230 elif class_comment_directive_continuation: | |
| 231 value_cont = class_comment_directive_continuation.groups()[0] | |
| 232 self._class_comment_directive[1].append(value_cont) | |
| 233 else: | |
| 234 raise Exception('Malformed class comment directive declaration in ' + | |
| 235 self._path) | |
| 236 | |
| 237 | |
| 204 def _ParseMultiLineDirectiveLine(self, line): | 238 def _ParseMultiLineDirectiveLine(self, line): |
| 205 multi_line_directive_continuation = ( | 239 multi_line_directive_continuation = ( |
| 206 HeaderParser.multi_line_directive_continuation_re.match(line)) | 240 HeaderParser.multi_line_directive_continuation_re.match(line)) |
| 207 multi_line_directive_end = ( | 241 multi_line_directive_end = ( |
| 208 HeaderParser.multi_line_directive_end_re.match(line)) | 242 HeaderParser.multi_line_directive_end_re.match(line)) |
| 209 | 243 |
| 210 if multi_line_directive_continuation: | 244 if multi_line_directive_continuation: |
| 211 value_cont = multi_line_directive_continuation.groups()[0] | 245 value_cont = multi_line_directive_continuation.groups()[0] |
| 212 self._multi_line_generator_directive[1].append(value_cont) | 246 self._multi_line_generator_directive[1].append(value_cont) |
| 213 elif multi_line_directive_end: | 247 elif multi_line_directive_end: |
| 214 directive_name = self._multi_line_generator_directive[0] | 248 directive_name = self._multi_line_generator_directive[0] |
| 215 directive_value = "".join(self._multi_line_generator_directive[1]) | 249 directive_value = "".join(self._multi_line_generator_directive[1]) |
| 216 directive_value += multi_line_directive_end.groups()[0] | 250 directive_value += multi_line_directive_end.groups()[0] |
| 217 self._multi_line_generator_directive = None | 251 self._multi_line_generator_directive = None |
| 218 self._generator_directives.Update(directive_name, directive_value) | 252 self._generator_directives.Update(directive_name, directive_value) |
| 219 else: | 253 else: |
| 220 raise Exception('Malformed multi-line directive declaration in ' + | 254 raise Exception('Malformed multi-line directive declaration in ' + |
| 221 self._path) | 255 self._path) |
| 222 | 256 |
| 223 def _ParseRegularLine(self, line): | 257 def _ParseRegularLine(self, line): |
| 224 enum_start = HeaderParser.enum_start_re.match(line) | 258 enum_start = HeaderParser.enum_start_re.match(line) |
| 225 generator_directive = HeaderParser.generator_directive_re.match(line) | 259 generator_directive = HeaderParser.generator_directive_re.match(line) |
| 226 multi_line_generator_directive_start = ( | 260 multi_line_generator_directive_start = ( |
| 227 HeaderParser.multi_line_generator_directive_start_re.match(line)) | 261 HeaderParser.multi_line_generator_directive_start_re.match(line)) |
| 262 class_comment_directive_start = ( | |
| 263 HeaderParser.class_comment_directive_start_re.match(line)) | |
| 228 | 264 |
| 229 if generator_directive: | 265 if class_comment_directive_start: |
| 266 directive_name = class_comment_directive_start.groups()[0] | |
| 267 directive_value = '' | |
| 268 self._class_comment_directive = (directive_name, [directive_value]) | |
| 269 elif generator_directive: | |
| 230 directive_name = generator_directive.groups()[0] | 270 directive_name = generator_directive.groups()[0] |
| 231 directive_value = generator_directive.groups()[1] | 271 directive_value = generator_directive.groups()[1] |
| 232 self._generator_directives.Update(directive_name, directive_value) | 272 self._generator_directives.Update(directive_name, directive_value) |
| 233 elif multi_line_generator_directive_start: | 273 elif multi_line_generator_directive_start: |
| 234 directive_name = multi_line_generator_directive_start.groups()[0] | 274 directive_name = multi_line_generator_directive_start.groups()[0] |
| 235 directive_value = multi_line_generator_directive_start.groups()[1] | 275 directive_value = multi_line_generator_directive_start.groups()[1] |
| 236 self._multi_line_generator_directive = (directive_name, [directive_value]) | 276 self._multi_line_generator_directive = (directive_name, [directive_value]) |
| 237 elif enum_start: | 277 elif enum_start: |
| 238 if self._generator_directives.empty: | 278 if self._generator_directives.empty: |
| 239 return | 279 return |
| (...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 277 // From | 317 // From |
| 278 // ${SOURCE_PATH} | 318 // ${SOURCE_PATH} |
| 279 | 319 |
| 280 package ${PACKAGE}; | 320 package ${PACKAGE}; |
| 281 | 321 |
| 282 import android.support.annotation.IntDef; | 322 import android.support.annotation.IntDef; |
| 283 | 323 |
| 284 import java.lang.annotation.Retention; | 324 import java.lang.annotation.Retention; |
| 285 import java.lang.annotation.RetentionPolicy; | 325 import java.lang.annotation.RetentionPolicy; |
| 286 | 326 |
| 327 /** ${CLASS_COMMENT} */ | |
| 287 public class ${CLASS_NAME} { | 328 public class ${CLASS_NAME} { |
| 329 /** @hide */ | |
|
agrieve
2016/09/14 00:43:45
Should @hide really be added unconditionally here?
pauljensen
2016/09/14 18:01:13
The alternative would be to add a comment describi
agrieve
2016/09/14 19:04:44
Sounds good then. I think likely cronet is the onl
| |
| 288 @IntDef({ | 330 @IntDef({ |
| 289 ${INT_DEF} | 331 ${INT_DEF} |
| 290 }) | 332 }) |
| 291 @Retention(RetentionPolicy.SOURCE) | 333 @Retention(RetentionPolicy.SOURCE) |
| 292 public @interface ${ANNOTATION} {} | 334 public @interface ${ANNOTATION} {} |
| 293 ${ENUM_ENTRIES} | 335 ${ENUM_ENTRIES} |
| 294 } | 336 } |
| 295 """) | 337 """) |
| 296 | 338 |
| 297 enum_template = Template(' public static final int ${NAME} = ${VALUE};') | 339 enum_template = Template(' public static final int ${NAME} = ${VALUE};') |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 322 subsequent_indent = enum_names_indent, | 364 subsequent_indent = enum_names_indent, |
| 323 width = 100) | 365 width = 100) |
| 324 enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names))) | 366 enum_names_string = '\n'.join(wrapper.wrap(', '.join(enum_names))) |
| 325 | 367 |
| 326 annotation_template = Template('${NAME}Enum') | 368 annotation_template = Template('${NAME}Enum') |
| 327 annotation_values = { 'NAME': enum_definition.class_name, } | 369 annotation_values = { 'NAME': enum_definition.class_name, } |
| 328 annotation_name = annotation_template.substitute(annotation_values) | 370 annotation_name = annotation_template.substitute(annotation_values) |
| 329 | 371 |
| 330 values = { | 372 values = { |
| 331 'CLASS_NAME': enum_definition.class_name, | 373 'CLASS_NAME': enum_definition.class_name, |
| 374 'CLASS_COMMENT': enum_definition.class_comment, | |
| 332 'ENUM_ENTRIES': enum_entries_string, | 375 'ENUM_ENTRIES': enum_entries_string, |
| 333 'PACKAGE': enum_definition.enum_package, | 376 'PACKAGE': enum_definition.enum_package, |
| 334 'INT_DEF': enum_names_string, | 377 'INT_DEF': enum_names_string, |
| 335 'ANNOTATION': annotation_name, | 378 'ANNOTATION': annotation_name, |
| 336 'SCRIPT_NAME': GetScriptName(), | 379 'SCRIPT_NAME': GetScriptName(), |
| 337 'SOURCE_PATH': source_path, | 380 'SOURCE_PATH': source_path, |
| 338 'YEAR': str(date.today().year) | 381 'YEAR': str(date.today().year) |
| 339 } | 382 } |
| 340 return template.substitute(values) | 383 return template.substitute(values) |
| 341 | 384 |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 409 if options.verbose: | 452 if options.verbose: |
| 410 print 'Output paths:' | 453 print 'Output paths:' |
| 411 print '\n'.join(output_paths) | 454 print '\n'.join(output_paths) |
| 412 | 455 |
| 413 # Used by GYP. | 456 # Used by GYP. |
| 414 return ' '.join(output_paths) | 457 return ' '.join(output_paths) |
| 415 | 458 |
| 416 | 459 |
| 417 if __name__ == '__main__': | 460 if __name__ == '__main__': |
| 418 DoMain(sys.argv[1:]) | 461 DoMain(sys.argv[1:]) |
| OLD | NEW |