From e630de2fc5738ad6f2299078cb0f362ee17b4c9c Mon Sep 17 00:00:00 2001
From: Rich Trott <rtrott@gmail.com>
Date: Fri, 9 Oct 2020 06:00:00 -0700
Subject: [PATCH] tools: refloat 7 Node.js patches to cpplint.py
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Cherry-pick 12c8b4d15471cb6211b39c3a2ca5b10fa4b9f12b
Original commit message:
    This commit is a suggestion for adding a rule for NULL usages in the
    code base. This will currently report a number of errors which could be
    ignored using // NOLINT (readability/null_usage)

    PR-URL: https://github.com/nodejs/node/pull/17373
    Reviewed-By: Jon Moss <me@jonathanmoss.me>
    Reviewed-By: Anna Henningsen <anna@addaleax.net>
    Reviewed-By: Timothy Gu <timothygu99@gmail.com>
    Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
    Reviewed-By: Michael Dawson <michael_dawson@ca.ibm.com>
    Reviewed-By: Sakthipriyan Vairamani <thechargingvolcano@gmail.com>
    Reviewed-By: Tobias Nießen <tniessen@tnie.de>

Refs: https://github.com/nodejs/node/commit/12c8b4d15471cb6211b39c3a2ca5b10fa4b9f12b

Cherry-pick fc81e801913de3e3f3c0c8e26c105f983a74e539
Original commit message:

    Update cpplint.py to check for inline headers when the corresponding
    header is already included.

    PR-URL: https://github.com/nodejs/node/pull/21521
    Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
    Reviewed-By: James M Snell <jasnell@gmail.com>

Refs: https://github.com/nodejs/node/commit/fc81e801913de3e3f3c0c8e26c105f983a74e539

Cherry-pick cbc3dd997eb90d629d1b9912b7a5a40eb82343df
Original commit message:

    src, tools: add check for left leaning pointers

    This commit adds a rule to cpplint to check that pointers in the code
    base lean to the left and not right, and also fixes the violations
    reported.

    PR-URL: https://github.com/nodejs/node/pull/21010
    Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
    Reviewed-By: Anna Henningsen <anna@addaleax.net>
    Reviewed-By: Ruben Bridgewater <ruben@bridgewater.de>
    Reviewed-By: James M Snell <jasnell@gmail.com>

Refs: https://github.com/nodejs/node/commit/cbc3dd997eb90d629d1b9912b7a5a40eb82343df

Cherry-pick 902998190a55d6915b881936f6dd5b6e9cca6ad8
Original commit message:

    tools: fix cpplint.py header rules

    THIS COMMIT SHOULD GO WITH THE NEXT. IT WILL FIND NEW LINT.

    PR-URL: https://github.com/nodejs/node/pull/26306
    Reviewed-By: Gireesh Punathil <gpunathi@in.ibm.com>

Refs: https://github.com/nodejs/node/commit/902998190a55d6915b881936f6dd5b6e9cca6ad8

Cherry-pick 0a25ace9c35b62ece4d32fd90b326d8063265109
Original commit message:

    tools: move cpplint configuration to .cpplint

    PR-URL: https://github.com/nodejs/node/pull/27098
    Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
    Reviewed-By: Daniel Bevenius <daniel.bevenius@gmail.com>

Refs: https://github.com/nodejs/node/commit/0a25ace9c35b62ece4d32fd90b326d8063265109

Cherry-pick afa9a7206c26a29a2af226696c145c924a6d3754
Original commit message:

    tools: refloat update link to google styleguide for cpplint

    This commit updates two old links to Google's C++ styleguide which
    currently result in a 404 when accessed.

    PR-URL: https://github.com/nodejs/node/pull/30876
    Reviewed-By: Michaël Zasso <targos@protonmail.com>
    Reviewed-By: David Carlier <devnexen@gmail.com>
    Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
    Reviewed-By: Richard Lau <riclau@uk.ibm.com>
    Reviewed-By: Rich Trott <rtrott@gmail.com>

Refs: https://github.com/nodejs/node/commit/afa9a7206c26a29a2af226696c145c924a6d3754

Cherry-pick e23bf8f771aa0bd60e25ff079985fc29b5846403
Original commit message:

    tools,src: refloat forbid usage of v8::Persistent

    `v8::Persistent` comes with the surprising catch that it requires
    manual cleanup. `v8::Global` doesn’t, making it easier to use,
    and additionally provides move semantics. New code should always
    use `v8::Global`.

    PR-URL: https://github.com/nodejs/node/pull/31018
    Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
    Reviewed-By: Richard Lau <riclau@uk.ibm.com>
    Reviewed-By: James M Snell <jasnell@gmail.com>
    Reviewed-By: David Carlier <devnexen@gmail.com>
    Reviewed-By: Rich Trott <rtrott@gmail.com>
    Reviewed-By: Gus Caplan <me@gus.host>
    Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com>
    Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl>
    Reviewed-By: Stephen Belanger <admin@stephenbelanger.com>

