Allow omitting a template file for java_cpp_strings / java_cpp_features

Most templates are the default one, so allow just using "class_name="
for them.

Bug: None
Change-Id: Iaf31cb6a5c699553c03923e4dcea405c684d9703
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/6662418
Reviewed-by: Peter Wen <[email protected]>
Commit-Queue: Andrew Grieve <[email protected]>
Owners-Override: Andrew Grieve <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1477435}
diff --git a/build/android/gyp/java_cpp_features.py b/build/android/gyp/java_cpp_features.py
index 93b61d3..3c1e585 100755
--- a/build/android/gyp/java_cpp_features.py
+++ b/build/android/gyp/java_cpp_features.py
@@ -35,28 +35,24 @@
     return java_cpp_utils.JavaString(name, value, comments)
 
 
-def _GenerateOutput(template, source_paths, template_path, features):
+def _GenerateOutput(template, source_paths, features):
   description_template = """
     // This following string constants were inserted by
     //     {SCRIPT_NAME}
     // From
     //     {SOURCE_PATHS}
-    // Into
-    //     {TEMPLATE_PATH}
 
 """
   values = {
       'SCRIPT_NAME': java_cpp_utils.GetScriptName(),
       'SOURCE_PATHS': ',\n    //     '.join(source_paths),
-      'TEMPLATE_PATH': template_path,
   }
   description = description_template.format(**values)
   native_features = '\n\n'.join(x.Format() for x in features)
 
-  values = {
-      'NATIVE_FEATURES': description + native_features,
-  }
-  return template.format(**values)
+  # TODO(agrieve): Remove {{ and }} from input templates.
+  template = template.replace('{{', '{').replace('}}', '}')
+  return template.replace('{NATIVE_FEATURES}', description + native_features)
 
 
 def _ParseFeatureFile(path):
@@ -66,44 +62,44 @@
   return feature_file_parser.Parse()
 
 
-def _Generate(source_paths, template_path):
-  with open(template_path, encoding='utf-8') as f:
-    lines = f.readlines()
-
-  template = ''.join(lines)
-  package, class_name = java_cpp_utils.ParseTemplateFile(lines)
+def _Generate(source_paths, template):
+  package, class_name = java_cpp_utils.ParseTemplateFile(template)
   output_path = java_cpp_utils.GetJavaFilePath(package, class_name)
 
   features = []
   for source_path in source_paths:
     features.extend(_ParseFeatureFile(source_path))
 
-  output = _GenerateOutput(template, source_paths, template_path, features)
+  output = _GenerateOutput(template, source_paths, features)
   return output, output_path
 
 
 def _Main(argv):
   parser = argparse.ArgumentParser()
-
   parser.add_argument('--srcjar',
                       required=True,
                       help='The path at which to generate the .srcjar file')
-
   parser.add_argument('--template',
-                      required=True,
                       help='The template file with which to generate the Java '
                       'class. Must have "{NATIVE_FEATURES}" somewhere in '
                       'the template.')
-
+  parser.add_argument('--class-name', help='FQN of Java class to generate')
   parser.add_argument('inputs',
                       nargs='+',
                       help='Input file(s)',
                       metavar='INPUTFILE')
   args = parser.parse_args(argv)
 
+  if args.template:
+    with open(args.template, encoding='utf-8') as f:
+      template = f.read()
+  else:
+    template = java_cpp_utils.CreateDefaultTemplate(args.class_name,
+                                                    '{NATIVE_FEATURES}')
+
   with action_helpers.atomic_output(args.srcjar) as f:
     with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as srcjar:
-      data, path = _Generate(args.inputs, args.template)
+      data, path = _Generate(args.inputs, template)
       zip_helpers.add_to_zip_hermetic(srcjar, path, data=data)
 
 
diff --git a/build/android/gyp/java_cpp_strings.py b/build/android/gyp/java_cpp_strings.py
index 74b256c..4a905ce3 100755
--- a/build/android/gyp/java_cpp_strings.py
+++ b/build/android/gyp/java_cpp_strings.py
@@ -31,28 +31,24 @@
     return java_cpp_utils.JavaString(name, value, comments)
 
 
