Skip to content

Commit e7ddd2a

Browse files
committed
cpplint --root: support non-subdirectories
Using cpplint.py --root with directories at a more outer level will now prepend the header guard with all the directories from the root to the file. For example given ls /a/b/c # /a/b/c/.git /a/b/c/filename.h cpplint.py --root=/a/b /a/b/c/filename.h # C_FILENAME_H_ # no root behavior: cpplint.py /a/b/c/filename.h # FILENAME_H_ Also supports relative paths: cd /a/b/c cpplint.py --root=.. filename.h # C_FILENAME_H_ Note that the old usage is still supported: cd /a/b/c mkdir -p d/e/f touch /a/b/c/d/e/f/filename.h cpplint.py --root=d/e/f d/e/f/filename.h # FILENAME_H_ which would "strip" the prefix rather than prepend an extra prefix. (Invalid root prefixes are as before also ignored)
1 parent ec88ff9 commit e7ddd2a

File tree

2 files changed

+108
-7
lines changed

2 files changed

+108
-7
lines changed

cpplint/cpplint.py

Lines changed: 57 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1754,6 +1754,30 @@ def GetIndentLevel(line):
17541754
else:
17551755
return 0
17561756

1757+
def PathSplitToList(path):
1758+
"""Returns the path split into a list by the separator.
1759+
1760+
Args:
1761+
path: An absolute or relative path (e.g. '/a/b/c/' or '../a')
1762+
1763+
Returns:
1764+
A list of path components (e.g. ['a', 'b', 'c]).
1765+
"""
1766+
lst = []
1767+
while True:
1768+
(head, tail) = os.path.split(path)
1769+
if head == path: # absolute paths end
1770+
lst.append(head)
1771+
break
1772+
if tail == path: # relative paths end
1773+
lst.append(tail)
1774+
break
1775+
1776+
path = head
1777+
lst.append(tail)
1778+
1779+
lst.reverse()
1780+
return lst
17571781

17581782
def GetHeaderGuardCPPVariable(filename):
17591783
"""Returns the CPP variable that should be used as a header guard.
@@ -1776,13 +1800,39 @@ def GetHeaderGuardCPPVariable(filename):
17761800

17771801
fileinfo = FileInfo(filename)
17781802
file_path_from_root = fileinfo.RepositoryName()
1779-
if _root:
1780-
suffix = os.sep
1781-
# On Windows using directory separator will leave us with
1782-
# "bogus escape error" unless we properly escape regex.
1783-
if suffix == '\\':
1784-
suffix += '\\'
1785-
file_path_from_root = re.sub('^' + _root + suffix, '', file_path_from_root)
1803+
1804+
def FixupPathFromRoot():
1805+
# Process the file path with the --root flag if it was set.
1806+
if not _root:
1807+
return file_path_from_root
1808+
1809+
def StripListPrefix(lst, prefix):
1810+
# f(['x', 'y'], ['w, z']) -> None (not a valid prefix)
1811+
if lst[:len(prefix)] != prefix:
1812+
return None
1813+
# f(['a, 'b', 'c', 'd'], ['a', 'b']) -> ['c', 'd']
1814+
return lst[(len(prefix)):]
1815+
1816+
# root behavior:
1817+
# --root=subdir , lstrips subdir from the header guard
1818+
maybe_path = StripListPrefix(PathSplitToList(file_path_from_root),
1819+
PathSplitToList(_root))
1820+
if maybe_path:
1821+
return os.path.join(*maybe_path)
1822+
1823+
# --root=.. , will prepend the outer directory to the header guard
1824+
full_path = fileinfo.FullName()
1825+
root_abspath = os.path.abspath(_root)
1826+
1827+
maybe_path = StripListPrefix(PathSplitToList(full_path),
1828+
PathSplitToList(root_abspath))
1829+
if maybe_path:
1830+
return os.path.join(*maybe_path)
1831+
1832+
# --root=FAKE_DIR is ignored
1833+
return file_path_from_root
1834+
1835+
file_path_from_root = FixupPathFromRoot()
17861836
return re.sub(r'[^a-zA-Z0-9]', '_', file_path_from_root).upper() + '_'
17871837

17881838

cpplint/cpplint_unittest.py

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4232,6 +4232,12 @@ def testBuildHeaderGuardWithRoot(self):
42324232

42334233
self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
42344234
cpplint.GetHeaderGuardCPPVariable(file_path))
4235+
#
4236+
# test --root flags:
4237+
# this changes the cpp header guard prefix
4238+
#
4239+
4240+
# left-strip the header guard by using a root dir inside of the repo dir.
42354241
cpplint._root = 'cpplint'
42364242
self.assertEquals('CPPLINT_TEST_HEADER_H_',
42374243
cpplint.GetHeaderGuardCPPVariable(file_path))
@@ -4240,6 +4246,51 @@ def testBuildHeaderGuardWithRoot(self):
42404246
self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
42414247
cpplint.GetHeaderGuardCPPVariable(file_path))
42424248

4249+
# prepend to the header guard by using a root dir that is more outer
4250+
# than the repo dir
4251+
4252+
# (using absolute paths)
4253+
this_files_path = os.path.dirname(os.path.abspath(__file__))
4254+
(styleguide_path, this_files_dir) = os.path.split(this_files_path)
4255+
(styleguide_parent_path, _) = os.path.split(styleguide_path)
4256+
# parent dir of styleguide
4257+
cpplint._root = styleguide_parent_path
4258+
self.assertIsNotNone(styleguide_parent_path)
4259+
# do not have 'styleguide' repo in '/'
4260+
self.assertEquals('STYLEGUIDE_CPPLINT_CPPLINT_TEST_HEADER_H_',
4261+
cpplint.GetHeaderGuardCPPVariable(file_path))
4262+
4263+
# (using relative paths)
4264+
styleguide_rel_path = os.path.relpath(styleguide_path, this_files_path)
4265+
# '..'
4266+
cpplint._root = styleguide_rel_path
4267+
self.assertEquals('CPPLINT_CPPLINT_TEST_HEADER_H_',
4268+
cpplint.GetHeaderGuardCPPVariable(file_path))
4269+
4270+
styleguide_rel_path = os.path.relpath(styleguide_parent_path,
4271+
this_files_path) # '../..'
4272+
cpplint._root = styleguide_rel_path
4273+
self.assertEquals('STYLEGUIDE_CPPLINT_CPPLINT_TEST_HEADER_H_',
4274+
cpplint.GetHeaderGuardCPPVariable(file_path))
4275+
4276+
cpplint._root = None
4277+
4278+
def testPathSplitToList(self):
4279+
self.assertEquals([''],
4280+
cpplint.PathSplitToList(os.path.join('')))
4281+
4282+
self.assertEquals(['.'],
4283+
cpplint.PathSplitToList(os.path.join('.')))
4284+
4285+
self.assertEquals(['..'],
4286+
cpplint.PathSplitToList(os.path.join('..')))
4287+
4288+
self.assertEquals(['..', 'a', 'b'],
4289+
cpplint.PathSplitToList(os.path.join('..', 'a', 'b')))
4290+
4291+
self.assertEquals(['a', 'b', 'c', 'd'],
4292+
cpplint.PathSplitToList(os.path.join('a', 'b', 'c', 'd')))
4293+
42434294
def testBuildInclude(self):
42444295
# Test that include statements have slashes in them.
42454296
self.TestLint('#include "foo.h"',

0 commit comments

Comments
 (0)