Revert "cpplint: Pull in upstream changes"

This reverts commit f7e1e10db5f949dead75f907934aba0a4dfd8b3d.

Reason for revert: breaks V8 presubmit, e.g. https://ci.chromium.org/p/v8/builders/luci.v8.try/v8_presubmit/b8943030202460843984

Original change's description:
> cpplint: Pull in upstream changes
> 
> The changes include:
> - root flag now can process non-subdirectories
> -- https://github.com/google/styleguide/commit/e7ddd2af622475b0c5e0f587d69fb061d2c10c46
> 
> - root flag can be configured with CPPLINT.cfg
> -- https://github.com/google/styleguide/commit/2322e4ffaa19f4c55e5679102318ce67454fb7ed
> 
> - root setting is relative to the CPPLINT.cfg file
> -- https://github.com/google/styleguide/commit/8a87a46cc7f8d6cca5c0203ddba5d81149db7695
> 
> - Cleans up header file detection for hpp and hxx
> 
> - Adds quite mode
> 
> Bug: 852898
> 
> Change-Id: Id44bbfadc913cc27192049ab9a222f22d0deab5d
> Reviewed-on: https://chromium-review.googlesource.com/1108381
> Commit-Queue: Amin Hassani <ahassani@chromium.org>
> Reviewed-by: Aaron Gable <agable@chromium.org>

TBR=agable@chromium.org,ahassani@chromium.org

Change-Id: I3d380ecf8cb80000d7f7dcc0a2c75bb8a12d2a51
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Bug: 852898
Reviewed-on: https://chromium-review.googlesource.com/1111797
Reviewed-by: Sergiy Byelozyorov <sergiyb@chromium.org>
Commit-Queue: Sergiy Byelozyorov <sergiyb@chromium.org>
diff --git a/cpplint.py b/cpplint.py
index f919562..42e3da3 100755
--- a/cpplint.py
+++ b/cpplint.py
@@ -53,19 +53,12 @@
 import string
 import sys
 import unicodedata
