tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

java_cpp_utils.py (5786B)


      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 
      5 import os
      6 import re
      7 import sys
      8 
      9 
     10 def GetScriptName():
     11  return os.path.basename(os.path.abspath(sys.argv[0]))
     12 
     13 
     14 def 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 
     20 def 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 
     41 class 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 
     52 def 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/40616187): Work will be needed if we want to annotate specific
     69 # constants in the file to be parsed.
     70 class 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