Merge pull request #293 from iam/cpplint_quiet

cpplint: add --quiet flag to suppress all output when there's no errors
This commit is contained in:
Mark Mentovai 2017-11-10 17:54:14 -05:00 committed by GitHub
commit 58e2a524cd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 114 additions and 3 deletions

35
cpplint/cpplint.py vendored
View File

@ -57,6 +57,7 @@ _USAGE = """
Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
[--counting=total|toplevel|detailed] [--root=subdir] [--counting=total|toplevel|detailed] [--root=subdir]
[--linelength=digits] [--headers=x,y,...] [--linelength=digits] [--headers=x,y,...]
[--quiet]
<file> [file] ... <file> [file] ...
The style guidelines this tries to follow are those in The style guidelines this tries to follow are those in
@ -83,6 +84,9 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...]
verbose=# verbose=#
Specify a number 0-5 to restrict errors to certain verbosity levels. Specify a number 0-5 to restrict errors to certain verbosity levels.
quiet
Don't print anything if no errors are found.
filter=-x,+y,... filter=-x,+y,...
Specify a comma-separated list of category-filters to apply: only Specify a comma-separated list of category-filters to apply: only
error messages whose category names pass the filters will be printed. error messages whose category names pass the filters will be printed.
@ -861,6 +865,7 @@ class _CppLintState(object):
self._filters_backup = self.filters[:] self._filters_backup = self.filters[:]
self.counting = 'total' # In what way are we counting errors? self.counting = 'total' # In what way are we counting errors?
self.errors_by_category = {} # string to int dict storing error counts self.errors_by_category = {} # string to int dict storing error counts
self.quiet = False # Suppress non-error messagess?
# output format: # output format:
# "emacs" - format that emacs can parse (default) # "emacs" - format that emacs can parse (default)
@ -871,6 +876,12 @@ class _CppLintState(object):
"""Sets the output format for errors.""" """Sets the output format for errors."""
self.output_format = output_format self.output_format = output_format
def SetQuiet(self, quiet):
"""Sets the module's quiet settings, and returns the previous setting."""
last_quiet = self.quiet
self.quiet = quiet
return last_quiet
def SetVerboseLevel(self, level): def SetVerboseLevel(self, level):
"""Sets the module's verbosity, and returns the previous setting.""" """Sets the module's verbosity, and returns the previous setting."""
last_verbose_level = self.verbose_level last_verbose_level = self.verbose_level
@ -952,6 +963,14 @@ def _SetOutputFormat(output_format):
"""Sets the module's output format.""" """Sets the module's output format."""
_cpplint_state.SetOutputFormat(output_format) _cpplint_state.SetOutputFormat(output_format)
def _Quiet():
"""Return's the module's quiet setting."""
return _cpplint_state.quiet
def _SetQuiet(quiet):
"""Set the module's quiet status, and return previous setting."""
return _cpplint_state.SetQuiet(quiet)
def _VerboseLevel(): def _VerboseLevel():
"""Returns the module's verbosity setting.""" """Returns the module's verbosity setting."""
@ -5955,6 +5974,9 @@ def ProcessConfigOverrides(filename):
if base_name: if base_name:
pattern = re.compile(val) pattern = re.compile(val)
if pattern.match(base_name): if pattern.match(base_name):
if _cpplint_state.quiet:
# Suppress "Ignoring file" warning when using --quiet.
return False
sys.stderr.write('Ignoring "%s": file excluded by "%s". ' sys.stderr.write('Ignoring "%s": file excluded by "%s". '
'File path component "%s" matches ' 'File path component "%s" matches '
'pattern "%s"\n' % 'pattern "%s"\n' %
@ -6006,6 +6028,7 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
_SetVerboseLevel(vlevel) _SetVerboseLevel(vlevel)
_BackupFilters() _BackupFilters()
old_errors = _cpplint_state.error_count
if not ProcessConfigOverrides(filename): if not ProcessConfigOverrides(filename):
_RestoreFilters() _RestoreFilters()
@ -6074,6 +6097,9 @@ def ProcessFile(filename, vlevel, extra_check_functions=[]):
Error(filename, linenum, 'whitespace/newline', 1, Error(filename, linenum, 'whitespace/newline', 1,
'Unexpected \\r (^M) found; better to use only \\n') 'Unexpected \\r (^M) found; better to use only \\n')
# Suppress printing anything if --quiet was passed unless the error
# count has increased after processing this file.
if not _cpplint_state.quiet or old_errors != _cpplint_state.error_count:
sys.stdout.write('Done processing %s\n' % filename) sys.stdout.write('Done processing %s\n' % filename)
_RestoreFilters() _RestoreFilters()
@ -6118,13 +6144,15 @@ def ParseArguments(args):
'root=', 'root=',
'linelength=', 'linelength=',
'extensions=', 'extensions=',
'headers=']) 'headers=',
'quiet'])
except getopt.GetoptError: except getopt.GetoptError:
PrintUsage('Invalid arguments.') PrintUsage('Invalid arguments.')
verbosity = _VerboseLevel() verbosity = _VerboseLevel()
output_format = _OutputFormat() output_format = _OutputFormat()
filters = '' filters = ''
quiet = _Quiet()
counting_style = '' counting_style = ''
for (opt, val) in opts: for (opt, val) in opts:
@ -6134,6 +6162,8 @@ def ParseArguments(args):
if val not in ('emacs', 'vs7', 'eclipse'): if val not in ('emacs', 'vs7', 'eclipse'):
PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.') PrintUsage('The only allowed output formats are emacs, vs7 and eclipse.')
output_format = val output_format = val
elif opt == '--quiet':
quiet = True
elif opt == '--verbose': elif opt == '--verbose':
verbosity = int(val) verbosity = int(val)
elif opt == '--filter': elif opt == '--filter':
@ -6166,6 +6196,7 @@ def ParseArguments(args):
PrintUsage('No files were specified.') PrintUsage('No files were specified.')
_SetOutputFormat(output_format) _SetOutputFormat(output_format)
_SetQuiet(quiet)
_SetVerboseLevel(verbosity) _SetVerboseLevel(verbosity)
_SetFilters(filters) _SetFilters(filters)
_SetCountingStyle(counting_style) _SetCountingStyle(counting_style)
@ -6186,6 +6217,8 @@ def main():
_cpplint_state.ResetErrorCounts() _cpplint_state.ResetErrorCounts()
for filename in filenames: for filename in filenames:
ProcessFile(filename, _cpplint_state.verbose_level) ProcessFile(filename, _cpplint_state.verbose_level)
# If --quiet is passed, suppress printing error count unless there are errors.
if not _cpplint_state.quiet or _cpplint_state.error_count > 0:
_cpplint_state.PrintErrorCounts() _cpplint_state.PrintErrorCounts()
sys.exit(_cpplint_state.error_count > 0) sys.exit(_cpplint_state.error_count > 0)

