Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(286)

Side by Side Diff: cpplint.py

Issue 406373002: depot_tools: modify cpplint.py to allow CPPLINT.cfg overrides (Closed) Base URL: https://chromium.googlesource.com/chromium/tools/depot_tools.git@master
Patch Set: Fixed review comments Created 6 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 #!/usr/bin/env python 1 #!/usr/bin/env python
2 # 2 #
3 # Copyright (c) 2009 Google Inc. All rights reserved. 3 # Copyright (c) 2009 Google Inc. All rights reserved.
4 # 4 #
5 # Redistribution and use in source and binary forms, with or without 5 # Redistribution and use in source and binary forms, with or without
6 # modification, are permitted provided that the following conditions are 6 # modification, are permitted provided that the following conditions are
7 # met: 7 # met:
8 # 8 #
9 # * Redistributions of source code must retain the above copyright 9 # * Redistributions of source code must retain the above copyright
10 # notice, this list of conditions and the following disclaimer. 10 # notice, this list of conditions and the following disclaimer.
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after
126 80 characters. 126 80 characters.
127 127
128 Examples: 128 Examples:
129 --linelength=120 129 --linelength=120
130 130
131 extensions=extension,extension,... 131 extensions=extension,extension,...
132 The allowed file extensions that cpplint will check 132 The allowed file extensions that cpplint will check
133 133
134 Examples: 134 Examples:
135 --extensions=hpp,cpp 135 --extensions=hpp,cpp
136
137 cpplint.py supports per-directory configurations specified in CPPLINT.cfg
138 files. CPPLINT.cfg file can contain a number of key=value pairs.
139 Currently the following options are supported:
140
141 filter=+filter1,-filter2,...
142 exclude_files=regex
143
144 The "filter" option is similar in function to --filter flag. It specifies
145 message filters in addition to the |_DEFAULT_FILTERS| and those specified
146 through --filter command-line flag.
147
148 "exclude_files" allows to specify a regular expression to be matched against
149 a file name. If the expression matches, the file is skipped and not run
150 through liner.
151
152 CPPLINT.cfg has an effect on files in the same directory and all
153 sub-directories, unless overridden by a nested configuration file.
154
155 Example file:
156 filter=-build/include_order,+build/include_alpha
157 exclude_files=.*\.cc
158
159 The above example disables build/include_order warning and enables
160 build/include_alpha as well as excludes all .cc from being
161 processed by linter, in the current directory (where the .cfg
162 file is located) and all sub-directories.
136 """ 163 """
137 164
138 # We categorize each error message we print. Here are the categories. 165 # We categorize each error message we print. Here are the categories.
139 # We want an explicit list so we can list them all in cpplint --filter=. 166 # We want an explicit list so we can list them all in cpplint --filter=.
140 # If you add a new error message with a new category, add it to the list 167 # If you add a new error message with a new category, add it to the list
141 # here! cpplint_unittest.py should tell you if you forget to do this. 168 # here! cpplint_unittest.py should tell you if you forget to do this.
142 _ERROR_CATEGORIES = [ 169 _ERROR_CATEGORIES = [
143 'build/class', 170 'build/class',
144 'build/c++11', 171 'build/c++11',
145 'build/deprecated', 172 'build/deprecated',
(...skipping 529 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 702
676 703
677 class _CppLintState(object): 704 class _CppLintState(object):
678 """Maintains module-wide state..""" 705 """Maintains module-wide state.."""
679 706
680 def __init__(self): 707 def __init__(self):
681 self.verbose_level = 1 # global setting. 708 self.verbose_level = 1 # global setting.
682 self.error_count = 0 # global count of reported errors 709 self.error_count = 0 # global count of reported errors
683 # filters to apply when emitting error messages 710 # filters to apply when emitting error messages
684 self.filters = _DEFAULT_FILTERS[:] 711 self.filters = _DEFAULT_FILTERS[:]
712 # backup of filter list. Used to restore the state after each file.
713 self._filters_backup = self.filters[:]
685 self.counting = 'total' # In what way are we counting errors? 714 self.counting = 'total' # In what way are we counting errors?
686 self.errors_by_category = {} # string to int dict storing error counts 715 self.errors_by_category = {} # string to int dict storing error counts
687 716
688 # output format: 717 # output format:
689 # "emacs" - format that emacs can parse (default) 718 # "emacs" - format that emacs can parse (default)
690 # "vs7" - format that Microsoft Visual Studio 7 can parse 719 # "vs7" - format that Microsoft Visual Studio 7 can parse
691 self.output_format = 'emacs' 720 self.output_format = 'emacs'
692 721
693 def SetOutputFormat(self, output_format): 722 def SetOutputFormat(self, output_format):
694 """Sets the output format for errors.""" 723 """Sets the output format for errors."""
(...skipping 18 matching lines...) Expand all
713 Args: 742 Args:
714 filters: A string of comma-separated filters (eg "+whitespace/indent"). 743 filters: A string of comma-separated filters (eg "+whitespace/indent").
715 Each filter should start with + or -; else we die. 744 Each filter should start with + or -; else we die.
716 745
717 Raises: 746 Raises:
718 ValueError: The comma-separated filters did not all start with '+' or '-'. 747 ValueError: The comma-separated filters did not all start with '+' or '-'.
719 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 748 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
720 """ 749 """
721 # Default filters always have less priority than the flag ones. 750 # Default filters always have less priority than the flag ones.
722 self.filters = _DEFAULT_FILTERS[:] 751 self.filters = _DEFAULT_FILTERS[:]
752 self.AddFilters(filters)
753
754 def AddFilters(self, filters):
755 """ Adds more filters to the existing list of error-message filters. """
723 for filt in filters.split(','): 756 for filt in filters.split(','):
724 clean_filt = filt.strip() 757 clean_filt = filt.strip()
725 if clean_filt: 758 if clean_filt:
726 self.filters.append(clean_filt) 759 self.filters.append(clean_filt)
727 for filt in self.filters: 760 for filt in self.filters:
728 if not (filt.startswith('+') or filt.startswith('-')): 761 if not (filt.startswith('+') or filt.startswith('-')):
729 raise ValueError('Every filter in --filters must start with + or -' 762 raise ValueError('Every filter in --filters must start with + or -'
730 ' (%s does not)' % filt) 763 ' (%s does not)' % filt)
731 764
765 def BackupFilters(self):
766 """ Saves the current filter list to backup storage."""
767 self._filters_backup = self.filters[:]
768
769 def RestoreFilters(self):
770 """ Restores filters previously backed up."""
771 self.filters = self._filters_backup[:]
772
732 def ResetErrorCounts(self): 773 def ResetErrorCounts(self):
733 """Sets the module's error statistic back to zero.""" 774 """Sets the module's error statistic back to zero."""
734 self.error_count = 0 775 self.error_count = 0
735 self.errors_by_category = {} 776 self.errors_by_category = {}
736 777
737 def IncrementErrorCount(self, category): 778 def IncrementErrorCount(self, category):
738 """Bumps the module's error statistic.""" 779 """Bumps the module's error statistic."""
739 self.error_count += 1 780 self.error_count += 1
740 if self.counting in ('toplevel', 'detailed'): 781 if self.counting in ('toplevel', 'detailed'):
741 if self.counting != 'detailed': 782 if self.counting != 'detailed':
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 830
790 These filters are applied when deciding whether to emit a given 831 These filters are applied when deciding whether to emit a given
791 error message. 832 error message.
792 833
793 Args: 834 Args:
794 filters: A string of comma-separated filters (eg "whitespace/indent"). 835 filters: A string of comma-separated filters (eg "whitespace/indent").
795 Each filter should start with + or -; else we die. 836 Each filter should start with + or -; else we die.
796 """ 837 """
797 _cpplint_state.SetFilters(filters) 838 _cpplint_state.SetFilters(filters)
798 839
840 def _AddFilters(filters):
841 """Adds more filter overrides.
842
843 Unlike _SetFilters, this function does not reset the current list of filters
844 available.
845
846 Args:
847 filters: A string of comma-separated filters (eg "whitespace/indent").
848 Each filter should start with + or -; else we die.
849 """
850 _cpplint_state.AddFilters(filters)
851
852 def _BackupFilters():
853 """ Saves the current filter list to backup storage."""
854 _cpplint_state.BackupFilters()
855
856 def _RestoreFilters():
857 """ Restores filters previously backed up."""
858 _cpplint_state.RestoreFilters()
799 859
800 class _FunctionState(object): 860 class _FunctionState(object):
801 """Tracks current function name and the number of lines in its body.""" 861 """Tracks current function name and the number of lines in its body."""
802 862
803 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 863 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
804 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 864 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
805 865
806 def __init__(self): 866 def __init__(self):
807 self.in_a_function = False 867 self.in_a_function = False
808 self.lines_in_function = 0 868 self.lines_in_function = 0
(...skipping 4512 matching lines...) Expand 10 before | Expand all | Expand 10 after
5321 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error) 5381 CheckForNonConstReference(filename, clean_lines, line, nesting_state, error)
5322 CheckForNonStandardConstructs(filename, clean_lines, line, 5382 CheckForNonStandardConstructs(filename, clean_lines, line,
5323 nesting_state, error) 5383 nesting_state, error)
5324 CheckVlogArguments(filename, clean_lines, line, error) 5384 CheckVlogArguments(filename, clean_lines, line, error)
5325 CheckPosixThreading(filename, clean_lines, line, error) 5385 CheckPosixThreading(filename, clean_lines, line, error)
5326 CheckInvalidIncrement(filename, clean_lines, line, error) 5386 CheckInvalidIncrement(filename, clean_lines, line, error)
5327 CheckMakePairUsesDeduction(filename, clean_lines, line, error) 5387 CheckMakePairUsesDeduction(filename, clean_lines, line, error)
5328 CheckDefaultLambdaCaptures(filename, clean_lines, line, error) 5388 CheckDefaultLambdaCaptures(filename, clean_lines, line, error)
5329 for check_fn in extra_check_functions: 5389 for check_fn in extra_check_functions:
5330 check_fn(filename, clean_lines, line, error) 5390 check_fn(filename, clean_lines, line, error)
5331 » 5391
5332 def FlagCxx11Features(filename, clean_lines, linenum, error): 5392 def FlagCxx11Features(filename, clean_lines, linenum, error):
5333 """Flag those c++11 features that we only allow in certain places. 5393 """Flag those c++11 features that we only allow in certain places.
5334 5394
5335 Args: 5395 Args:
5336 filename: The name of the current file. 5396 filename: The name of the current file.
5337 clean_lines: A CleansedLines instance containing the file. 5397 clean_lines: A CleansedLines instance containing the file.
5338 linenum: The number of the line to check. 5398 linenum: The number of the line to check.
5339 error: The function to call with any errors found. 5399 error: The function to call with any errors found.
5340 """ 5400 """
5341 line = clean_lines.elided[linenum] 5401 line = clean_lines.elided[linenum]
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after
5417 nesting_state.CheckCompletedBlocks(filename, error) 5477 nesting_state.CheckCompletedBlocks(filename, error)
5418 5478
5419 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) 5479 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
5420 5480
5421 # We check here rather than inside ProcessLine so that we see raw 5481 # We check here rather than inside ProcessLine so that we see raw
5422 # lines rather than "cleaned" lines. 5482 # lines rather than "cleaned" lines.
5423 CheckForBadCharacters(filename, lines, error) 5483 CheckForBadCharacters(filename, lines, error)
5424 5484
5425 CheckForNewlineAtEOF(filename, lines, error) 5485 CheckForNewlineAtEOF(filename, lines, error)
5426 5486
5487 def GetConfigOverrideFiles(filename):
5488 """ Looks for CPPLINT.cfg files in the directory containing |filename| and
sosa 2014/07/23 20:25:42 docstring issue
Alex Vakulenko (Google) 2014/07/23 20:44:32 Done.
5489 its parents and returns a list of configuration files found.
5490
5491 Args:
5492 filename: The name of the file being processed by the linter.
5493 """
5494
5495 cfg_override_files = []
5496 abs_path = os.path.abspath(os.path.dirname(filename))
5497
5498 while True:
5499 file = os.path.join(abs_path, "CPPLINT.cfg")
5500 if os.path.isfile(file):
5501 cfg_override_files.append(file)
5502 parent = os.path.dirname(abs_path)
5503 if parent == abs_path:
5504 break
5505 abs_path = parent
5506
5507 return reversed(cfg_override_files)
5508
5509 def ProcessConfigFile(cfg_file, filename):
5510 """ Loads the configuration file and processes the config overrides.
5511
5512 Args:
5513 cfg_file: config file to process
5514 filename: The name of the file being processed by the linter.
5515
5516 Returns:
5517 false if the current |filename| should not be processed further.
5518 """
5519
5520 try:
5521 with open(cfg_file) as file_handle:
5522 for line in file_handle:
5523 line, _, _ = line.partition('#') # Remove comments.
5524 if line.strip():
5525 name, _, val = line.partition('=')
5526 name = name.strip()
5527 val = val.strip()
5528 if name == 'filter':
5529 _AddFilters(val)
5530 elif name == 'exclude_files':
5531 pattern = re.compile(val)
5532 if pattern.match(filename):
5533 sys.stderr.write('Ignoring %s; file excluded by (%s)\n' %
5534 (filename, cfg_file))
5535 return False
5536 else:
5537 sys.stderr.write('Invalid configuration option (%s) in file %s\n' %
5538 (name, cfg_file))
5539
5540 except IOError:
5541 sys.stderr.write(
5542 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
5543 _RestoreFilters()
5544 return True
5545
5546 return True
5547
5548
5549 def ProcessConfigOverrides(cfg_override_files, filename):
5550 """ Loads the configuration files and processes the config overrides.
5551
5552 Args:
5553 cfg_override_files: list of cfg files to process
5554 filename: The name of the file being processed by the linter.
5555
5556 Returns:
5557 false if the current |filename| should not be processed further.
5558 """
5559 for cfg_file in cfg_override_files:
5560 if not ProcessConfigFile(cfg_file, filename):
5561 return False
5562
5563 return True
5427 5564
5428 def ProcessFile(filename, vlevel, extra_check_functions=[]): 5565 def ProcessFile(filename, vlevel, extra_check_functions=[]):
5429 """Does google-lint on a single file. 5566 """Does google-lint on a single file.
5430 5567
5431 Args: 5568 Args:
5432 filename: The name of the file to parse. 5569 filename: The name of the file to parse.
5433 5570
5434 vlevel: The level of errors to report. Every error of confidence 5571 vlevel: The level of errors to report. Every error of confidence
5435 >= verbose_level will be reported. 0 is a good default. 5572 >= verbose_level will be reported. 0 is a good default.
5436 5573
5437 extra_check_functions: An array of additional check functions that will be 5574 extra_check_functions: An array of additional check functions that will be
5438 run on each source line. Each function takes 4 5575 run on each source line. Each function takes 4
5439 arguments: filename, clean_lines, line, error 5576 arguments: filename, clean_lines, line, error
5440 """ 5577 """
5441 5578
5442 _SetVerboseLevel(vlevel) 5579 _SetVerboseLevel(vlevel)
5580 _BackupFilters()
5581
5582 cfg_override_files = GetConfigOverrideFiles(filename)
5583 if not ProcessConfigOverrides(cfg_override_files, filename):
5584 _RestoreFilters()
5585 return
5443 5586
5444 lf_lines = [] 5587 lf_lines = []
5445 crlf_lines = [] 5588 crlf_lines = []
5446 try: 5589 try:
5447 # Support the UNIX convention of using "-" for stdin. Note that 5590 # Support the UNIX convention of using "-" for stdin. Note that
5448 # we are not opening the file with universal newline support 5591 # we are not opening the file with universal newline support
5449 # (which codecs doesn't support anyway), so the resulting lines do 5592 # (which codecs doesn't support anyway), so the resulting lines do
5450 # contain trailing '\r' characters if we are reading a file that 5593 # contain trailing '\r' characters if we are reading a file that
5451 # has CRLF endings. 5594 # has CRLF endings.
5452 # If after the split a trailing '\r' is present, it is removed 5595 # If after the split a trailing '\r' is present, it is removed
(...skipping 11 matching lines...) Expand all
5464 for linenum in range(len(lines) - 1): 5607 for linenum in range(len(lines) - 1):
5465 if lines[linenum].endswith('\r'): 5608 if lines[linenum].endswith('\r'):
5466 lines[linenum] = lines[linenum].rstrip('\r') 5609 lines[linenum] = lines[linenum].rstrip('\r')
5467 crlf_lines.append(linenum + 1) 5610 crlf_lines.append(linenum + 1)
5468 else: 5611 else:
5469 lf_lines.append(linenum + 1) 5612 lf_lines.append(linenum + 1)
5470 5613
5471 except IOError: 5614 except IOError:
5472 sys.stderr.write( 5615 sys.stderr.write(
5473 "Skipping input '%s': Can't open for reading\n" % filename) 5616 "Skipping input '%s': Can't open for reading\n" % filename)
5617 _RestoreFilters()
5474 return 5618 return
5475 5619
5476 # Note, if no dot is found, this will give the entire filename as the ext. 5620 # Note, if no dot is found, this will give the entire filename as the ext.
5477 file_extension = filename[filename.rfind('.') + 1:] 5621 file_extension = filename[filename.rfind('.') + 1:]
5478 5622
5479 # When reading from stdin, the extension is unknown, so no cpplint tests 5623 # When reading from stdin, the extension is unknown, so no cpplint tests
5480 # should rely on the extension. 5624 # should rely on the extension.
5481 if filename != '-' and file_extension not in _valid_extensions: 5625 if filename != '-' and file_extension not in _valid_extensions:
5482 sys.stderr.write('Ignoring %s; not a valid file name ' 5626 sys.stderr.write('Ignoring %s; not a valid file name '
5483 '(%s)\n' % (filename, ', '.join(_valid_extensions))) 5627 '(%s)\n' % (filename, ', '.join(_valid_extensions)))
(...skipping 13 matching lines...) Expand all
5497 # server-side end-of-line sequence. 5641 # server-side end-of-line sequence.
5498 if lf_lines and crlf_lines: 5642 if lf_lines and crlf_lines:
5499 # Warn on every line with CR. An alternative approach might be to 5643 # Warn on every line with CR. An alternative approach might be to
5500 # check whether the file is mostly CRLF or just LF, and warn on the 5644 # check whether the file is mostly CRLF or just LF, and warn on the
5501 # minority, we bias toward LF here since most tools prefer LF. 5645 # minority, we bias toward LF here since most tools prefer LF.
5502 for linenum in crlf_lines: 5646 for linenum in crlf_lines:
5503 Error(filename, linenum, 'whitespace/newline', 1, 5647 Error(filename, linenum, 'whitespace/newline', 1,
5504 'Unexpected \\r (^M) found; better to use only \\n') 5648 'Unexpected \\r (^M) found; better to use only \\n')
5505 5649
5506 sys.stderr.write('Done processing %s\n' % filename) 5650 sys.stderr.write('Done processing %s\n' % filename)
5651 _RestoreFilters()
5507 5652
5508 5653
5509 def PrintUsage(message): 5654 def PrintUsage(message):
5510 """Prints a brief usage string and exits, optionally with an error message. 5655 """Prints a brief usage string and exits, optionally with an error message.
5511 5656
5512 Args: 5657 Args:
5513 message: The optional error message. 5658 message: The optional error message.
5514 """ 5659 """
5515 sys.stderr.write(_USAGE) 5660 sys.stderr.write(_USAGE)
5516 if message: 5661 if message:
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
5611 _cpplint_state.ResetErrorCounts() 5756 _cpplint_state.ResetErrorCounts()
5612 for filename in filenames: 5757 for filename in filenames:
5613 ProcessFile(filename, _cpplint_state.verbose_level) 5758 ProcessFile(filename, _cpplint_state.verbose_level)
5614 _cpplint_state.PrintErrorCounts() 5759 _cpplint_state.PrintErrorCounts()
5615 5760
5616 sys.exit(_cpplint_state.error_count > 0) 5761 sys.exit(_cpplint_state.error_count > 0)
5617 5762
5618 5763
5619 if __name__ == '__main__': 5764 if __name__ == '__main__':
5620 main() 5765 main()
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698