diff --git a/tools/cpplint.py b/tools/cpplint.py index 5f5f1400d7ec56..8ca6471179b070 100755 --- a/tools/cpplint.py +++ b/tools/cpplint.py @@ -45,7 +45,6 @@ import copy import getopt import glob -import logging import itertools import math # for log import os @@ -56,10 +55,6 @@ import unicodedata import xml.etree.ElementTree -try: - xrange -except NameError: - xrange = range # if empty, use defaults _header_extensions = set([]) @@ -73,7 +68,7 @@ # option (also supported in CPPLINT.cfg) def GetHeaderExtensions(): if not _header_extensions: - return set(['h', 'hpp', 'hxx', 'h++', 'cuh']) + return set(['h', 'hh', 'hpp', 'hxx', 'h++', 'cuh']) return _header_extensions # The allowed extensions for file names @@ -85,7 +80,6 @@ def GetAllExtensions(): def GetNonHeaderExtensions(): return GetAllExtensions().difference(GetHeaderExtensions()) -logger = logging.getLogger('testrunner') _USAGE = """ @@ -95,7 +89,6 @@ def GetNonHeaderExtensions(): [--root=subdir] [--linelength=digits] [--recursive] [--exclude=path] [--headers=ext1,ext2] - [--logfile=filename] [--extensions=hpp,cpp,...] [file] ... @@ -129,7 +122,7 @@ def GetNonHeaderExtensions(): likely to be false positives. quiet - Suppress output other than linting errors, such as information about + Supress output other than linting errors, such as information about which files have been processed and excluded. filter=-x,+y,... @@ -289,6 +282,7 @@ def GetNonHeaderExtensions(): 'build/forward_decl', 'build/header_guard', 'build/include', + 'build/include_subdir', 'build/include_alpha', 'build/include_order', 'build/include_what_you_use', @@ -359,13 +353,7 @@ def GetNonHeaderExtensions(): # flag. By default all errors are on, so only add here categories that should be # off by default (i.e., categories that must be enabled by the --filter= flags). # All entries here should start with a '-' or '+', as in the --filter= flag. -_DEFAULT_FILTERS = [ - '-build/include', - '-build/include_alpha', - '-build/include_order', - '-build/include_subdir', - '-legal/copyright', - ] +_DEFAULT_FILTERS = ['-build/include_alpha'] # The default list of categories suppressed for C (not C++) files. _DEFAULT_C_SUPPRESSED_CATEGORIES = [ @@ -489,6 +477,18 @@ def GetNonHeaderExtensions(): 'utility', 'valarray', 'vector', + # 17.6.1.2 C++14 headers + 'shared_mutex', + # 17.6.1.2 C++17 headers + 'any', + 'charconv', + 'codecvt', + 'execution', + 'filesystem', + 'memory_resource', + 'optional', + 'string_view', + 'variant', # 17.6.1.2 C++ headers for C library facilities 'cassert', 'ccomplex', @@ -626,12 +626,6 @@ def GetNonHeaderExtensions(): # 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') - -_RIGHT_LEANING_POINTER_PATTERN = re.compile(r'[^=|(,\s><);&?:}]' - r'(?= 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 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/null_usage', 2, - 'Use left leaning pointer instead of right leaning') def GetLineWidth(line): """Determines the width of the line in column positions. @@ -4504,10 +4477,6 @@ def CheckStyle(filename, clean_lines, linenum, file_extension, nesting_state, error(filename, linenum, 'whitespace/tab', 1, 'Tab found; better to use spaces') - if line.find('template<') != -1: - error(filename, linenum, 'whitespace/template', 1, - 'Leave a single space after template, as in `template <...>`') - # One or three blank spaces at the beginning of the line is weird; it's # hard to reconcile that with 2-space indents. # NOTE: here are the conditions rob pike used for his tests. Mine aren't @@ -4601,8 +4570,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) - CheckLeftLeaningPointer(filename, clean_lines, linenum, error) classinfo = nesting_state.InnermostClass() if classinfo: CheckSectionSpacing(filename, clean_lines, classinfo, linenum, error) @@ -4677,7 +4644,7 @@ def _ClassifyInclude(fileinfo, include, is_system): # Headers with C++ extensions shouldn't be considered C system headers if is_system and os.path.splitext(include)[1] in ['.hpp', '.hxx', '.h++']: - is_system = False + is_system = False if is_system: if is_cpp_h: @@ -4911,8 +4878,6 @@ def CheckLanguage(filename, clean_lines, linenum, file_extension, if match: include_state.ResetSection(match.group(1)) - # Make Windows paths like Unix. - fullname = os.path.abspath(filename).replace('\\', '/') # Perform other checks now that we are sure that this is not an include line CheckCasts(filename, clean_lines, linenum, error) @@ -5565,12 +5530,15 @@ def ExpectingFunctionArgs(clean_lines, linenum): ('', ('numeric_limits',)), ('', ('list',)), ('', ('map', 'multimap',)), - ('', ('allocator',)), + ('', ('allocator', 'make_shared', 'make_unique', 'shared_ptr', + 'unique_ptr', 'weak_ptr')), ('', ('queue', 'priority_queue',)), ('', ('set', 'multiset',)), ('', ('stack',)), ('', ('char_traits', 'basic_string',)), ('', ('tuple',)), + ('', ('unordered_map', 'unordered_multimap')), + ('', ('unordered_set', 'unordered_multiset')), ('', ('pair',)), ('', ('vector',)), @@ -5585,7 +5553,7 @@ def ExpectingFunctionArgs(clean_lines, linenum): ('', ('copy', 'max', 'min', 'min_element', 'sort', 'transform', )), - ('', ('swap',)), + ('', ('forward', 'make_pair', 'move', 'swap')), ) _RE_PATTERN_STRING = re.compile(r'\bstring\b') @@ -5716,7 +5684,7 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, required = {} # A map of header name to linenumber and the template entity. # Example of required: { '': (1219, 'less<>') } - for linenum in xrange(clean_lines.NumLines()): + for linenum in range(clean_lines.NumLines()): line = clean_lines.elided[linenum] if not line or line[0] == '#': continue @@ -5739,8 +5707,13 @@ def CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error, continue for pattern, template, header in _re_pattern_templates: - if pattern.search(line): - required[header] = (linenum, template) + matched = pattern.search(line) + if matched: + # Don't warn about IWYU in non-STL namespaces: + # (We check only the first match per line; good enough.) + prefix = line[:matched.start()] + if prefix.endswith('std::') or not prefix.endswith('::'): + required[header] = (linenum, template) # The policy is that if you #include something in foo.h you don't need to # include it again in foo.cc. Here, we will look at possible includes. @@ -6120,7 +6093,7 @@ def ProcessFileData(filename, file_extension, lines, error, if file_extension in GetHeaderExtensions(): CheckForHeaderGuard(filename, clean_lines, error) - for line in xrange(clean_lines.NumLines()): + for line in range(clean_lines.NumLines()): ProcessLine(filename, file_extension, clean_lines, line, include_state, function_state, nesting_state, error, extra_check_functions) @@ -6139,8 +6112,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. @@ -6190,7 +6161,7 @@ def ProcessConfigOverrides(filename): if pattern.match(base_name): _cpplint_state.PrintInfo('Ignoring "%s": file excluded by ' '"%s". File path component "%s" matches pattern "%s"\n' % - (filename, cfg_file, base_name, val)) + (filename, cfg_file, base_name, val)) return False elif name == 'linelength': global _line_length @@ -6363,7 +6334,6 @@ def ParseArguments(args): (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 'counting=', 'filter=', - 'logfile=', 'root=', 'repository=', 'linelength=', @@ -6385,9 +6355,9 @@ def ParseArguments(args): if opt == '--help': PrintUsage(None) elif opt == '--output': - if val not in ('emacs', 'vs7', 'eclipse', 'junit', 'tap'): - PrintUsage( - 'The only allowed output formats are emacs, vs7, eclipse, junit and tap.') + if val not in ('emacs', 'vs7', 'eclipse', 'junit'): + PrintUsage('The only allowed output formats are emacs, vs7, eclipse ' + 'and junit.') output_format = val elif opt == '--verbose': verbosity = int(val) @@ -6408,9 +6378,9 @@ def ParseArguments(args): elif opt == '--linelength': global _line_length try: - _line_length = int(val) + _line_length = int(val) except ValueError: - PrintUsage('Line length must be digits.') + PrintUsage('Line length must be digits.') elif opt == '--exclude': global _excludes if not _excludes: @@ -6419,7 +6389,7 @@ def ParseArguments(args): elif opt == '--extensions': global _valid_extensions try: - _valid_extensions = set(val.split(',')) + _valid_extensions = set(val.split(',')) except ValueError: PrintUsage('Extensions must be comma seperated list.') elif opt == '--headers': @@ -6430,8 +6400,6 @@ def ParseArguments(args): PrintUsage('Extensions must be comma seperated list.') elif opt == '--recursive': recursive = True - elif opt == '--logfile': - logger.addHandler(logging.FileHandler(val, mode='wb')) elif opt == '--quiet': global _quiet _quiet = True @@ -6497,22 +6465,13 @@ def main(): try: # Change stderr to write with replacement characters so we don't die # if we try to print something containing non-ASCII characters. - sys.stderr = codecs.StreamReaderWriter(sys.stderr, - codecs.getreader('utf8'), - codecs.getwriter('utf8'), - 'replace') - - logger.addHandler(logging.StreamHandler(sys.stdout)) - logger.setLevel(logging.INFO) + sys.stderr = codecs.StreamReader(sys.stderr, 'replace') _cpplint_state.ResetErrorCounts() for filename in filenames: - ProcessFile(filename.decode('utf-8'), _cpplint_state.verbose_level) + ProcessFile(filename, _cpplint_state.verbose_level) _cpplint_state.PrintErrorCounts() - if _cpplint_state.output_format == 'tap': - logger.info('TAP version 13') - if _cpplint_state.output_format == 'junit': sys.stderr.write(_cpplint_state.FormatJUnitXML())