View File

@ -37,6 +37,7 @@ import codecs
import os import os
import random import random
import re import re
import subprocess
import sys import sys
import unittest import unittest
@ -5686,6 +5687,83 @@ class NestingStateTest(unittest.TestCase):
self.assertEquals(len(self.nesting_state.stack), 0) self.assertEquals(len(self.nesting_state.stack), 0)
class QuietTest(unittest.TestCase):
def setUp(self):
self.this_dir_path = os.path.dirname(os.path.abspath(__file__))
self.python_executable = sys.executable or 'python'
self.cpplint_test_h = os.path.join(self.this_dir_path,
'cpplint_test_header.h')
def _runCppLint(self, *args):
cpplint_abspath = os.path.join(self.this_dir_path, 'cpplint.py')
cmd_line = [self.python_executable, cpplint_abspath] + \
list(args) + \
[ self.cpplint_test_h ]
return_code = 0
try:
output = subprocess.check_output(cmd_line,
stderr=subprocess.STDOUT)
except subprocess.CalledProcessError as err:
return_code = err.returncode
output = err.output
return (return_code, output)
def testNonQuietWithErrors(self):
# This will fail: the test header is missing a copyright and header guard.
(return_code, output) = self._runCppLint()
self.assertEquals(1, return_code)
# Always-on behavior: Print error messages as they come up.
self.assertIn("[legal/copyright]", output)
self.assertIn("[build/header_guard]", output)
# If --quiet was unspecified: Print 'Done processing' and 'Total errors..'
self.assertIn("Done processing", output)
self.assertIn("Total errors found:", output)
def testQuietWithErrors(self):
# When there are errors, behavior is identical to not passing --quiet.
(return_code, output) = self._runCppLint('--quiet')
self.assertEquals(1, return_code)
self.assertIn("[legal/copyright]", output)
self.assertIn("[build/header_guard]", output)
# Even though --quiet was used, print these since there were errors.
self.assertIn("Done processing", output)
self.assertIn("Total errors found:", output)
def testNonQuietWithoutErrors(self):
# This will succeed. We filtered out all the known errors for that file.
(return_code, output) = self._runCppLint('--filter=' +
'-legal/copyright,' +
'-build/header_guard')
self.assertEquals(0, return_code, output)
# No cpplint errors are printed since there were no errors.
self.assertNotIn("[legal/copyright]", output)
self.assertNotIn("[build/header_guard]", output)
# Print 'Done processing' and 'Total errors found' since
# --quiet was not specified.
self.assertIn("Done processing", output)
self.assertIn("Total errors found:", output)
def testQuietWithoutErrors(self):
# This will succeed. We filtered out all the known errors for that file.
(return_code, output) = self._runCppLint('--quiet',
'--filter=' +
'-legal/copyright,' +
'-build/header_guard')
self.assertEquals(0, return_code, output)
# No cpplint errors are printed since there were no errors.
self.assertNotIn("[legal/copyright]", output)
self.assertNotIn("[build/header_guard]", output)
# --quiet was specified and there were no errors:
# skip the printing of 'Done processing' and 'Total errors..'
self.assertNotIn("Done processing", output)
self.assertNotIn("Total errors found:", output)
# Output with no errors must be completely blank!
self.assertEquals("", output)
# pylint: disable-msg=C6409 # pylint: disable-msg=C6409
def setUp(): def setUp():
"""Runs before all tests are executed. """Runs before all tests are executed.