From 4d70a88efd4a1d2975481670c1d43341e3a10236 Mon Sep 17 00:00:00 2001 From: "erg@google.com" Date: Tue, 16 Apr 2013 21:06:32 +0000 Subject: [PATCH] Add --root flag used for deriving header guard CPP variable. By default, the header guard CPP variable is calculated as the relative path to the directory that contains .git, .hg, or .svn. When this flag is specified, the relative path is calculated from the specified directory. Patch by mazda@chromium.org CR: https://codereview.appspot.com/8630045/ --- cpplint/cpplint.py | 31 +++++++++++++++++++++++++++++-- cpplint/cpplint_test_header.h | 1 + cpplint/cpplint_unittest.py | 23 +++++++++++++++++++++++ 3 files changed, 53 insertions(+), 2 deletions(-) create mode 100644 cpplint/cpplint_test_header.h diff --git a/cpplint/cpplint.py b/cpplint/cpplint.py index 0445454..159dbbb 100755 --- a/cpplint/cpplint.py +++ b/cpplint/cpplint.py @@ -136,6 +136,22 @@ Syntax: cpplint.py [--verbose=#] [--output=vs7] [--filter=-x,+y,...] the top-level categories like 'build' and 'whitespace' will also be printed. If 'detailed' is provided, then a count is provided for each category like 'build/class'. + + root=subdir + The root directory used for deriving header guard CPP variable. + By default, the header guard CPP variable is calculated as the relative + path to the directory that contains .git, .hg, or .svn. When this flag + is specified, the relative path is calculated from the specified + directory. If the specified directory does not exist, this flag is + ignored. + + Examples: + Assuing that src/.git exists, the header guard CPP variables for + src/chrome/browser/ui/browser.h are: + + No flag => CHROME_BROWSER_UI_BROWSER_H_ + --root=chrome => BROWSER_UI_BROWSER_H_ + --root=chrome/browser => UI_BROWSER_H_ """ # We categorize each error message we print. Here are the categories. @@ -336,6 +352,10 @@ _RE_SUPPRESSION = re.compile(r'\bNOLINT\b(\([^)]*\))?') # on which those errors are expected and should be suppressed. _error_suppressions = {} +# The root directory used for deriving header guard CPP variable. +# This is set by --root flag. +_root = None + def ParseNolintSuppressions(filename, raw_line, linenum, error): """Updates the global list of error-suppressions. @@ -1102,7 +1122,10 @@ def GetHeaderGuardCPPVariable(filename): filename = re.sub(r'/\.flymake/([^/]*)$', r'/\1', filename) fileinfo = FileInfo(filename) - return re.sub(r'[-./\s]', '_', fileinfo.RepositoryName()).upper() + '_' + file_path_from_root = fileinfo.RepositoryName() + if _root: + file_path_from_root = re.sub('^' + _root + os.sep, '', file_path_from_root) + return re.sub(r'[-./\s]', '_', file_path_from_root).upper() + '_' def CheckForHeaderGuard(filename, lines, error): @@ -3933,7 +3956,8 @@ def ParseArguments(args): try: (opts, filenames) = getopt.getopt(args, '', ['help', 'output=', 'verbose=', 'counting=', - 'filter=']) + 'filter=', + 'root=']) except getopt.GetoptError: PrintUsage('Invalid arguments.') @@ -3959,6 +3983,9 @@ def ParseArguments(args): if val not in ('total', 'toplevel', 'detailed'): PrintUsage('Valid counting options are total, toplevel, and detailed') counting_style = val + elif opt == '--root': + global _root + _root = val if not filenames: PrintUsage('No files were specified.') diff --git a/cpplint/cpplint_test_header.h b/cpplint/cpplint_test_header.h new file mode 100644 index 0000000..4307e80 --- /dev/null +++ b/cpplint/cpplint_test_header.h @@ -0,0 +1 @@ +// A test header for cpplint_unittest.py. diff --git a/cpplint/cpplint_unittest.py b/cpplint/cpplint_unittest.py index 907e364..a195e91 100755 --- a/cpplint/cpplint_unittest.py +++ b/cpplint/cpplint_unittest.py @@ -2588,6 +2588,29 @@ class CpplintTest(CpplintTestBase): ' [build/header_guard] [5]' % expected_guard), error_collector.ResultList()) + def testBuildHeaderGuardWithRoot(self): + file_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), + 'cpplint_test_header.h') + file_info = cpplint.FileInfo(file_path) + if file_info.FullName() == file_info.RepositoryName(): + # When FileInfo cannot deduce the root directory of the repository, + # FileInfo.RepositoryName returns the same value as FileInfo.FullName. + # This can happen when this source file was obtained without .svn or + # .git directory. (e.g. using 'svn export' or 'git archive'). + # Skip this test in such a case because --root flag makes sense only + # when the root directory of the repository is properly deduced. + return + + self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + cpplint._root = 'cpplint' + self.assertEquals('CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + # --root flag is ignored if an non-existent directory is specified. + cpplint._root = 'NON_EXISTENT_DIR' + self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_', + cpplint.GetHeaderGuardCPPVariable(file_path)) + def testBuildInclude(self): # Test that include statements have slashes in them. self.TestLint('#include "foo.h"',