-import sysconfig
-
-try:
-  xrange          # Python 2
-except NameError:
-  xrange = range  # Python 3
 
 
 _USAGE = """
 Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
                    [--counting=total|toplevel|detailed] [--root=subdir]
-                   [--linelength=digits] [--headers=x,y,...]
-                   [--quiet]
+                   [--linelength=digits]
         <file> [file] ...
 
   The style guidelines this tries to follow are those in
@@ -92,9 +85,6 @@
     verbose=#
       Specify a number 0-5 to restrict errors to certain verbosity levels.
 
-    quiet
-      Don't print anything if no errors are found.
-
     filter=-x,+y,...
       Specify a comma-separated list of category-filters to apply: only
       error messages whose category names pass the filters will be printed.
@@ -126,13 +116,12 @@
       ignored.
 
       Examples:
-        Assuming that top/src/.git exists (and cwd=top/src), the header guard
-        CPP variables for top/src/chrome/browser/ui/browser.h are:
+        Assuming that src/.git exists, the header guard CPP variables for
+        src/chrome/browser/ui/browser.h are:
 
         No flag => CHROME_BROWSER_UI_BROWSER_H_
         --root=chrome => BROWSER_UI_BROWSER_H_
         --root=chrome/browser => UI_BROWSER_H_
-        --root=.. => SRC_CHROME_BROWSER_UI_BROWSER_H_
 
     linelength=digits
       This is the allowed line length for the project. The default value is
@@ -147,14 +136,6 @@
       Examples:
         --extensions=hpp,cpp
 
-    headers=x,y,...
-      The header extensions that cpplint will treat as .h in checks. Values are
-      automatically added to --extensions list.
-
-      Examples:
-        --headers=hpp,hxx
-        --headers=hpp
-
     cpplint.py supports per-directory configurations specified in CPPLINT.cfg
     files. CPPLINT.cfg file can contain a number of key=value pairs.
     Currently the following options are supported:
@@ -163,8 +144,6 @@
       filter=+filter1,-filter2,...
       exclude_files=regex
       linelength=80
-      root=subdir
-      headers=x,y,...
 
     "set noparent" option prevents cpplint from traversing directory tree
     upwards looking for more .cfg files in parent directories. This option
@@ -180,12 +159,6 @@
 
     "linelength" allows to specify the allowed line length for the project.
 
-    The "root" option is similar in function to the --root flag (see example
-    above). Paths are relative to the directory of the CPPLINT.cfg.
-
-    The "headers" option is similar in function to the --headers flag
-    (see example above).
-
     CPPLINT.cfg has an effect on files in the same directory and all
     sub-directories, unless overridden by a nested configuration file.
 
@@ -552,7 +525,10 @@
 # The root directory used for deriving header guard CPP variable.
 # This is set by --root flag.
 _root = None
-_root_debug = False
+
+# The project root directory. Used for deriving header guard CPP variable.
+# This is set by --project_root flag. Must be an absolute path.
+_project_root = None
 
 # The allowed line length of files.
 # This is set by --linelength flag.
@@ -562,25 +538,10 @@
 # This is set by --extensions flag.
 _valid_extensions = set(['cc', 'h', 'cpp', 'cu', 'cuh'])
 
-# Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
-# This is set by --headers flag.
-_hpp_headers = set(['h'])
-
 # {str, bool}: a map from error categories to booleans which indicate if the
 # category should be suppressed for every line.
 _global_error_suppressions = {}
 
-def ProcessHppHeadersOption(val):
-  global _hpp_headers
-  try:
-    _hpp_headers = set(val.split(','))
-    # Automatically append to extensions list so it does not have to be set 2 times
-    _valid_extensions.update(_hpp_headers)
-  except ValueError:
-    PrintUsage('Header extensions must be comma separated list.')
-
-def IsHeaderExtension(file_extension):
-  return file_extension in _hpp_headers
 
 def ParseNolintSuppressions(filename, raw_line, linenum, error):
   """Updates the global list of line error-suppressions.
@@ -873,7 +834,6 @@
     self._filters_backup = self.filters[:]
     self.counting = 'total'  # In what way are we counting errors?
     self.errors_by_category = {}  # string to int dict storing error counts
-    self.quiet = False  # Suppress non-error messagess?
 
     # output format:
     # "emacs" - format that emacs can parse (default)
@@ -884,12 +844,6 @@
     """Sets the output format for errors."""
     self.output_format = output_format
 
-  def SetQuiet(self, quiet):
-    """Sets the module's quiet settings, and returns the previous setting."""
-    last_quiet = self.quiet
-    self.quiet = quiet
-    return last_quiet
-
   def SetVerboseLevel(self, level):
     """Sets the module's verbosity, and returns the previous setting."""
     last_verbose_level = self.verbose_level
@@ -957,7 +911,7 @@
     for category, count in self.errors_by_category.iteritems():
       sys.stderr.write('Category \'%s\' errors found: %d\n' %
                        (category, count))
-    sys.stdout.write('Total errors found: %d\n' % self.error_count)
+    sys.stderr.write('Total errors found: %d\n' % self.error_count)
 
 _cpplint_state = _CppLintState()
 
@@ -971,14 +925,6 @@
   """Sets the module's output format."""
   _cpplint_state.SetOutputFormat(output_format)
 
-def _Quiet():
-  """Return's the module's quiet setting."""
-  return _cpplint_state.quiet
-
-def _SetQuiet(quiet):
-  """Set the module's quiet status, and return previous setting."""
-  return _cpplint_state.SetQuiet(quiet)
-
 
 def _VerboseLevel():
   """Returns the module's verbosity setting."""
@@ -1125,6 +1071,10 @@
     if os.path.exists(fullname):
       project_dir = os.path.dirname(fullname)
 
+      if _project_root:
+        prefix = os.path.commonprefix([_project_root, project_dir])
+        return fullname[len(prefix) + 1:]
+
       if os.path.exists(os.path.join(project_dir, ".svn")):
         # If there's a .svn file in the current directory, we recursively look
         # up the directory tree for the top of the SVN checkout
