Chromium Code Reviews| Index: cpplint.py |
| diff --git a/cpplint.py b/cpplint.py |
| index 92384dc37181f6e982d0e6f74afe93d393c5de19..65e2b4259217663e6c50ad2d4e700aec80938419 100755 |
| --- a/cpplint.py |
| +++ b/cpplint.py |
| @@ -133,6 +133,33 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] |
| Examples: |
| --extensions=hpp,cpp |
| + |
| + cpplint.py supports per-directory configurations specified in CPPLINT.cfg |
| + files. CPPLINT.cfg file can contain a number of key=value pairs. |
| + Currently the following options are supported: |
| + |
| + filter=+filter1,-filter2,... |
| + exclude_files=regex |
| + |
| + The "filter" option is similar in function to --filter flag. It specifies |
| + message filters in addition to the |_DEFAULT_FILTERS| and those specified |
| + through --filter command-line flag. |
| + |
| + "exclude_files" allows to specify a regular expression to be matched against |
| + a file name. If the expression matches, the file is skipped and not run |
| + through liner. |
| + |
| + CPPLINT.cfg has an effect on files in the same directory and all |
| + sub-directories, unless overridden by a nested configuration file. |
| + |
| + Example file: |
| + filter=-build/include_order,+build/include_alpha |
| + exclude_files=.*\.cc |
| + |
| + The above example disables build/include_order warning and enables |
| + build/include_alpha as well as excludes all .cc from being |
| + processed by linter, in the current directory (where the .cfg |
| + file is located) and all sub-directories. |
| """ |
| # We categorize each error message we print. Here are the categories. |
| @@ -682,6 +709,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. |
| + 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 +749,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 +762,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 +837,25 @@ def _SetFilters(filters): |
| """ |
| _cpplint_state.SetFilters(filters) |
| +def _AddFilters(filters): |
| + """Adds more filter overrides. |
| + |
| + Unlike _SetFilters, this function does not 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.""" |
| @@ -5328,7 +5388,7 @@ def ProcessLine(filename, file_extension, clean_lines, line, |
| CheckDefaultLambdaCaptures(filename, clean_lines, line, error) |
| for check_fn in extra_check_functions: |
| check_fn(filename, clean_lines, line, error) |
| - |
| + |
| def FlagCxx11Features(filename, clean_lines, linenum, error): |
| """Flag those c++11 features that we only allow in certain places. |
| @@ -5424,6 +5484,83 @@ 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 |
|
sosa
2014/07/23 20:25:42
docstring issue
Alex Vakulenko (Google)
2014/07/23 20:44:32
Done.
|
| + 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. |
| + |
| + 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: |
| + with open(cfg_file) as file_handle: |
| + for line in file_handle: |
| + line, _, _ = line.partition('#') # Remove comments. |
| + if line.strip(): |
| + name, _, val = line.partition('=') |
| + name = name.strip() |
| + val = val.strip() |
| + if name == 'filter': |
| + _AddFilters(val) |
| + elif name == 'exclude_files': |
| + pattern = re.compile(val) |
| + if pattern.match(filename): |
| + sys.stderr.write('Ignoring %s; file excluded by (%s)\n' % |
| + (filename, cfg_file)) |
| + return False |
| + else: |
| + sys.stderr.write('Invalid configuration option (%s) in file %s\n' % |
| + (name, cfg_file)) |
| + |
| + except IOError: |
| + sys.stderr.write( |
| + "Skipping config file '%s': Can't open for reading\n" % cfg_file) |
| + _RestoreFilters() |
| + return True |
| + |
| + return True |
| + |
| + |
| +def ProcessConfigOverrides(cfg_override_files, filename): |
| + """ Loads the configuration files and processes the config overrides. |
| + |
| + 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 +5577,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 +5614,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 +5648,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): |