• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1# Copyright 2019 The Chromium Authors
2# Use of this source code is governed by a BSD-style license that can be
3# found in the LICENSE file.
4
5import os
6import re
7import sys
8
9
10def GetScriptName():
11  return os.path.basename(os.path.abspath(sys.argv[0]))
12
13
14def GetJavaFilePath(java_package, class_name):
15  package_path = java_package.replace('.', os.path.sep)
16  file_name = class_name + '.java'
17  return os.path.join(package_path, file_name)
18
19
20def KCamelToShouty(s):
21  """Convert |s| from kCamelCase or CamelCase to SHOUTY_CASE.
22
23  kFooBar -> FOO_BAR
24  FooBar -> FOO_BAR
25  FooBAR9 -> FOO_BAR9
26  FooBARBaz -> FOO_BAR_BAZ
27  """
28  if not re.match(r'^k?([A-Z][^A-Z]+|[A-Z0-9]+)+$', s):
29    return s
30  # Strip the leading k.
31  s = re.sub(r'^k', '', s)
32  # Treat "WebView" like one word.
33  s = re.sub(r'WebView', r'Webview', s)
34  # Add _ between title words and anything else.
35  s = re.sub(r'([^_])([A-Z][^A-Z_0-9]+)', r'\1_\2', s)
36  # Add _ between lower -> upper transitions.
37  s = re.sub(r'([^A-Z_0-9])([A-Z])', r'\1_\2', s)
38  return s.upper()
39
40
41class JavaString:
42  def __init__(self, name, value, comments):
43    self.name = KCamelToShouty(name)
44    self.value = value
45    self.comments = '\n'.join('    ' + x for x in comments)
46
47  def Format(self):
48    return '%s\n    public static final String %s = %s;' % (
49        self.comments, self.name, self.value)
50
51
52def ParseTemplateFile(lines):
53  package_re = re.compile(r'^package (.*);')
54  class_re = re.compile(r'.*class (.*) {')
55  package = ''
56  class_name = ''
57  for line in lines:
58    package_line = package_re.match(line)
59    if package_line:
60      package = package_line.groups()[0]
61    class_line = class_re.match(line)
62    if class_line:
63      class_name = class_line.groups()[0]
64      break
65  return package, class_name
66
67
68# TODO(crbug.com/937282): Work will be needed if we want to annotate specific
69# constants in the file to be parsed.
70class CppConstantParser:
71  """Parses C++ constants, retaining their comments.
72
73  The Delegate subclass is responsible for matching and extracting the
74  constant's variable name and value, as well as generating an object to
75  represent the Java representation of this value.
76  """
77  SINGLE_LINE_COMMENT_RE = re.compile(r'\s*(// [^\n]*)')
78
79  class Delegate:
80    def ExtractConstantName(self, line):
81      """Extracts a constant's name from line or None if not a match."""
82      raise NotImplementedError()
83
84    def ExtractValue(self, line):
85      """Extracts a constant's value from line or None if not a match."""
86      raise NotImplementedError()
87
88    def CreateJavaConstant(self, name, value, comments):
89      """Creates an object representing the Java analog of a C++ constant.
90
91      CppConstantParser will not interact with the object created by this
92      method. Instead, it will store this value in a list and return a list of
93      all objects from the Parse() method. In this way, the caller may define
94      whatever class suits their need.
95
96      Args:
97        name: the constant's variable name, as extracted by
98          ExtractConstantName()
99        value: the constant's value, as extracted by ExtractValue()
100        comments: the code comments describing this constant
101      """
102      raise NotImplementedError()
103
104  def __init__(self, delegate, lines):
105    self._delegate = delegate
106    self._lines = lines
107    self._in_variable = False
108    self._in_comment = False
109    self._package = ''
110    self._current_comments = []
111    self._current_name = ''
112    self._current_value = ''
113    self._constants = []
114
115  def _ExtractVariable(self, line):
116    match = StringFileParser.STRING_RE.match(line)
117    return match.group(1) if match else None
118
119  def _ExtractValue(self, line):
120    match = StringFileParser.VALUE_RE.search(line)
121    return match.group(1) if match else None
122
123  def _Reset(self):
124    self._current_comments = []
125    self._current_name = ''
126    self._current_value = ''
127    self._in_variable = False
128    self._in_comment = False
129
130  def _AppendConstant(self):
131    self._constants.append(
132        self._delegate.CreateJavaConstant(self._current_name,
133                                          self._current_value,
134                                          self._current_comments))
135    self._Reset()
136
137  def _ParseValue(self, line):
138    current_value = self._delegate.ExtractValue(line)
139    if current_value is not None:
140      self._current_value = current_value
141      self._AppendConstant()
142    else:
143      self._Reset()
144
145  def _ParseComment(self, line):
146    comment_line = CppConstantParser.SINGLE_LINE_COMMENT_RE.match(line)
147    if comment_line:
148      self._current_comments.append(comment_line.groups()[0])
149      self._in_comment = True
150      self._in_variable = True
151      return True
152    self._in_comment = False
153    return False
154
155  def _ParseVariable(self, line):
156    current_name = self._delegate.ExtractConstantName(line)
157    if current_name is not None:
158      self._current_name = current_name
159      current_value = self._delegate.ExtractValue(line)
160      if current_value is not None:
161        self._current_value = current_value
162        self._AppendConstant()
163      else:
164        self._in_variable = True
165      return True
166    self._in_variable = False
167    return False
168
169  def _ParseLine(self, line):
170    if not self._in_variable:
171      if not self._ParseVariable(line):
172        self._ParseComment(line)
173      return
174
175    if self._in_comment:
176      if self._ParseComment(line):
177        return
178      if not self._ParseVariable(line):
179        self._Reset()
180      return
181
182    if self._in_variable:
183      self._ParseValue(line)
184
185  def Parse(self):
186    """Returns a list of objects representing C++ constants.
187
188    Each object in the list was created by Delegate.CreateJavaValue().
189    """
190    for line in self._lines:
191      self._ParseLine(line)
192    return self._constants
193