@@ -1139,13 +1089,12 @@
 
       # Not SVN <= 1.6? Try to find a git, hg, or svn top level directory by
       # searching up from the current path.
-      root_dir = current_dir = os.path.dirname(fullname)
-      while current_dir != os.path.dirname(current_dir):
-        if (os.path.exists(os.path.join(current_dir, ".git")) or
-            os.path.exists(os.path.join(current_dir, ".hg")) or
-            os.path.exists(os.path.join(current_dir, ".svn"))):
-          root_dir = current_dir
-        current_dir = os.path.dirname(current_dir)
+      root_dir = os.path.dirname(fullname)
+      while (root_dir != os.path.dirname(root_dir) and
+             not os.path.exists(os.path.join(root_dir, ".git")) and
+             not os.path.exists(os.path.join(root_dir, ".hg")) and
+             not os.path.exists(os.path.join(root_dir, ".svn"))):
+        root_dir = os.path.dirname(root_dir)
 
       if (os.path.exists(os.path.join(root_dir, ".git")) or
           os.path.exists(os.path.join(root_dir, ".hg")) or
@@ -1240,8 +1189,8 @@
   if _ShouldPrintError(category, confidence, linenum):
     _cpplint_state.IncrementErrorCount(category)
     if _cpplint_state.output_format == 'vs7':
-      sys.stderr.write('%s(%s): error cpplint: [%s] %s [%d]\n' % (
-          filename, linenum, category, message, confidence))
+      sys.stderr.write('%s(%s):  %s  [%s] [%d]\n' % (
+          filename, linenum, message, category, confidence))
     elif _cpplint_state.output_format == 'eclipse':
       sys.stderr.write('%s:%s: warning: %s  [%s] [%d]\n' % (
           filename, linenum, message, category, confidence))
@@ -1783,30 +1732,6 @@
   else:
     return 0
 
-def PathSplitToList(path):
-  """Returns the path split into a list by the separator.
-
-  Args:
-    path: An absolute or relative path (e.g. '/a/b/c/' or '../a')
-
-  Returns:
-    A list of path components (e.g. ['a', 'b', 'c]).
-  """
-  lst = []
-  while True:
-    (head, tail) = os.path.split(path)
-    if head == path: # absolute paths end
-      lst.append(head)
-      break
-    if tail == path: # relative paths end
-      lst.append(tail)
-      break
-
-    path = head
-    lst.append(tail)
-
-  lst.reverse()
-  return lst
 
 def GetHeaderGuardCPPVariable(filename):
   """Returns the CPP variable that should be used as a header guard.
@@ -1829,58 +1754,8 @@
 
   fileinfo = FileInfo(filename)
   file_path_from_root = fileinfo.RepositoryName()
-
-  def FixupPathFromRoot():
-    if _root_debug:
-      sys.stderr.write("\n_root fixup, _root = '%s', repository name = '%s'\n"
-          %(_root, fileinfo.RepositoryName()))
-
-    # Process the file path with the --root flag if it was set.
-    if not _root:
-      if _root_debug:
-        sys.stderr.write("_root unspecified\n")
-      return file_path_from_root
-
-    def StripListPrefix(lst, prefix):
-      # f(['x', 'y'], ['w, z']) -> None  (not a valid prefix)
-      if lst[:len(prefix)] != prefix:
-        return None
-      # f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd']
-      return lst[(len(prefix)):]
-
-    # root behavior:
-    #   --root=subdir , lstrips subdir from the header guard
-    maybe_path = StripListPrefix(PathSplitToList(file_path_from_root),
-                                 PathSplitToList(_root))
-
-    if _root_debug:
-      sys.stderr.write(("_root lstrip (maybe_path=%s, file_path_from_root=%s," +
-          " _root=%s)\n") %(maybe_path, file_path_from_root, _root))
-
-    if maybe_path:
-      return os.path.join(*maybe_path)
-
-    #   --root=.. , will prepend the outer directory to the header guard
-    full_path = fileinfo.FullName()
-    root_abspath = os.path.abspath(_root)
-
-    maybe_path = StripListPrefix(PathSplitToList(full_path),
-                                 PathSplitToList(root_abspath))
-
-    if _root_debug:
-      sys.stderr.write(("_root prepend (maybe_path=%s, full_path=%s, " +
-          "root_abspath=%s)\n") %(maybe_path, full_path, root_abspath))
-
-    if maybe_path:
-      return os.path.join(*maybe_path)
-
-    if _root_debug:
-      sys.stderr.write("_root ignore, returning %s\n" %(file_path_from_root))
-
-    #   --root=FAKE_DIR is ignored
-    return file_path_from_root
-
-  file_path_from_root = FixupPathFromRoot()
+  if _root:
+    file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root)
   return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
 
 
@@ -3989,14 +3864,6 @@
       # outputting warnings for the matching closing brace, if there are
       # nested blocks with trailing semicolons, we will get the error
       # messages in reversed order.
-
-      # We need to check the line forward for NOLINT
-      raw_lines = clean_lines.raw_lines
-      ParseNolintSuppressions(filename, raw_lines[endlinenum-1], endlinenum-1,
-                              error)
-      ParseNolintSuppressions(filename, raw_lines[endlinenum], endlinenum,
-                              error)
-
       error(filename, endlinenum, 'readability/braces', 4,
             "You don't need a ; after a }")
 
@@ -4294,16 +4161,6 @@
       if unicodedata.east_asian_width(uc) in ('W', 'F'):
         width += 2
       elif not unicodedata.combining(uc):
-        # Issue 337
-        # https://mail.python.org/pipermail/python-list/2012-August/628809.html
-        if (sys.version_info.major, sys.version_info.minor) <= (3, 2):
-          # https://github.com/python/cpython/blob/2.7/Include/unicodeobject.h#L81
-          is_wide_build = sysconfig.get_config_var("Py_UNICODE_SIZE") >= 4
-          # https://github.com/python/cpython/blob/2.7/Objects/unicodeobject.c#L564
-          is_low_surrogate = 0xDC00 <= ord(uc) <= 0xDFFF
-          if not is_wide_build and is_low_surrogate:
-            width -= 1
-
         width += 1
     return width
   else:
@@ -4377,7 +4234,7 @@
 
   # Check if the line is a header guard.
   is_header_guard = False
-  if IsHeaderExtension(file_extension):
+  if file_extension == 'h':
     cppvar = GetHeaderGuardCPPVariable(filename)
     if (line.startswith('#ifndef %s' % cppvar) or
         line.startswith('#define %s' % cppvar) or
@@ -4726,7 +4583,7 @@
   CheckGlobalStatic(filename, clean_lines, linenum, error)
   CheckPrintf(filename, clean_lines, linenum, error)
 
-  if IsHeaderExtension(file_extension):
+  if file_extension == 'h':
     # TODO(unknown): check that 1-arg constructors are explicit.
     #                How to tell it's a constructor?
     #                (handled in CheckForNonStandardConstructs for now)
@@ -4833,12 +4690,12 @@
   # Check for use of unnamed namespaces in header files.  Registration
   # macros are typically OK, so we allow use of "namespace {" on lines
   # that end with backslashes.
-  if (IsHeaderExtension(file_extension)
+  if (file_extension == 'h'
       and Search(r'\bnamespace\s*{', line)
       and line[-1] != '\\'):
     error(filename, linenum, 'build/namespaces', 4,
           'Do not use unnamed namespaces in header files.  See '
-          'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
+          'https://google.github.io/styleguide/cppguide.html#Namespaces'
           ' for more information.')
 
 
@@ -5923,7 +5780,7 @@
   RemoveMultiLineComments(filename, lines, error)
   clean_lines = CleansedLines(lines)
 
-  if IsHeaderExtension(file_extension):
+  if file_extension == 'h':
     CheckForHeaderGuard(filename, clean_lines, error)
 
   for line in xrange(clean_lines.NumLines()):
@@ -5992,9 +5849,6 @@
             if base_name:
               pattern = re.compile(val)
               if pattern.match(base_name):
-                if _cpplint_state.quiet:
-                  # Suppress "Ignoring file" warning when using --quiet.
-                  return False
                 sys.stderr.write('Ignoring "%s": file excluded by "%s". '
                                  'File path component "%s" matches '
                                  'pattern "%s"\n' %
@@ -6006,12 +5860,6 @@
                 _line_length = int(val)
             except ValueError:
                 sys.stderr.write('Line length must be numeric.')
-          elif name == 'root':
-            global _root
-            # root directories are specified relative to CPPLINT.cfg dir.
-            _root = os.path.join(os.path.dirname(cfg_file), val)
-          elif name == 'headers':
-            ProcessHppHeadersOption(val)
           else:
             sys.stderr.write(
                 'Invalid configuration option (%s) in file %s\n' %
@@ -6046,7 +5894,6 @@
 
   _SetVerboseLevel(vlevel)
   _BackupFilters()
-  old_errors = _cpplint_state.error_count
 
   if not ProcessConfigOverrides(filename):
     _RestoreFilters()
@@ -6115,10 +5962,7 @@
         Error(filename, linenum, 'whitespace/newline', 1,
               'Unexpected \\r (^M) found; better to use only \\n')
 
-  # Suppress printing anything if --quiet was passed unless the error
-  # count has increased after processing this file.
-  if not _cpplint_state.quiet or old_errors != _cpplint_state.error_count:
-    sys.stdout.write('Done processing %s\n' % filename)
+  sys.stderr.write('Done processing %s\n' % filename)
   _RestoreFilters()
 
 
@@ -6162,15 +6006,13 @@
                                                  'root=',
                                                  'linelength=',
                                                  'extensions=',
-                                                 'headers=',
-                                                 'quiet'])
+                                                 'project_root='])
   except getopt.GetoptError:
     PrintUsage('Invalid arguments.')
 
   verbosity = _VerboseLevel()
   output_format = _OutputFormat()
   filters = ''
-  quiet = _Quiet()
   counting_style = ''
 
   for (opt, val) in opts:
@@ -6180,8 +6022,6 @@
       if val not in ('emacs', 'vs7', 'eclipse'):
         PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
       output_format = val
-    elif opt == '--quiet':
-      quiet = True
     elif opt == '--verbose':
       verbosity = int(val)
     elif opt == '--filter':
@@ -6195,6 +6035,11 @@
     elif opt == '--root':
       global _root
       _root = val
+    elif opt == '--project_root':
+      global _project_root
+      _project_root = val
+      if not os.path.isabs(_project_root):
+        PrintUsage('Project root must be an absolute path.')
     elif opt == '--linelength':
       global _line_length
       try:
@@ -6207,14 +6052,11 @@
           _valid_extensions = set(val.split(','))
       except ValueError:
           PrintUsage('Extensions must be comma separated list.')
-    elif opt == '--headers':
-      ProcessHppHeadersOption(val)
 
   if not filenames:
     PrintUsage('No files were specified.')
 
   _SetOutputFormat(output_format)
-  _SetQuiet(quiet)
   _SetVerboseLevel(verbosity)
   _SetFilters(filters)
   _SetCountingStyle(counting_style)
@@ -6235,9 +6077,7 @@
   _cpplint_state.ResetErrorCounts()
   for filename in filenames:
     ProcessFile(filename, _cpplint_state.verbose_level)
-  # If --quiet is passed, suppress printing error count unless there are errors.
-  if not _cpplint_state.quiet or _cpplint_state.error_count > 0:
-    _cpplint_state.PrintErrorCounts()
+  _cpplint_state.PrintErrorCounts()
 
   sys.exit(_cpplint_state.error_count > 0)