-def _GenerateOutput(template, source_paths, template_path, strings):
+def _GenerateOutput(template, source_paths, strings):
   description_template = """
     // This following string constants were inserted by
     //     {SCRIPT_NAME}
     // From
     //     {SOURCE_PATHS}
-    // Into
-    //     {TEMPLATE_PATH}
 
 """
   values = {
       'SCRIPT_NAME': java_cpp_utils.GetScriptName(),
       'SOURCE_PATHS': ',\n    //     '.join(source_paths),
-      '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)
+  # TODO(agrieve): Remove {{ and }} from input templates.
+  template = template.replace('{{', '{').replace('}}', '}')
+  return template.replace('{NATIVE_STRINGS}', description + native_strings)
 
 
 def _ParseStringFile(path):
@@ -62,41 +58,41 @@
   return string_file_parser.Parse()
 
 
-def _Generate(source_paths, template_path):
-  with open(template_path, encoding='utf-8') as f:
-    lines = f.readlines()
-
-  template = ''.join(lines)
-  package, class_name = java_cpp_utils.ParseTemplateFile(lines)
+def _Generate(source_paths, template):
+  package, class_name = java_cpp_utils.ParseTemplateFile(template)
   output_path = java_cpp_utils.GetJavaFilePath(package, class_name)
   strings = []
   for source_path in source_paths:
     strings.extend(_ParseStringFile(source_path))
 
-  output = _GenerateOutput(template, source_paths, template_path, strings)
+  output = _GenerateOutput(template, source_paths, strings)
   return output, output_path
 
 
 def _Main(argv):
   parser = argparse.ArgumentParser()
-
   parser.add_argument('--srcjar',
                       required=True,
                       help='The path at which to generate the .srcjar file')
-
   parser.add_argument('--template',
-                      required=True,
                       help='The template file with which to generate the Java '
                       'class. Must have "{NATIVE_STRINGS}" somewhere in '
                       'the template.')
-
+  parser.add_argument('--class-name', help='FQN of Java class to generate')
   parser.add_argument(
       'inputs', nargs='+', help='Input file(s)', metavar='INPUTFILE')
   args = parser.parse_args(argv)
 
+  if args.template:
+    with open(args.template, encoding='utf-8') as f:
+      template = f.read()
+  else:
+    template = java_cpp_utils.CreateDefaultTemplate(args.class_name,
+                                                    '{NATIVE_STRINGS}')
+
   with action_helpers.atomic_output(args.srcjar) as f:
     with zipfile.ZipFile(f, 'w', zipfile.ZIP_STORED) as srcjar:
-      data, path = _Generate(args.inputs, args.template)
+      data, path = _Generate(args.inputs, template)
       zip_helpers.add_to_zip_hermetic(srcjar, path, data=data)
 
 
diff --git a/build/android/gyp/java_cpp_strings_tests.py b/build/android/gyp/java_cpp_strings_tests.py
index 793b2c31..24e1a0b2 100755
--- a/build/android/gyp/java_cpp_strings_tests.py
+++ b/build/android/gyp/java_cpp_strings_tests.py
@@ -141,7 +141,7 @@
 {NATIVE_STRINGS}
 
 }}
-""".split('\n')
+"""
     package, class_name = java_cpp_utils.ParseTemplateFile(test_data)
     self.assertEqual('my.java.package', package)
     self.assertEqual('MyClass', class_name)
diff --git a/build/android/gyp/util/java_cpp_utils.py b/build/android/gyp/util/java_cpp_utils.py
index ec92e95..3f0334e 100644
--- a/build/android/gyp/util/java_cpp_utils.py
+++ b/build/android/gyp/util/java_cpp_utils.py
@@ -7,8 +7,26 @@
 import sys
 
 
+def CreateDefaultTemplate(java_class, placeholder):
+  assert '.' in java_class, 'Wanted fully-qualified name. Found ' + java_class
+  package, _, class_name = java_class.rpartition('.')
+
+  script_name = GetScriptName()
+  return f"""\
+// Generated by {script_name}
+
+package {package};
+
+public final class {class_name} {{
+    private {class_name}() {{}}
+
+{placeholder}
+}}
+"""
+
+
 def GetScriptName():
-  return os.path.basename(os.path.abspath(sys.argv[0]))
+  return os.path.basename(sys.argv[0])
 
 
 def GetJavaFilePath(java_package, class_name):
@@ -49,22 +67,13 @@
         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
-  if not package:
-    raise Exception('Could not find java package.')
-  return package, class_name
+def ParseTemplateFile(data):
+  if m := re.search(r'^package (.*);[\s\S]+\bclass (\w+) {',
+                    data,
+                    flags=re.MULTILINE):
+    package, class_name = m.groups()
+    return package, class_name
+  raise Exception('Could not find java package.')
 
 
 # TODO(crbug.com/40616187): Work will be needed if we want to annotate specific