forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Share strings between native and Java
Creates a script that can be used to generate Java files to expose native strings to Java, giving us a single source of truth for these constants. Bug: 937280 Change-Id: I1f0804bdfff8101dfd149612acd44360ae0dc2c0 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/1495747 Commit-Queue: Ian Vollick <vollick@chromium.org> Auto-Submit: Ian Vollick <vollick@chromium.org> Reviewed-by: Scott Violet <sky@chromium.org> Reviewed-by: Andrew Grieve <agrieve@chromium.org> Cr-Commit-Position: refs/heads/master@{#638754}
- Loading branch information
Ian Vollick
authored and
Commit Bot
committed
Mar 7, 2019
1 parent
a9528b2
commit b99472e
Showing
18 changed files
with
612 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,5 @@ | |
java_cpp_enum.py | ||
util/__init__.py | ||
util/build_utils.py | ||
util/java_cpp_utils.py | ||
util/md5_check.py |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,212 @@ | ||
#!/user/bin/env python | ||
# | ||
# Copyright 2019 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. | ||
|
||
import argparse | ||
import os | ||
import re | ||
import sys | ||
import zipfile | ||
|
||
from util import build_utils | ||
from util import java_cpp_utils | ||
|
||
|
||
def _ToUpper(match): | ||
return match.group(1).upper() | ||
|
||
|
||
def _GetClassName(source_path): | ||
name = os.path.basename(os.path.abspath(source_path)) | ||
(name, _) = os.path.splitext(name) | ||
name = re.sub(r'_([a-z])', _ToUpper, name) | ||
name = re.sub(r'^(.)', _ToUpper, name) | ||
return name | ||
|
||
|
||
class _String(object): | ||
|
||
def __init__(self, name, value, comments): | ||
self.name = java_cpp_utils.KCamelToShouty(name) | ||
self.value = value | ||
self.comments = '\n'.join(' ' + x for x in comments) | ||
|
||
def Format(self): | ||
return '%s\n public static final String %s = %s;' % ( | ||
self.comments, self.name, self.value) | ||
|
||
|
||
def ParseTemplateFile(lines): | ||
package_re = re.compile(r'^package (.*);') | ||
class_re = re.compile(r'.*class (.*) {') | ||
package = '' | ||
class_name = '' | ||
for line in lines: | ||
package_line = package_re.match(line) | ||
if package_line: | ||
package = package_line.groups()[0] | ||
class_line = class_re.match(line) | ||
if class_line: | ||
class_name = class_line.groups()[0] | ||
break | ||
return package, class_name | ||
|
||
|
||
# TODO(crbug.com/937282): It should be possible to parse a file for more than | ||
# string constants. However, this currently only handles extracting string | ||
# constants from a file (and all string constants from that file). Work will | ||
# be needed if we want to annotate specific constants or non string constants | ||
# in the file to be parsed. | ||
class StringFileParser(object): | ||
SINGLE_LINE_COMMENT_RE = re.compile(r'\s*(// [^\n]*)') | ||
STRING_RE = re.compile(r'\s*const char k(.*)\[\]\s*=\s*(?:(".*"))?') | ||
VALUE_RE = re.compile(r'\s*("[^"]*")') | ||
|
||
def __init__(self, lines, path=''): | ||
self._lines = lines | ||
self._path = path | ||
self._in_string = False | ||
self._in_comment = False | ||
self._package = '' | ||
self._current_comments = [] | ||
self._current_name = '' | ||
self._current_value = '' | ||
self._strings = [] | ||
|
||
def _Reset(self): | ||
self._current_comments = [] | ||
self._current_name = '' | ||
self._current_value = '' | ||
self._in_string = False | ||
self._in_comment = False | ||
|
||
def _AppendString(self): | ||
self._strings.append( | ||
_String(self._current_name, self._current_value, | ||
self._current_comments)) | ||
self._Reset() | ||
|
||
def _ParseValue(self, line): | ||
value_line = StringFileParser.VALUE_RE.match(line) | ||
if value_line: | ||
self._current_value = value_line.groups()[0] | ||
self._AppendString() | ||
else: | ||
self._Reset() | ||
|
||
def _ParseComment(self, line): | ||
comment_line = StringFileParser.SINGLE_LINE_COMMENT_RE.match(line) | ||
if comment_line: | ||
self._current_comments.append(comment_line.groups()[0]) | ||
self._in_comment = True | ||
self._in_string = True | ||
return True | ||
else: | ||
self._in_comment = False | ||
return False | ||
|
||
def _ParseString(self, line): | ||
string_line = StringFileParser.STRING_RE.match(line) | ||
if string_line: | ||
self._current_name = string_line.groups()[0] | ||
if string_line.groups()[1]: | ||
self._current_value = string_line.groups()[1] | ||
self._AppendString() | ||
return True | ||
else: | ||
self._in_string = False | ||
return False | ||
|
||
def _ParseLine(self, line): | ||
if not self._in_string: | ||
self._ParseComment(line) | ||
return | ||
|
||
if self._in_comment: | ||
if self._ParseComment(line): | ||
return | ||
if not self._ParseString(line): | ||
self._Reset() | ||
return | ||
|
||
if self._in_string: | ||
self._ParseValue(line) | ||
|
||
def Parse(self): | ||
for line in self._lines: | ||
self._ParseLine(line) | ||
return self._strings | ||
|
||
|
||
def _GenerateOutput(template, source_path, template_path, strings): | ||
description_template = """ | ||
// This following string constants were inserted by | ||
// {SCRIPT_NAME} | ||
// From | ||
// {SOURCE_PATH} | ||
// Into | ||
// {TEMPLATE_PATH} | ||
""" | ||
values = { | ||
'SCRIPT_NAME': java_cpp_utils.GetScriptName(), | ||
'SOURCE_PATH': source_path, | ||
'TEMPLATE_PATH': template_path, | ||
} | ||
description = description_template.format(**values) | ||
native_strings = '\n\n'.join(x.Format() for x in strings) | ||
|
||
values = { | ||
'NATIVE_STRINGS': description + native_strings, | ||
} | ||
return template.format(**values) | ||
|
||
|
||
def _ParseStringFile(path): | ||
with open(path) as f: | ||
return StringFileParser(f.readlines(), path).Parse() | ||
|
||
|
||
def _Generate(source_paths, template_path): | ||
with open(template_path) as f: | ||
lines = f.readlines() | ||
template = ''.join(lines) | ||
for source_path in source_paths: | ||
strings = _ParseStringFile(source_path) | ||
package, class_name = ParseTemplateFile(lines) | ||
package_path = package.replace('.', os.path.sep) | ||
file_name = class_name + '.java' | ||
output_path = os.path.join(package_path, file_name) | ||
output = _GenerateOutput(template, source_path, template_path, strings) | ||
yield output, output_path | ||
|
||
|
||
def _Main(argv): | ||
parser = argparse.ArgumentParser() | ||
|
||
parser.add_argument( | ||
'--srcjar', | ||
required=True, | ||
help='When specified, a .srcjar at the given path is ' | ||
'created instead of individual .java files.') | ||
|
||
parser.add_argument( | ||
'--template', | ||
required=True, | ||
help='Can be used to provide a context into which the' | ||
'new string constants will be inserted.') | ||
|
||
parser.add_argument( | ||
'inputs', nargs='+', help='Input file(s)', metavar='INPUTFILE') | ||
args = parser.parse_args(argv) | ||
|
||
with build_utils.AtomicOutput(args.srcjar) as f: | ||
with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as srcjar: | ||
for data, path in _Generate(args.inputs, args.template): | ||
build_utils.AddToZipHermetic(srcjar, path, data=data) | ||
|
||
|
||
if __name__ == '__main__': | ||
_Main(sys.argv[1:]) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
# Generated by running: | ||
# build/print_python_deps.py --root build/android/gyp --output build/android/gyp/java_cpp_strings.pydeps build/android/gyp/java_cpp_strings.py | ||
../../gn_helpers.py | ||
java_cpp_strings.py | ||
util/__init__.py | ||
util/build_utils.py | ||
util/java_cpp_utils.py | ||
util/md5_check.py |
Oops, something went wrong.