PR-URL: https://github.com/nodejs/node/pull/35569
Reviewed-By: Richard Lau <rlau@redhat.com>
Reviewed-By: Daijiro Wachi <daijiro.wachi@gmail.com>
Reviewed-By: Jiawen Geng <technicalcute@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/35719
Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/35866

PR-URL: https://github.com/nodejs/node/pull/36213
Reviewed-By: Franziska Hinkelmann <franziska.hinkelmann@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/36235
Reviewed-By: Luigi Pinca <luigipinca@gmail.com>

PR-URL: https://github.com/nodejs/node/pull/36324
Reviewed-By: Beth Griggs <bgriggs@redhat.com>

PR-URL: https://github.com/nodejs/node/pull/38851
Reviewed-By: Khaidi Chu <i@2333.moe>

PR-URL: https://github.com/nodejs/node/pull/42416
Reviewed-By: Mestery <mestery@protonmail.com>
Reviewed-By: Darshan Sen <raisinten@gmail.com>
---
 tools/cpplint.py | 121 ++++++++++++++++++++++++++++++++++++++++++-----
 1 file changed, 109 insertions(+), 12 deletions(-)

diff --git a/tools/cpplint.py b/tools/cpplint.py
index 6b78b308c95..06fc45abf1a 100755
--- a/tools/cpplint.py
+++ b/tools/cpplint.py
@@ -300,6 +300,7 @@
     'build/include',
     'build/include_subdir',
     'build/include_alpha',
+    'build/include_inline',
     'build/include_order',
     'build/include_what_you_use',
     'build/namespaces_headers',
@@ -315,11 +316,13 @@
     'readability/constructors',
     'readability/fn_size',
     'readability/inheritance',
+    'readability/pointer_notation',
     'readability/multiline_comment',
     'readability/multiline_string',
     'readability/namespace',
     'readability/nolint',
     'readability/nul',
+    'readability/null_usage',
     'readability/strings',
     'readability/todo',
     'readability/utf8',
@@ -339,6 +342,7 @@
     'runtime/string',
     'runtime/threadsafe_fn',
     'runtime/vlog',
+    'runtime/v8_persistent',
     'whitespace/blank_line',
     'whitespace/braces',
     'whitespace/comma',
@@ -847,6 +851,14 @@
   'Missing space after ,': r's/,\([^ ]\)/, \1/g',
 }
 
+_NULL_TOKEN_PATTERN = re.compile(r'\bNULL\b')
+
+_V8_PERSISTENT_PATTERN = re.compile(r'\bv8::Persistent\b')
+
+_RIGHT_LEANING_POINTER_PATTERN = re.compile(r'[^=|(,\s><);&?:}]'
+                                            r'(?<!(sizeof|return))'
+                                            r'\s\*[a-zA-Z_][0-9a-zA-Z_]*')
+
 _regexp_compile_cache = {}
 
 # {str, set(int)}: a map from error categories to sets of linenumbers
@@ -1087,10 +1099,11 @@ class _IncludeState(object):
   # needs to move backwards, CheckNextIncludeOrder will raise an error.
   _INITIAL_SECTION = 0
   _MY_H_SECTION = 1
-  _C_SECTION = 2
-  _CPP_SECTION = 3
-  _OTHER_SYS_SECTION = 4
-  _OTHER_H_SECTION = 5
+  _OTHER_H_SECTION = 2
+  _OTHER_SYS_SECTION = 3
+  _C_SECTION = 4
+  _CPP_SECTION = 5
+
 
   _TYPE_NAMES = {
       _C_SYS_HEADER: 'C system header',
@@ -2527,6 +2540,21 @@ def CheckForBadCharacters(filename, lines, error):
       error(filename, linenum, 'readability/nul', 5, 'Line contains NUL byte.')
 
 
+def CheckInlineHeader(filename, include_state, error):
+  """Logs an error if both a header and its inline variant are included."""
+
+  all_headers = dict(item for sublist in include_state.include_list
+                     for item in sublist)
+  bad_headers = set('%s.h' % name[:-6] for name in all_headers.keys()
+                    if name.endswith('-inl.h'))
+  bad_headers &= set(all_headers.keys())
+
+  for name in bad_headers:
+    err =  '%s includes both %s and %s-inl.h' % (filename, name, name)
+    linenum = all_headers[name]
+    error(filename, linenum, 'build/include_inline', 5, err)
+
+
 def CheckForNewlineAtEOF(filename, lines, error):
   """Logs an error if there is no newline char at the end of the file.
 
@@ -3550,7 +3578,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
   """Reports for long function bodies.
 
   For an overview why this is done, see:
-  https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
+  https://google.github.io/styleguide/cppguide.html#Write_Short_Functions
 
   Uses a simplistic algorithm assuming other style guidelines
   (especially spacing) are followed.
@@ -4777,6 +4805,71 @@ def CheckAltTokens(filename, clean_lines, linenum, error):
           'Use operator %s instead of %s' % (
               _ALT_TOKEN_REPLACEMENT[match.group(1)], match.group(1)))
 
