Chromium Code Reviews| Index: cpplint.py |
| diff --git a/cpplint.py b/cpplint.py |
| index 92384dc37181f6e982d0e6f74afe93d393c5de19..640ae08bfbac87a781a3a0e3e1a57600b601acc1 100755 |
| --- a/cpplint.py |
| +++ b/cpplint.py |
| @@ -682,6 +682,8 @@ class _CppLintState(object): |
| self.error_count = 0 # global count of reported errors |
| # filters to apply when emitting error messages |
| self.filters = _DEFAULT_FILTERS[:] |
| + # 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.
|
| + self.filters_backup = self.filters[:] |
| self.counting = 'total' # In what way are we counting errors? |
| self.errors_by_category = {} # string to int dict storing error counts |
| @@ -720,6 +722,10 @@ class _CppLintState(object): |
| """ |
| # Default filters always have less priority than the flag ones. |
| self.filters = _DEFAULT_FILTERS[:] |
| + self.AddFilters(filters) |
| + |
| + def AddFilters(self, filters): |
| + """ Adds more filters to the existing list of error-message filters. """ |
| for filt in filters.split(','): |
| clean_filt = filt.strip() |
| if clean_filt: |
| @@ -729,6 +735,14 @@ class _CppLintState(object): |
| raise ValueError('Every filter in --filters must start with + or -' |
| ' (%s does not)' % filt) |
| + def BackupFilters(self): |
| + """ Saves the current filter list to backup storage.""" |
| + self.filters_backup = self.filters[:] |
| + |
| + def RestoreFilters(self): |
| + """ Restores filters previously backed up.""" |
| + self.filters = self.filters_backup[:] |
| + |
| def ResetErrorCounts(self): |
| """Sets the module's error statistic back to zero.""" |
| self.error_count = 0 |
| @@ -796,6 +810,22 @@ def _SetFilters(filters): |
| """ |
| _cpplint_state.SetFilters(filters) |
| +def _AddFilters(filters): |
| + """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.
|
| + reset the current list of filters available. |
| + Args: |
| + filters: A string of comma-separated filters (eg "whitespace/indent"). |
| + Each filter should start with + or -; else we die. |
| + """ |
| + _cpplint_state.AddFilters(filters) |
| + |
| +def _BackupFilters(): |
| + """ Saves the current filter list to backup storage.""" |
| + _cpplint_state.BackupFilters() |
| + |
| +def _RestoreFilters(): |
| + """ Restores filters previously backed up.""" |
| + _cpplint_state.RestoreFilters() |
| class _FunctionState(object): |
| """Tracks current function name and the number of lines in its body.""" |
| @@ -5424,6 +5454,84 @@ def ProcessFileData(filename, file_extension, lines, error, |
| CheckForNewlineAtEOF(filename, lines, error) |
| +def GetConfigOverrideFiles(filename): |
| + """ Looks for CPPLINT.cfg files in the directory containing |filename| and |
| + its parents and returns a list of configuration files found. |
| + |
| + Args: |
| + filename: The name of the file being processed by the linter. |
| + """ |
| + |
| + cfg_override_files = [] |
| + abs_path = os.path.abspath(os.path.dirname(filename)) |
| + |
| + while True: |
| + file = os.path.join(abs_path, "CPPLINT.cfg") |
| + if os.path.isfile(file): |
| + cfg_override_files.append(file) |
| + parent = os.path.dirname(abs_path) |
| + if parent == abs_path: |
| + break |
| + abs_path = parent |
| + |
| + return reversed(cfg_override_files) |
| + |
| +def ProcessConfigFile(cfg_file, filename): |
| + """ 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.
|
| + specified in it. |
| + |
| + 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.
|
| + we are looking only for: |
| + filter=+filter1,-filter2,... |
| + exclude_files=regex |
| + |
| + Args: |
| + cfg_file: config file to process |
| + filename: The name of the file being processed by the linter. |
| + |
| + Returns: |
| + false if the current |filename| should not be processed further. |
| + """ |
| + |
| + try: |
| + #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.
|
| + 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.
|
| + for line in lines: |
| + 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
|
| + name = name.strip() |
|
sosa
2014/07/23 17:35:00
val = val.strip() here
Alex Vakulenko (Google)
2014/07/23 19:04:50
Done.
|
| + if name == 'filter': |
| + _AddFilters(val.strip()) |
| + 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.
|
| + pattern = re.compile(val.strip()) |
| + if pattern.match(filename): |
| + sys.stderr.write('Ignoring %s; file excluded by (%s)\n' % |
| + (filename, cfg_file)) |
| + return False |
| + |
| + except IOError: |
| + sys.stderr.write( |
| + "Skipping config file '%s': Can't open for reading\n" % cfg_file) |
| + _RestoreFilters() |
| + return True |
| + |
| + return True |
| + |
|
sosa
2014/07/23 17:35:00
2 lines should separate top-level methods
Alex Vakulenko (Google)
2014/07/23 19:04:50
Done.
|
| +def ProcessConfigOverrides(cfg_override_files, filename): |
| + """ 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.
|
| + specified in those files.. |
| + |
| + Args: |
| + cfg_override_files: list of cfg files to process |
| + filename: The name of the file being processed by the linter. |
| + |
| + Returns: |
| + false if the current |filename| should not be processed further. |
| + """ |
| + for cfg_file in cfg_override_files: |
| + if not ProcessConfigFile(cfg_file, filename): |
| + return False |
| + |
| + return True |
| def ProcessFile(filename, vlevel, extra_check_functions=[]): |
| """Does google-lint on a single file. |
| @@ -5440,6 +5548,12 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): |
| """ |
| _SetVerboseLevel(vlevel) |
| + _BackupFilters() |
| + |
| + cfg_override_files = GetConfigOverrideFiles(filename) |
| + if not ProcessConfigOverrides(cfg_override_files, filename): |
| + _RestoreFilters() |
| + return |
| lf_lines = [] |
| crlf_lines = [] |
| @@ -5471,6 +5585,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): |
| except IOError: |
| sys.stderr.write( |
| "Skipping input '%s': Can't open for reading\n" % filename) |
| + _RestoreFilters() |
| return |
| # Note, if no dot is found, this will give the entire filename as the ext. |
| @@ -5504,6 +5619,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]): |
| 'Unexpected \\r (^M) found; better to use only \\n') |
| sys.stderr.write('Done processing %s\n' % filename) |
| + _RestoreFilters() |
| def PrintUsage(message): |