| Index: build/android/gyp/java_cpp_string.py
|
| diff --git a/build/android/gyp/java_cpp_enum.py b/build/android/gyp/java_cpp_string.py
|
| similarity index 53%
|
| copy from build/android/gyp/java_cpp_enum.py
|
| copy to build/android/gyp/java_cpp_string.py
|
| index b304930d9d763089862948d8085b7304e24ff0a0..470def7fedf22fb64547659baad47581fde28eb8 100755
|
| --- a/build/android/gyp/java_cpp_enum.py
|
| +++ b/build/android/gyp/java_cpp_string.py
|
| @@ -1,6 +1,6 @@
|
| #!/usr/bin/env python
|
| #
|
| -# Copyright 2014 The Chromium Authors. All rights reserved.
|
| +# Copyright 2016 The Chromium Authors. All rights reserved.
|
| # Use of this source code is governed by a BSD-style license that can be
|
| # found in the LICENSE file.
|
|
|
| @@ -15,91 +15,31 @@ import zipfile
|
|
|
| from util import build_utils
|
|
|
| -# List of C++ types that are compatible with the Java code generated by this
|
| -# script.
|
| -#
|
| -# This script can parse .idl files however, at present it ignores special
|
| -# rules such as [cpp_enum_prefix_override="ax_attr"].
|
| -ENUM_FIXED_TYPE_WHITELIST = ['char', 'unsigned char',
|
| - 'short', 'unsigned short',
|
| - 'int', 'int8_t', 'int16_t', 'int32_t', 'uint8_t', 'uint16_t']
|
| -
|
| -class EnumDefinition(object):
|
| - def __init__(self, original_enum_name=None, class_name_override=None,
|
| - enum_package=None, entries=None, fixed_type=None):
|
| - self.original_enum_name = original_enum_name
|
| - self.class_name_override = class_name_override
|
| - self.enum_package = enum_package
|
| +class StringListDefinition(object):
|
| + def __init__(self, class_name=None, string_package=None, entries=None):
|
| + self.class_name = class_name
|
| + self.string_package = string_package
|
| self.entries = collections.OrderedDict(entries or [])
|
| - self.prefix_to_strip = None
|
| - self.fixed_type = fixed_type
|
|
|
| def AppendEntry(self, key, value):
|
| if key in self.entries:
|
| raise Exception('Multiple definitions of key %s found.' % key)
|
| self.entries[key] = value
|
|
|
| - @property
|
| - def class_name(self):
|
| - return self.class_name_override or self.original_enum_name
|
| -
|
| def Finalize(self):
|
| self._Validate()
|
| - self._AssignEntryIndices()
|
| - self._StripPrefix()
|
|
|
| def _Validate(self):
|
| assert self.class_name
|
| - assert self.enum_package
|
| + assert self.string_package
|
| assert self.entries
|
| - if self.fixed_type and self.fixed_type not in ENUM_FIXED_TYPE_WHITELIST:
|
| - raise Exception('Fixed type %s for enum %s not whitelisted.' %
|
| - (self.fixed_type, self.class_name))
|
| -
|
| - def _AssignEntryIndices(self):
|
| - # Enums, if given no value, are given the value of the previous enum + 1.
|
| - if not all(self.entries.values()):
|
| - prev_enum_value = -1
|
| - for key, value in self.entries.iteritems():
|
| - if not value:
|
| - self.entries[key] = prev_enum_value + 1
|
| - elif value in self.entries:
|
| - self.entries[key] = self.entries[value]
|
| - else:
|
| - try:
|
| - self.entries[key] = int(value)
|
| - except ValueError:
|
| - raise Exception('Could not interpret integer from enum value "%s" '
|
| - 'for key %s.' % (value, key))
|
| - prev_enum_value = self.entries[key]
|
| -
|
| -
|
| - def _StripPrefix(self):
|
| - prefix_to_strip = self.prefix_to_strip
|
| - if not prefix_to_strip:
|
| - prefix_to_strip = self.original_enum_name
|
| - prefix_to_strip = re.sub('(?!^)([A-Z]+)', r'_\1', prefix_to_strip).upper()
|
| - prefix_to_strip += '_'
|
| - if not all([w.startswith(prefix_to_strip) for w in self.entries.keys()]):
|
| - prefix_to_strip = ''
|
| -
|
| - entries = collections.OrderedDict()
|
| - for (k, v) in self.entries.iteritems():
|
| - stripped_key = k.replace(prefix_to_strip, '', 1)
|
| - if isinstance(v, basestring):
|
| - stripped_value = v.replace(prefix_to_strip, '', 1)
|
| - else:
|
| - stripped_value = v
|
| - entries[stripped_key] = stripped_value
|
| -
|
| - self.entries = entries
|
| +
|
|
|
| class DirectiveSet(object):
|
| - class_name_override_key = 'CLASS_NAME_OVERRIDE'
|
| - enum_package_key = 'ENUM_PACKAGE'
|
| - prefix_to_strip_key = 'PREFIX_TO_STRIP'
|
| + class_name_key = 'CLASS_NAME'
|
| + string_package_key = 'STRING_PACKAGE'
|
|
|
| - known_keys = [class_name_override_key, enum_package_key, prefix_to_strip_key]
|
| + known_keys = [class_name_key, string_package_key]
|
|
|
| def __init__(self):
|
| self._directives = {}
|
| @@ -114,19 +54,21 @@ class DirectiveSet(object):
|
| return len(self._directives) == 0
|
|
|
| def UpdateDefinition(self, definition):
|
| - definition.class_name_override = self._directives.get(
|
| - DirectiveSet.class_name_override_key, '')
|
| - definition.enum_package = self._directives.get(
|
| - DirectiveSet.enum_package_key)
|
| - definition.prefix_to_strip = self._directives.get(
|
| - DirectiveSet.prefix_to_strip_key)
|
| + definition.class_name = self._directives.get(
|
| + DirectiveSet.class_name_key)
|
| + definition.string_package = self._directives.get(
|
| + DirectiveSet.string_package_key)
|
|
|
|
|
| -class HeaderParser(object):
|
| +class CppStringFileParser(object):
|
| single_line_comment_re = re.compile(r'\s*//')
|
| multi_line_comment_start_re = re.compile(r'\s*/\*')
|
| - enum_line_re = re.compile(r'^\s*(\w+)(\s*\=\s*([^,\n]+))?,?')
|
| - enum_end_re = re.compile(r'^\s*}\s*;\.*$')
|
| + single_string_line_re = re.compile(
|
| + r'^\s*const\s*char\s*(\w+)\[\]\s*\=\s*"([^"]*)";')
|
| + multi_string_line_start_re = re.compile(
|
| + r'^\s*const\s*char\s*(\w+)\[\]\s*\=?\s*$')
|
| + multi_string_line_end_re = re.compile(
|
| + r'^\s*\=?\s*"([^"]*)";')
|
| generator_directive_re = re.compile(
|
| r'^\s*//\s+GENERATED_JAVA_(\w+)\s*:\s*([\.\w]+)$')
|
| multi_line_generator_directive_start_re = re.compile(
|
| @@ -136,62 +78,92 @@ class HeaderParser(object):
|
| multi_line_directive_end_re = re.compile(
|
| r'^\s*//\s+([\.\w]*)\)$')
|
|
|
| - optional_class_or_struct_re = r'(class|struct)?'
|
| - enum_name_re = r'(\w+)'
|
| - optional_fixed_type_re = r'(\:\s*(\w+\s*\w+?))?'
|
| - enum_start_re = re.compile(r'^\s*(?:\[cpp.*\])?\s*enum\s+' +
|
| - optional_class_or_struct_re + '\s*' + enum_name_re + '\s*' +
|
| - optional_fixed_type_re + '\s*{\s*$')
|
|
|
| def __init__(self, lines, path=None):
|
| self._lines = lines
|
| self._path = path
|
| - self._enum_definitions = []
|
| - self._in_enum = False
|
| + self._string_definitions = []
|
| self._current_definition = None
|
| self._generator_directives = DirectiveSet()
|
| self._multi_line_generator_directive = None
|
| + self._current_multiline_string_key = None
|
|
|
| def _ApplyGeneratorDirectives(self):
|
| self._generator_directives.UpdateDefinition(self._current_definition)
|
| self._generator_directives = DirectiveSet()
|
|
|
| def ParseDefinitions(self):
|
| + self._current_definition = StringListDefinition()
|
| for line in self._lines:
|
| self._ParseLine(line)
|
| - return self._enum_definitions
|
| + self._ApplyGeneratorDirectives()
|
| + self._current_definition.Finalize()
|
| + return self._current_definition
|
|
|
| def _ParseLine(self, line):
|
| if self._multi_line_generator_directive:
|
| self._ParseMultiLineDirectiveLine(line)
|
| - elif not self._in_enum:
|
| - self._ParseRegularLine(line)
|
| else:
|
| - self._ParseEnumLine(line)
|
| + self._ParseStringLine(line)
|
| +
|
| + def _ParseStringLine(self, line):
|
| + # If we're continuing the start of a string definition, we need to match
|
| + # the end part of the string defintiion.
|
| + if self._current_multiline_string_key:
|
| + string_multi_line_end = (
|
| + CppStringFileParser.multi_string_line_end_re.match(line))
|
| + if not string_multi_line_end:
|
| + raise Exception('Incomplete multi-line string definition ' +
|
| + self._path)
|
| +
|
| + string_key = self._current_multiline_string_key
|
| + string_value = string_multi_line_end.groups()[0]
|
| + self._current_definition.AppendEntry(string_key, string_value)
|
| + self._current_multiline_string_key = None
|
| + return
|
|
|
| - def _ParseEnumLine(self, line):
|
| - if HeaderParser.single_line_comment_re.match(line):
|
| + generator_directive = CppStringFileParser.generator_directive_re.match(line)
|
| + multi_line_generator_directive_start = (
|
| + CppStringFileParser.multi_line_generator_directive_start_re.match(line))
|
| + if generator_directive:
|
| + directive_name = generator_directive.groups()[0]
|
| + directive_value = generator_directive.groups()[1]
|
| + self._generator_directives.Update(directive_name, directive_value)
|
| + return
|
| + if multi_line_generator_directive_start:
|
| + directive_name = multi_line_generator_directive_start.groups()[0]
|
| + directive_value = multi_line_generator_directive_start.groups()[1]
|
| + self._multi_line_generator_directive = (directive_name, [directive_value])
|
| + return
|
| +
|
| + if CppStringFileParser.single_line_comment_re.match(line):
|
| return
|
| - if HeaderParser.multi_line_comment_start_re.match(line):
|
| - raise Exception('Multi-line comments in enums are not supported in ' +
|
| + if CppStringFileParser.multi_line_comment_start_re.match(line):
|
| + raise Exception('Multi-line comments in strings are not supported in ' +
|
| self._path)
|
| - enum_end = HeaderParser.enum_end_re.match(line)
|
| - enum_entry = HeaderParser.enum_line_re.match(line)
|
| - if enum_end:
|
| - self._ApplyGeneratorDirectives()
|
| - self._current_definition.Finalize()
|
| - self._enum_definitions.append(self._current_definition)
|
| - self._in_enum = False
|
| - elif enum_entry:
|
| - enum_key = enum_entry.groups()[0]
|
| - enum_value = enum_entry.groups()[2]
|
| - self._current_definition.AppendEntry(enum_key, enum_value)
|
| +
|
| + string_multi_line_start = (
|
| + CppStringFileParser.multi_string_line_start_re.match(line))
|
| + single_string_line = CppStringFileParser.single_string_line_re.match(line)
|
| + if string_multi_line_start or single_string_line:
|
| + if self._generator_directives.empty:
|
| + raise Exception('Missing directives before string definition in ' +
|
| + self._path)
|
| + if string_multi_line_start:
|
| + self._current_multiline_string_key = string_multi_line_start.groups()[0]
|
| + return
|
| + if single_string_line:
|
| + string_key = single_string_line.groups()[0]
|
| + string_value = single_string_line.groups()[1]
|
| + self._current_definition.AppendEntry(string_key, string_value)
|
| + return
|
| +
|
|
|
| def _ParseMultiLineDirectiveLine(self, line):
|
| multi_line_directive_continuation = (
|
| - HeaderParser.multi_line_directive_continuation_re.match(line))
|
| + CppStringFileParser.multi_line_directive_continuation_re.match(line))
|
| multi_line_directive_end = (
|
| - HeaderParser.multi_line_directive_end_re.match(line))
|
| + CppStringFileParser.multi_line_directive_end_re.match(line))
|
|
|
| if multi_line_directive_continuation:
|
| value_cont = multi_line_directive_continuation.groups()[0]
|
| @@ -206,53 +178,30 @@ class HeaderParser(object):
|
| raise Exception('Malformed multi-line directive declaration in ' +
|
| self._path)
|
|
|
| - def _ParseRegularLine(self, line):
|
| - enum_start = HeaderParser.enum_start_re.match(line)
|
| - generator_directive = HeaderParser.generator_directive_re.match(line)
|
| - multi_line_generator_directive_start = (
|
| - HeaderParser.multi_line_generator_directive_start_re.match(line))
|
| -
|
| - if generator_directive:
|
| - directive_name = generator_directive.groups()[0]
|
| - directive_value = generator_directive.groups()[1]
|
| - self._generator_directives.Update(directive_name, directive_value)
|
| - elif multi_line_generator_directive_start:
|
| - directive_name = multi_line_generator_directive_start.groups()[0]
|
| - directive_value = multi_line_generator_directive_start.groups()[1]
|
| - self._multi_line_generator_directive = (directive_name, [directive_value])
|
| - elif enum_start:
|
| - if self._generator_directives.empty:
|
| - return
|
| - self._current_definition = EnumDefinition(
|
| - original_enum_name=enum_start.groups()[1],
|
| - fixed_type=enum_start.groups()[3])
|
| - self._in_enum = True
|
|
|
| def GetScriptName():
|
| return os.path.basename(os.path.abspath(sys.argv[0]))
|
|
|
| def DoGenerate(source_paths):
|
| for source_path in source_paths:
|
| - enum_definitions = DoParseHeaderFile(source_path)
|
| - if not enum_definitions:
|
| - raise Exception('No enums found in %s\n'
|
| - 'Did you forget prefixing enums with '
|
| - '"// GENERATED_JAVA_ENUM_PACKAGE: foo"?' %
|
| + string_definition = DoParseHeaderFile(source_path)
|
| + if not string_definition:
|
| + raise Exception('No strings found in %s\n'
|
| + 'Did you forget prefixing strings with '
|
| + '"// GENERATED_JAVA_STRING_PACKAGE: foo"?' %
|
| source_path)
|
| - for enum_definition in enum_definitions:
|
| - package_path = enum_definition.enum_package.replace('.', os.path.sep)
|
| - file_name = enum_definition.class_name + '.java'
|
| - output_path = os.path.join(package_path, file_name)
|
| - output = GenerateOutput(source_path, enum_definition)
|
| - yield output_path, output
|
| -
|
| + package_path = string_definition.string_package.replace('.', os.path.sep)
|
| + file_name = string_definition.class_name + '.java'
|
| + output_path = os.path.join(package_path, file_name)
|
| + output = GenerateOutput(source_path, string_definition)
|
| + yield output_path, output
|
|
|
| def DoParseHeaderFile(path):
|
| with open(path) as f:
|
| - return HeaderParser(f.readlines(), path).ParseDefinitions()
|
| + return CppStringFileParser(f.readlines(), path).ParseDefinitions()
|
|
|
|
|
| -def GenerateOutput(source_path, enum_definition):
|
| +def GenerateOutput(source_path, string_definition):
|
| template = Template("""
|
| // Copyright ${YEAR} The Chromium Authors. All rights reserved.
|
| // Use of this source code is governed by a BSD-style license that can be
|
| @@ -266,24 +215,25 @@ def GenerateOutput(source_path, enum_definition):
|
| package ${PACKAGE};
|
|
|
| public class ${CLASS_NAME} {
|
| -${ENUM_ENTRIES}
|
| +${STRING_ENTRIES}
|
| }
|
| """)
|
|
|
| - enum_template = Template(' public static final int ${NAME} = ${VALUE};')
|
| - enum_entries_string = []
|
| - for enum_name, enum_value in enum_definition.entries.iteritems():
|
| + string_template = (
|
| + Template(' public static final String ${NAME} = "${VALUE}";'))
|
| + string_entries_string = []
|
| + for string_name, string_value in string_definition.entries.iteritems():
|
| values = {
|
| - 'NAME': enum_name,
|
| - 'VALUE': enum_value,
|
| + 'NAME': string_name,
|
| + 'VALUE': string_value,
|
| }
|
| - enum_entries_string.append(enum_template.substitute(values))
|
| - enum_entries_string = '\n'.join(enum_entries_string)
|
| + string_entries_string.append(string_template.substitute(values))
|
| + string_entries_string = '\n'.join(string_entries_string)
|
|
|
| values = {
|
| - 'CLASS_NAME': enum_definition.class_name,
|
| - 'ENUM_ENTRIES': enum_entries_string,
|
| - 'PACKAGE': enum_definition.enum_package,
|
| + 'CLASS_NAME': string_definition.class_name,
|
| + 'STRING_ENTRIES': string_entries_string,
|
| + 'PACKAGE': string_definition.string_package,
|
| 'SCRIPT_NAME': GetScriptName(),
|
| 'SOURCE_PATH': source_path,
|
| 'YEAR': str(date.today().year)
|
| @@ -364,6 +314,5 @@ def DoMain(argv):
|
| # Used by GYP.
|
| return ' '.join(output_paths)
|
|
|
| -
|
| if __name__ == '__main__':
|
| DoMain(sys.argv[1:])
|
|
|