+def CheckNullTokens(filename, clean_lines, linenum, error):
+  """Check NULL usage.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Avoid preprocessor lines
+  if Match(r'^\s*#', line):
+    return
+
+  if line.find('/*') >= 0 or line.find('*/') >= 0:
+    return
+
+  for match in _NULL_TOKEN_PATTERN.finditer(line):
+    error(filename, linenum, 'readability/null_usage', 2,
+          'Use nullptr instead of NULL')
+
+def CheckV8PersistentTokens(filename, clean_lines, linenum, error):
+  """Check v8::Persistent usage.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Avoid preprocessor lines
+  if Match(r'^\s*#', line):
+    return
+
+  if line.find('/*') >= 0 or line.find('*/') >= 0:
+    return
+
+  for match in _V8_PERSISTENT_PATTERN.finditer(line):
+    error(filename, linenum, 'runtime/v8_persistent', 2,
+          'Use v8::Global instead of v8::Persistent')
+
+def CheckLeftLeaningPointer(filename, clean_lines, linenum, error):
+  """Check for left-leaning pointer placement.
+
+  Args:
+    filename: The name of the current file.
+    clean_lines: A CleansedLines instance containing the file.
+    linenum: The number of the line to check.
+    error: The function to call with any errors found.
+  """
+  line = clean_lines.elided[linenum]
+
+  # Avoid preprocessor lines
+  if Match(r'^\s*#', line):
+    return
+
+  if '/*' in line or '*/' in line:
+    return
+
+  for match in _RIGHT_LEANING_POINTER_PATTERN.finditer(line):
+    error(filename, linenum, 'readability/pointer_notation', 2,
+          'Use left leaning pointer instead of right leaning')
 
 def GetLineWidth(line):
   """Determines the width of the line in column positions.
@@ -4931,6 +5024,9 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state,
   CheckSpacingForFunctionCall(filename, clean_lines, linenum, error)
   CheckCheck(filename, clean_lines, linenum, error)
   CheckAltTokens(filename, clean_lines, linenum, error)
+  CheckNullTokens(filename, clean_lines, linenum, error)
+  CheckV8PersistentTokens(filename, clean_lines, linenum, error)
+  CheckLeftLeaningPointer(filename, clean_lines, linenum, error)
   classinfo = nesting_state.InnermostClass()
   if classinfo:
     CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error)
@@ -5118,11 +5214,10 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
       include_state.include_list[-1].append((include, linenum))
 
       # We want to ensure that headers appear in the right order:
-      # 1) for foo.cc, foo.h  (preferred location)
-      # 2) c system files
-      # 3) cpp system files
-      # 4) for foo.cc, foo.h  (deprecated location)
-      # 5) other google headers
+      # 1) for foo.cc, foo.h
+      # 2) other project headers
+      # 3) c system files
+      # 4) cpp system files
       #
       # We classify each include statement as one of those 5 types
       # using a number of techniques. The include_state object keeps
@@ -5385,7 +5480,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
       and line[-1] != '\\'):
     error(filename, linenum, 'build/namespaces_headers', 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.')
 
 
@@ -6507,6 +6602,8 @@ def ProcessFileData(filename, file_extension, lines, error,
 
   CheckForNewlineAtEOF(filename, lines, error)
 
+  CheckInlineHeader(filename, include_state, error)
+
 def ProcessConfigOverrides(filename):
   """ Loads the configuration files and processes the config overrides.
 
@@ -6525,7 +6622,7 @@ def ProcessConfigOverrides(filename):
     if not base_name:
       break  # Reached the root directory.
 
-    cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
+    cfg_file = os.path.join(abs_path, ".cpplint")
     abs_filename = abs_path
     if not os.path.isfile(cfg_file):
       continue