mirror of
https://github.com/nodejs/node.git
synced 2025-08-15 13:48:44 +02:00
tools: bump cpplint.py to 1.4.6
Refs: https://github.com/cpplint/cpplint/releases/tag/1.4.6 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>
This commit is contained in:
parent
900f28aa6d
commit
7dd786bb89
1 changed files with 106 additions and 159 deletions
265
tools/cpplint.py
vendored
265
tools/cpplint.py
vendored
|
@ -59,7 +59,7 @@ import xml.etree.ElementTree
|
|||
# if empty, use defaults
|
||||
_valid_extensions = set([])
|
||||
|
||||
__VERSION__ = '1.4.4'
|
||||
__VERSION__ = '1.4.6'
|
||||
|
||||
try:
|
||||
xrange # Python 2
|
||||
|
@ -280,7 +280,6 @@ _ERROR_CATEGORIES = [
|
|||
'build/include',
|
||||
'build/include_subdir',
|
||||
'build/include_alpha',
|
||||
'build/include_inline',
|
||||
'build/include_order',
|
||||
'build/include_what_you_use',
|
||||
'build/namespaces_literals',
|
||||
|
@ -295,13 +294,11 @@ _ERROR_CATEGORIES = [
|
|||
'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',
|
||||
|
@ -321,7 +318,6 @@ _ERROR_CATEGORIES = [
|
|||
'runtime/string',
|
||||
'runtime/threadsafe_fn',
|
||||
'runtime/vlog',
|
||||
'runtime/v8_persistent',
|
||||
'whitespace/blank_line',
|
||||
'whitespace/braces',
|
||||
'whitespace/comma',
|
||||
|
@ -626,14 +622,6 @@ _SEARCH_C_FILE = re.compile(r'\b(?:LINT_C_FILE|'
|
|||
# Match string that indicates we're working on a Linux Kernel file.
|
||||
_SEARCH_KERNEL_FILE = re.compile(r'\b(?:LINT_KERNEL_FILE)')
|
||||
|
||||
_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
|
||||
|
@ -653,7 +641,7 @@ _repository = None
|
|||
# Files to exclude from linting. This is set by the --exclude flag.
|
||||
_excludes = None
|
||||
|
||||
# Whether to suppress PrintInfo messages
|
||||
# Whether to supress PrintInfo messages
|
||||
_quiet = False
|
||||
|
||||
# The allowed line length of files.
|
||||
|
@ -690,7 +678,7 @@ def unicode_escape_decode(x):
|
|||
|
||||
# Treat all headers starting with 'h' equally: .h, .hpp, .hxx etc.
|
||||
# This is set by --headers flag.
|
||||
_hpp_headers = set(['h', 'hh', 'hpp', 'hxx', 'h++', 'cuh'])
|
||||
_hpp_headers = set([])
|
||||
|
||||
# {str, bool}: a map from error categories to booleans which indicate if the
|
||||
# category should be suppressed for every line.
|
||||
|
@ -699,30 +687,39 @@ _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)
|
||||
_hpp_headers = {ext.strip() for ext in val.split(',')}
|
||||
except ValueError:
|
||||
PrintUsage('Header extensions must be comma separated list.')
|
||||
|
||||
def IsHeaderExtension(file_extension):
|
||||
return file_extension in _hpp_headers
|
||||
return file_extension in GetHeaderExtensions()
|
||||
|
||||
def GetHeaderExtensions():
|
||||
return _hpp_headers or ['h']
|
||||
if _hpp_headers:
|
||||
return _hpp_headers
|
||||
if _valid_extensions:
|
||||
return {h for h in _valid_extensions if 'h' in h}
|
||||
return set(['h', 'hh', 'hpp', 'hxx', 'h++', 'cuh'])
|
||||
|
||||
# The allowed extensions for file names
|
||||
# This is set by --extensions flag
|
||||
def GetAllExtensions():
|
||||
if not _valid_extensions:
|
||||
return GetHeaderExtensions().union(set(['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']))
|
||||
return _valid_extensions
|
||||
return GetHeaderExtensions().union(_valid_extensions or set(
|
||||
['c', 'cc', 'cpp', 'cxx', 'c++', 'cu']))
|
||||
|
||||
def ProcessExtensionsOption(val):
|
||||
global _valid_extensions
|
||||
try:
|
||||
extensions = [ext.strip() for ext in val.split(',')]
|
||||
_valid_extensions = set(extensions)
|
||||
except ValueError:
|
||||
PrintUsage('Extensions should be a comma-separated list of values;'
|
||||
'for example: extensions=hpp,cpp\n'
|
||||
'This could not be parsed: "%s"' % (val,))
|
||||
|
||||
def GetNonHeaderExtensions():
|
||||
return GetAllExtensions().difference(GetHeaderExtensions())
|
||||
|
||||
|
||||
|
||||
def ParseNolintSuppressions(filename, raw_line, linenum, error):
|
||||
"""Updates the global list of line error-suppressions.
|
||||
|
||||
|
@ -853,9 +850,9 @@ class _IncludeState(object):
|
|||
# needs to move backwards, CheckNextIncludeOrder will raise an error.
|
||||
_INITIAL_SECTION = 0
|
||||
_MY_H_SECTION = 1
|
||||
_OTHER_H_SECTION = 2
|
||||
_C_SECTION = 3
|
||||
_CPP_SECTION = 4
|
||||
_C_SECTION = 2
|
||||
_CPP_SECTION = 3
|
||||
_OTHER_H_SECTION = 4
|
||||
|
||||
_TYPE_NAMES = {
|
||||
_C_SYS_HEADER: 'C system header',
|
||||
|
@ -867,9 +864,9 @@ class _IncludeState(object):
|
|||
_SECTION_NAMES = {
|
||||
_INITIAL_SECTION: "... nothing. (This can't be an error.)",
|
||||
_MY_H_SECTION: 'a header this file implements',
|
||||
_OTHER_H_SECTION: 'other header',
|
||||
_C_SECTION: 'C system header',
|
||||
_CPP_SECTION: 'C++ system header',
|
||||
_OTHER_H_SECTION: 'other header',
|
||||
}
|
||||
|
||||
def __init__(self):
|
||||
|
@ -1129,9 +1126,9 @@ class _CppLintState(object):
|
|||
num_failures = len(self._junit_failures)
|
||||
|
||||
testsuite = xml.etree.ElementTree.Element('testsuite')
|
||||
testsuite.attrib['name'] = 'cpplint'
|
||||
testsuite.attrib['errors'] = str(num_errors)
|
||||
testsuite.attrib['failures'] = str(num_failures)
|
||||
testsuite.attrib['name'] = 'cpplint'
|
||||
|
||||
if num_errors == 0 and num_failures == 0:
|
||||
testsuite.attrib['tests'] = str(1)
|
||||
|
@ -1325,7 +1322,7 @@ class FileInfo(object):
|
|||
If we have a real absolute path name here we can try to do something smart:
|
||||
detecting the root of the checkout and truncating /path/to/checkout from
|
||||
the name so that we get header guards that don't include things like
|
||||
"C:\Documents and Settings\..." or "/home/username/..." in them and thus
|
||||
"C:\\Documents and Settings\\..." or "/home/username/..." in them and thus
|
||||
people on different computers who have checked the source out to different
|
||||
locations won't see bogus errors.
|
||||
"""
|
||||
|
@ -2265,21 +2262,6 @@ 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.
|
||||
|
||||
|
@ -3171,7 +3153,8 @@ def CheckForNonStandardConstructs(filename, clean_lines, linenum,
|
|||
Search(r'\bstd\s*::\s*initializer_list\b', constructor_args[0]))
|
||||
copy_constructor = bool(
|
||||
onearg_constructor and
|
||||
Match(r'(const\s+)?%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
|
||||
Match(r'((const\s+(volatile\s+)?)?|(volatile\s+(const\s+)?))?'
|
||||
r'%s(\s*<[^>]*>)?(\s+const)?\s*(?:<\w+>\s*)?&'
|
||||
% re.escape(base_classname), constructor_args[0].strip()))
|
||||
|
||||
if (not is_marked_explicit and
|
||||
|
@ -3302,7 +3285,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
|
|||
"""Reports for long function bodies.
|
||||
|
||||
For an overview why this is done, see:
|
||||
https://google.github.io/styleguide/cppguide.html#Write_Short_Functions
|
||||
https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Write_Short_Functions
|
||||
|
||||
Uses a simplistic algorithm assuming other style guidelines
|
||||
(especially spacing) are followed.
|
||||
|
@ -3343,7 +3326,7 @@ def CheckForFunctionLengths(filename, clean_lines, linenum,
|
|||
if Search(r'(;|})', start_line): # Declarations and trivial functions
|
||||
body_found = True
|
||||
break # ... ignore
|
||||
elif Search(r'{', start_line):
|
||||
if Search(r'{', start_line):
|
||||
body_found = True
|
||||
function = Search(r'((\w|:)*)\(', line).group(1)
|
||||
if Match(r'TEST', function): # Handle TEST... macros
|
||||
|
@ -3537,8 +3520,8 @@ def CheckSpacing(filename, clean_lines, linenum, nesting_state, error):
|
|||
line = clean_lines.elided[linenum]
|
||||
|
||||
# You shouldn't have spaces before your brackets, except maybe after
|
||||
# 'delete []' or 'return []() {};'
|
||||
if Search(r'\w\s+\[', line) and not Search(r'(?:delete|return)\s+\[', line):
|
||||
# 'delete []', 'return []() {};', or 'auto [abc, ...] = ...;'.
|
||||
if Search(r'\w\s+\[', line) and not Search(r'(?:auto&?|delete|return)\s+\[', line):
|
||||
error(filename, linenum, 'whitespace/braces', 5,
|
||||
'Extra space before [')
|
||||
|
||||
|
@ -4056,11 +4039,11 @@ def CheckBraces(filename, clean_lines, linenum, error):
|
|||
# its line, and the line after that should have an indent level equal to or
|
||||
# lower than the if. We also check for ambiguous if/else nesting without
|
||||
# braces.
|
||||
if_else_match = Search(r'\b(if\s*\(|else\b)', line)
|
||||
if_else_match = Search(r'\b(if\s*(|constexpr)\s*\(|else\b)', line)
|
||||
if if_else_match and not Match(r'\s*#', line):
|
||||
if_indent = GetIndentLevel(line)
|
||||
endline, endlinenum, endpos = line, linenum, if_else_match.end()
|
||||
if_match = Search(r'\bif\s*\(', line)
|
||||
if_match = Search(r'\bif\s*(|constexpr)\s*\(', line)
|
||||
if if_match:
|
||||
# This could be a multiline if condition, so find the end first.
|
||||
pos = if_match.end() - 1
|
||||
|
@ -4528,71 +4511,6 @@ 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.
|
||||
|
@ -4747,9 +4665,6 @@ 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)
|
||||
|
@ -4910,14 +4825,27 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
|
|||
'Do not include .' + extension + ' files from other packages')
|
||||
return
|
||||
|
||||
if not _THIRD_PARTY_HEADERS_PATTERN.match(include):
|
||||
# We DO want to include a 3rd party looking header if it matches the
|
||||
# filename. Otherwise we get an erroneous error "...should include its
|
||||
# header" error later.
|
||||
third_src_header = False
|
||||
for ext in GetHeaderExtensions():
|
||||
basefilename = filename[0:len(filename) - len(fileinfo.Extension())]
|
||||
headerfile = basefilename + '.' + ext
|
||||
headername = FileInfo(headerfile).RepositoryName()
|
||||
if headername in include or include in headername:
|
||||
third_src_header = True
|
||||
break
|
||||
|
||||
if third_src_header or not _THIRD_PARTY_HEADERS_PATTERN.match(include):
|
||||
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
|
||||
# 2) other project headers
|
||||
# 3) c system files
|
||||
# 4) cpp system files
|
||||
# 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
|
||||
#
|
||||
# We classify each include statement as one of those 5 types
|
||||
# using a number of techniques. The include_state object keeps
|
||||
|
@ -5180,7 +5108,7 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension,
|
|||
and line[-1] != '\\'):
|
||||
error(filename, linenum, 'build/namespaces', 4,
|
||||
'Do not use unnamed namespaces in header files. See '
|
||||
'https://google.github.io/styleguide/cppguide.html#Namespaces'
|
||||
'https://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Namespaces'
|
||||
' for more information.')
|
||||
|
||||
|
||||
|
@ -5708,11 +5636,11 @@ _HEADERS_CONTAINING_TEMPLATES = (
|
|||
)),
|
||||
('<limits>', ('numeric_limits',)),
|
||||
('<list>', ('list',)),
|
||||
('<map>', ('map', 'multimap',)),
|
||||
('<map>', ('multimap',)),
|
||||
('<memory>', ('allocator', 'make_shared', 'make_unique', 'shared_ptr',
|
||||
'unique_ptr', 'weak_ptr')),
|
||||
('<queue>', ('queue', 'priority_queue',)),
|
||||
('<set>', ('set', 'multiset',)),
|
||||
('<set>', ('multiset',)),
|
||||
('<stack>', ('stack',)),
|
||||
('<string>', ('char_traits', 'basic_string',)),
|
||||
('<tuple>', ('tuple',)),
|
||||
|
@ -5746,6 +5674,16 @@ for _header, _templates in _HEADERS_MAYBE_TEMPLATES:
|
|||
(re.compile(r'[^>.]\b' + _template + r'(<.*?>)?\([^\)]'),
|
||||
_template,
|
||||
_header))
|
||||
# Match set<type>, but not foo->set<type>, foo.set<type>
|
||||
_re_pattern_headers_maybe_templates.append(
|
||||
(re.compile(r'[^>.]\bset\s*\<'),
|
||||
'set<>',
|
||||
'<set>'))
|
||||
# Match 'map<type> var' and 'std::map<type>(...)', but not 'map<type>(...)''
|
||||
_re_pattern_headers_maybe_templates.append(
|
||||
(re.compile(r'(std\b::\bmap\s*\<)|(^(std\b::\b)map\b\(\s*\<)'),
|
||||
'map<>',
|
||||
'<map>'))
|
||||
|
||||
# Other scripts may reach in and modify this pattern.
|
||||
_re_pattern_templates = []
|
||||
|
@ -5828,18 +5766,19 @@ def UpdateIncludeState(filename, include_dict, io=codecs):
|
|||
"""
|
||||
headerfile = None
|
||||
try:
|
||||
headerfile = io.open(filename, 'r', 'utf8', 'replace')
|
||||
with io.open(filename, 'r', 'utf8', 'replace') as headerfile:
|
||||
linenum = 0
|
||||
for line in headerfile:
|
||||
linenum += 1
|
||||
clean_line = CleanseComments(line)
|
||||
match = _RE_PATTERN_INCLUDE.search(clean_line)
|
||||
if match:
|
||||
include = match.group(2)
|
||||
include_dict.setdefault(include, linenum)
|
||||
return True
|
||||
except IOError:
|
||||
return False
|
||||
linenum = 0
|
||||
for line in headerfile:
|
||||
linenum += 1
|
||||
clean_line = CleanseComments(line)
|
||||
match = _RE_PATTERN_INCLUDE.search(clean_line)
|
||||
if match:
|
||||
include = match.group(2)
|
||||
include_dict.setdefault(include, linenum)
|
||||
return True
|
||||
|
||||
|
||||
|
||||
def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error,
|
||||
|
@ -6291,8 +6230,6 @@ 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.
|
||||
|
||||
|
@ -6311,7 +6248,7 @@ def ProcessConfigOverrides(filename):
|
|||
if not base_name:
|
||||
break # Reached the root directory.
|
||||
|
||||
cfg_file = os.path.join(abs_path, ".cpplint")
|
||||
cfg_file = os.path.join(abs_path, "CPPLINT.cfg")
|
||||
abs_filename = abs_path
|
||||
if not os.path.isfile(cfg_file):
|
||||
continue
|
||||
|
@ -6355,14 +6292,7 @@ def ProcessConfigOverrides(filename):
|
|||
except ValueError:
|
||||
_cpplint_state.PrintError('Line length must be numeric.')
|
||||
elif name == 'extensions':
|
||||
global _valid_extensions
|
||||
try:
|
||||
extensions = [ext.strip() for ext in val.split(',')]
|
||||
_valid_extensions = set(extensions)
|
||||
except ValueError:
|
||||
sys.stderr.write('Extensions should be a comma-separated list of values;'
|
||||
'for example: extensions=hpp,cpp\n'
|
||||
'This could not be parsed: "%s"' % (val,))
|
||||
ProcessExtensionsOption(val)
|
||||
elif name == 'root':
|
||||
global _root
|
||||
# root directories are specified relative to CPPLINT.cfg dir.
|
||||
|
@ -6425,7 +6355,8 @@ def ProcessFile(filename, vlevel, extra_check_functions=None):
|
|||
codecs.getwriter('utf8'),
|
||||
'replace').read().split('\n')
|
||||
else:
|
||||
lines = codecs.open(filename, 'r', 'utf8', 'replace').read().split('\n')
|
||||
with codecs.open(filename, 'r', 'utf8', 'replace') as target_file:
|
||||
lines = target_file.read().split('\n')
|
||||
|
||||
# Remove trailing '\r'.
|
||||
# The -1 accounts for the extra trailing blank line we get from split()
|
||||
|
@ -6585,11 +6516,7 @@ def ParseArguments(args):
|
|||
_excludes = set()
|
||||
_excludes.update(glob.glob(val))
|
||||
elif opt == '--extensions':
|
||||
global _valid_extensions
|
||||
try:
|
||||
_valid_extensions = set(val.split(','))
|
||||
except ValueError:
|
||||
PrintUsage('Extensions must be comma seperated list.')
|
||||
ProcessExtensionsOption(val)
|
||||
elif opt == '--headers':
|
||||
ProcessHppHeadersOption(val)
|
||||
elif opt == '--recursive':
|
||||
|
@ -6641,15 +6568,35 @@ def _ExpandDirectories(filenames):
|
|||
for filename in expanded:
|
||||
if os.path.splitext(filename)[1][1:] in GetAllExtensions():
|
||||
filtered.append(filename)
|
||||
|
||||
return filtered
|
||||
|
||||
def _FilterExcludedFiles(filenames):
|
||||
def _FilterExcludedFiles(fnames):
|
||||
"""Filters out files listed in the --exclude command line switch. File paths
|
||||
in the switch are evaluated relative to the current working directory
|
||||
"""
|
||||
exclude_paths = [os.path.abspath(f) for f in _excludes]
|
||||
return [f for f in filenames if os.path.abspath(f) not in exclude_paths]
|
||||
# because globbing does not work recursively, exclude all subpath of all excluded entries
|
||||
return [f for f in fnames
|
||||
if not any(e for e in exclude_paths
|
||||
if _IsParentOrSame(e, os.path.abspath(f)))]
|
||||
|
||||
def _IsParentOrSame(parent, child):
|
||||
"""Return true if child is subdirectory of parent.
|
||||
Assumes both paths are absolute and don't contain symlinks.
|
||||
"""
|
||||
parent = os.path.normpath(parent)
|
||||
child = os.path.normpath(child)
|
||||
if parent == child:
|
||||
return True
|
||||
|
||||
prefix = os.path.commonprefix([parent, child])
|
||||
if prefix != parent:
|
||||
return False
|
||||
# Note: os.path.commonprefix operates on character basis, so
|
||||
# take extra care of situations like '/foo/ba' and '/foo/bar/baz'
|
||||
child_suffix = child[len(prefix):]
|
||||
child_suffix = child_suffix.lstrip(os.sep)
|
||||
return child == os.path.join(prefix, child_suffix)
|
||||
|
||||
def main():
|
||||
filenames = ParseArguments(sys.argv[1:])
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue