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

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: 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 664 matching lines...) Expand 10 before | Expand all | Expand 10 after
675 675
676 676
677 class _CppLintState(object): 677 class _CppLintState(object):
678 """Maintains module-wide state..""" 678 """Maintains module-wide state.."""
679 679
680 def __init__(self): 680 def __init__(self):
681 self.verbose_level = 1 # global setting. 681 self.verbose_level = 1 # global setting.
682 self.error_count = 0 # global count of reported errors 682 self.error_count = 0 # global count of reported errors
683 # filters to apply when emitting error messages 683 # filters to apply when emitting error messages
684 self.filters = _DEFAULT_FILTERS[:] 684 self.filters = _DEFAULT_FILTERS[:]
685 # backup of filter list. Used to restore the state after each file.
sosa 2014/07/23 17:35:00 indentation also this seems super private to the c
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
686 self.filters_backup = self.filters[:]
685 self.counting = 'total' # In what way are we counting errors? 687 self.counting = 'total' # In what way are we counting errors?
686 self.errors_by_category = {} # string to int dict storing error counts 688 self.errors_by_category = {} # string to int dict storing error counts
687 689
688 # output format: 690 # output format:
689 # "emacs" - format that emacs can parse (default) 691 # "emacs" - format that emacs can parse (default)
690 # "vs7" - format that Microsoft Visual Studio 7 can parse 692 # "vs7" - format that Microsoft Visual Studio 7 can parse
691 self.output_format = 'emacs' 693 self.output_format = 'emacs'
692 694
693 def SetOutputFormat(self, output_format): 695 def SetOutputFormat(self, output_format):
694 """Sets the output format for errors.""" 696 """Sets the output format for errors."""
(...skipping 18 matching lines...) Expand all
713 Args: 715 Args:
714 filters: A string of comma-separated filters (eg "+whitespace/indent"). 716 filters: A string of comma-separated filters (eg "+whitespace/indent").
715 Each filter should start with + or -; else we die. 717 Each filter should start with + or -; else we die.
716 718
717 Raises: 719 Raises:
718 ValueError: The comma-separated filters did not all start with '+' or '-'. 720 ValueError: The comma-separated filters did not all start with '+' or '-'.
719 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter" 721 E.g. "-,+whitespace,-whitespace/indent,whitespace/badfilter"
720 """ 722 """
721 # Default filters always have less priority than the flag ones. 723 # Default filters always have less priority than the flag ones.
722 self.filters = _DEFAULT_FILTERS[:] 724 self.filters = _DEFAULT_FILTERS[:]
725 self.AddFilters(filters)
726
727 def AddFilters(self, filters):
728 """ Adds more filters to the existing list of error-message filters. """
723 for filt in filters.split(','): 729 for filt in filters.split(','):
724 clean_filt = filt.strip() 730 clean_filt = filt.strip()
725 if clean_filt: 731 if clean_filt:
726 self.filters.append(clean_filt) 732 self.filters.append(clean_filt)
727 for filt in self.filters: 733 for filt in self.filters:
728 if not (filt.startswith('+') or filt.startswith('-')): 734 if not (filt.startswith('+') or filt.startswith('-')):
729 raise ValueError('Every filter in --filters must start with + or -' 735 raise ValueError('Every filter in --filters must start with + or -'
730 ' (%s does not)' % filt) 736 ' (%s does not)' % filt)
731 737
738 def BackupFilters(self):
739 """ Saves the current filter list to backup storage."""
740 self.filters_backup = self.filters[:]
741
742 def RestoreFilters(self):
743 """ Restores filters previously backed up."""
744 self.filters = self.filters_backup[:]
745
732 def ResetErrorCounts(self): 746 def ResetErrorCounts(self):
733 """Sets the module's error statistic back to zero.""" 747 """Sets the module's error statistic back to zero."""
734 self.error_count = 0 748 self.error_count = 0
735 self.errors_by_category = {} 749 self.errors_by_category = {}
736 750
737 def IncrementErrorCount(self, category): 751 def IncrementErrorCount(self, category):
738 """Bumps the module's error statistic.""" 752 """Bumps the module's error statistic."""
739 self.error_count += 1 753 self.error_count += 1
740 if self.counting in ('toplevel', 'detailed'): 754 if self.counting in ('toplevel', 'detailed'):
741 if self.counting != 'detailed': 755 if self.counting != 'detailed':
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
789 803
790 These filters are applied when deciding whether to emit a given 804 These filters are applied when deciding whether to emit a given
791 error message. 805 error message.
792 806
793 Args: 807 Args:
794 filters: A string of comma-separated filters (eg "whitespace/indent"). 808 filters: A string of comma-separated filters (eg "whitespace/indent").
795 Each filter should start with + or -; else we die. 809 Each filter should start with + or -; else we die.
796 """ 810 """
797 _cpplint_state.SetFilters(filters) 811 _cpplint_state.SetFilters(filters)
798 812
813 def _AddFilters(filters):
814 """Adds more filter overrides. Unlike _SetFilters, this function does not
sosa 2014/07/23 17:35:00 Unlike should be on a newline. We usually keep the
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
815 reset the current list of filters available.
816 Args:
817 filters: A string of comma-separated filters (eg "whitespace/indent").
818 Each filter should start with + or -; else we die.
819 """
820 _cpplint_state.AddFilters(filters)
821
822 def _BackupFilters():
823 """ Saves the current filter list to backup storage."""
824 _cpplint_state.BackupFilters()
825
826 def _RestoreFilters():
827 """ Restores filters previously backed up."""
828 _cpplint_state.RestoreFilters()
799 829
800 class _FunctionState(object): 830 class _FunctionState(object):
801 """Tracks current function name and the number of lines in its body.""" 831 """Tracks current function name and the number of lines in its body."""
802 832
803 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc. 833 _NORMAL_TRIGGER = 250 # for --v=0, 500 for --v=1, etc.
804 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER. 834 _TEST_TRIGGER = 400 # about 50% more than _NORMAL_TRIGGER.
805 835
806 def __init__(self): 836 def __init__(self):
807 self.in_a_function = False 837 self.in_a_function = False
808 self.lines_in_function = 0 838 self.lines_in_function = 0
(...skipping 4608 matching lines...) Expand 10 before | Expand all | Expand 10 after
5417 nesting_state.CheckCompletedBlocks(filename, error) 5447 nesting_state.CheckCompletedBlocks(filename, error)
5418 5448
5419 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error) 5449 CheckForIncludeWhatYouUse(filename, clean_lines, include_state, error)
5420 5450
5421 # We check here rather than inside ProcessLine so that we see raw 5451 # We check here rather than inside ProcessLine so that we see raw
5422 # lines rather than "cleaned" lines. 5452 # lines rather than "cleaned" lines.
5423 CheckForBadCharacters(filename, lines, error) 5453 CheckForBadCharacters(filename, lines, error)
5424 5454
5425 CheckForNewlineAtEOF(filename, lines, error) 5455 CheckForNewlineAtEOF(filename, lines, error)
5426 5456
5457 def GetConfigOverrideFiles(filename):
5458 """ Looks for CPPLINT.cfg files in the directory containing |filename| and
5459 its parents and returns a list of configuration files found.
5460
5461 Args:
5462 filename: The name of the file being processed by the linter.
5463 """
5464
5465 cfg_override_files = []
5466 abs_path = os.path.abspath(os.path.dirname(filename))
5467
5468 while True:
5469 file = os.path.join(abs_path, "CPPLINT.cfg")
5470 if os.path.isfile(file):
5471 cfg_override_files.append(file)
5472 parent = os.path.dirname(abs_path)
5473 if parent == abs_path:
5474 break
5475 abs_path = parent
5476
5477 return reversed(cfg_override_files)
5478
5479 def ProcessConfigFile(cfg_file, filename):
5480 """ Loads the configuration file and processes the config overrides
sosa 2014/07/23 17:35:00 nit about docstring
Alex Vakulenko (Google) 2014/07/23 19:04:51 Done.
5481 specified in it.
5482
5483 Config file contains a bunch of key=value pairs. Currently
sosa 2014/07/23 17:35:00 This should probably go in the module docstring /
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5484 we are looking only for:
5485 filter=+filter1,-filter2,...
5486 exclude_files=regex
5487
5488 Args:
5489 cfg_file: config file to process
5490 filename: The name of the file being processed by the linter.
5491
5492 Returns:
5493 false if the current |filename| should not be processed further.
5494 """
5495
5496 try:
5497 #lines = codecs.open(cfg_file, 'r', 'utf8', 'replace').read().split('\n')
sosa 2014/07/23 17:35:00 What's the line commented out for?
Alex Vakulenko (Google) 2014/07/23 19:04:50 Just forgot to remove. Done.
5498 with open(cfg_file) as lines:
sosa 2014/07/23 17:35:00 Not completely correct naming. This is the file_ha
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5499 for line in lines:
5500 name, val = line.partition('=')[::2]
sosa 2014/07/23 17:35:00 mmm, this works but not really the correct usage o
Alex Vakulenko (Google) 2014/07/23 19:04:50 I copied this from somewhere. Fixed
5501 name = name.strip()
sosa 2014/07/23 17:35:00 val = val.strip() here
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5502 if name == 'filter':
5503 _AddFilters(val.strip())
5504 elif name == 'exclude_files':
sosa 2014/07/23 17:35:00 Should support comments but also error out for nam
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5505 pattern = re.compile(val.strip())
5506 if pattern.match(filename):
5507 sys.stderr.write('Ignoring %s; file excluded by (%s)\n' %
5508 (filename, cfg_file))
5509 return False
5510
5511 except IOError:
5512 sys.stderr.write(
5513 "Skipping config file '%s': Can't open for reading\n" % cfg_file)
5514 _RestoreFilters()
5515 return True
5516
5517 return True
5518
sosa 2014/07/23 17:35:00 2 lines should separate top-level methods
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5519 def ProcessConfigOverrides(cfg_override_files, filename):
5520 """ Loads the configuration files and processes the config overrides
sosa 2014/07/23 17:35:00 same nit about docstrings.
Alex Vakulenko (Google) 2014/07/23 19:04:50 Done.
5521 specified in those files..
5522
5523 Args:
5524 cfg_override_files: list of cfg files to process
5525 filename: The name of the file being processed by the linter.
5526
5527 Returns:
5528 false if the current |filename| should not be processed further.
5529 """
5530 for cfg_file in cfg_override_files:
5531 if not ProcessConfigFile(cfg_file, filename):
5532 return False
5533
5534 return True
5427 5535
5428 def ProcessFile(filename, vlevel, extra_check_functions=[]): 5536 def ProcessFile(filename, vlevel, extra_check_functions=[]):
5429 """Does google-lint on a single file. 5537 """Does google-lint on a single file.
5430 5538
5431 Args: 5539 Args:
5432 filename: The name of the file to parse. 5540 filename: The name of the file to parse.
5433 5541
5434 vlevel: The level of errors to report. Every error of confidence 5542 vlevel: The level of errors to report. Every error of confidence
5435 >= verbose_level will be reported. 0 is a good default. 5543 >= verbose_level will be reported. 0 is a good default.
5436 5544
5437 extra_check_functions: An array of additional check functions that will be 5545 extra_check_functions: An array of additional check functions that will be
5438 run on each source line. Each function takes 4 5546 run on each source line. Each function takes 4
5439 arguments: filename, clean_lines, line, error 5547 arguments: filename, clean_lines, line, error
5440 """ 5548 """
5441 5549
5442 _SetVerboseLevel(vlevel) 5550 _SetVerboseLevel(vlevel)
5551 _BackupFilters()
5552
5553 cfg_override_files = GetConfigOverrideFiles(filename)
5554 if not ProcessConfigOverrides(cfg_override_files, filename):
5555 _RestoreFilters()
5556 return
5443 5557
5444 lf_lines = [] 5558 lf_lines = []
5445 crlf_lines = [] 5559 crlf_lines = []
5446 try: 5560 try:
5447 # Support the UNIX convention of using "-" for stdin. Note that 5561 # Support the UNIX convention of using "-" for stdin. Note that
5448 # we are not opening the file with universal newline support 5562 # we are not opening the file with universal newline support
5449 # (which codecs doesn't support anyway), so the resulting lines do 5563 # (which codecs doesn't support anyway), so the resulting lines do
5450 # contain trailing '\r' characters if we are reading a file that 5564 # contain trailing '\r' characters if we are reading a file that
5451 # has CRLF endings. 5565 # has CRLF endings.
5452 # If after the split a trailing '\r' is present, it is removed 5566 # 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): 5578 for linenum in range(len(lines) - 1):
5465 if lines[linenum].endswith('\r'): 5579 if lines[linenum].endswith('\r'):
5466 lines[linenum] = lines[linenum].rstrip('\r') 5580 lines[linenum] = lines[linenum].rstrip('\r')
5467 crlf_lines.append(linenum + 1) 5581 crlf_lines.append(linenum + 1)
5468 else: 5582 else:
5469 lf_lines.append(linenum + 1) 5583 lf_lines.append(linenum + 1)
5470 5584
5471 except IOError: 5585 except IOError:
5472 sys.stderr.write( 5586 sys.stderr.write(
5473 "Skipping input '%s': Can't open for reading\n" % filename) 5587 "Skipping input '%s': Can't open for reading\n" % filename)
5588 _RestoreFilters()
5474 return 5589 return
5475 5590
5476 # Note, if no dot is found, this will give the entire filename as the ext. 5591 # Note, if no dot is found, this will give the entire filename as the ext.
5477 file_extension = filename[filename.rfind('.') + 1:] 5592 file_extension = filename[filename.rfind('.') + 1:]
5478 5593
5479 # When reading from stdin, the extension is unknown, so no cpplint tests 5594 # When reading from stdin, the extension is unknown, so no cpplint tests
5480 # should rely on the extension. 5595 # should rely on the extension.
5481 if filename != '-' and file_extension not in _valid_extensions: 5596 if filename != '-' and file_extension not in _valid_extensions:
5482 sys.stderr.write('Ignoring %s; not a valid file name ' 5597 sys.stderr.write('Ignoring %s; not a valid file name '
5483 '(%s)\n' % (filename, ', '.join(_valid_extensions))) 5598 '(%s)\n' % (filename, ', '.join(_valid_extensions)))
(...skipping 13 matching lines...) Expand all
5497 # server-side end-of-line sequence. 5612 # server-side end-of-line sequence.
5498 if lf_lines and crlf_lines: 5613 if lf_lines and crlf_lines:
5499 # Warn on every line with CR. An alternative approach might be to 5614 # 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 5615 # 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. 5616 # minority, we bias toward LF here since most tools prefer LF.
5502 for linenum in crlf_lines: 5617 for linenum in crlf_lines:
5503 Error(filename, linenum, 'whitespace/newline', 1, 5618 Error(filename, linenum, 'whitespace/newline', 1,
5504 'Unexpected \\r (^M) found; better to use only \\n') 5619 'Unexpected \\r (^M) found; better to use only \\n')
5505 5620
5506 sys.stderr.write('Done processing %s\n' % filename) 5621 sys.stderr.write('Done processing %s\n' % filename)
5622 _RestoreFilters()
5507 5623
5508 5624
5509 def PrintUsage(message): 5625 def PrintUsage(message):
5510 """Prints a brief usage string and exits, optionally with an error message. 5626 """Prints a brief usage string and exits, optionally with an error message.
5511 5627
5512 Args: 5628 Args:
5513 message: The optional error message. 5629 message: The optional error message.
5514 """ 5630 """
5515 sys.stderr.write(_USAGE) 5631 sys.stderr.write(_USAGE)
5516 if message: 5632 if message:
(...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after
5611 _cpplint_state.ResetErrorCounts() 5727 _cpplint_state.ResetErrorCounts()
5612 for filename in filenames: 5728 for filename in filenames:
5613 ProcessFile(filename, _cpplint_state.verbose_level) 5729 ProcessFile(filename, _cpplint_state.verbose_level)
5614 _cpplint_state.PrintErrorCounts() 5730 _cpplint_state.PrintErrorCounts()
5615 5731
5616 sys.exit(_cpplint_state.error_count > 0) 5732 sys.exit(_cpplint_state.error_count > 0)
5617 5733
5618 5734
5619 if __name__ == '__main__': 5735 if __name__ == '__main__':
5620 main() 5736 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