Skip to content

Commit 2eef70d

Browse files
authored
Allow specifying _third_party_headers_pattern (#388)
1 parent c2b1ce6 commit 2eef70d

File tree

2 files changed

+83
-11
lines changed

2 files changed

+83
-11
lines changed

cpplint.py

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@
6868
[--filter=-x,+y,...]
6969
[--counting=total|toplevel|detailed] [--root=subdir]
7070
[--repository=path]
71-
[--linelength=digits] [--headers=x,y,...]
71+
[--linelength=digits] [--headers=x,y,...] [--third_party_headers=pattern]
7272
[--recursive]
7373
[--exclude=path]
7474
[--extensions=hpp,cpp,...]
@@ -240,6 +240,8 @@
240240
The header extensions that cpplint will treat as .h in checks. Values are
241241
automatically added to --extensions list.
242242
(by default, only files with extensions %s will be assumed to be headers)
243+
third_party_headers=pattern
244+
Regex for identifying third-party headers to exclude from include checks.
243245
244246
Examples:
245247
--headers=%s
@@ -256,6 +258,7 @@
256258
linelength=80
257259
root=subdir
258260
headers=x,y,...
261+
third_party_headers=pattern
259262
260263
"set noparent" option prevents cpplint from traversing directory tree
261264
upwards looking for more .cfg files in parent directories. This option
@@ -812,14 +815,6 @@
812815
r")$"
813816
)
814817

815-
816-
# These headers are excluded from [build/include] and [build/include_order]
817-
# checks:
818-
# - Anything not following google file name conventions (containing an
819-
# uppercase character, such as Python.h or nsStringAPI.h, for example).
820-
# - Lua headers.
821-
_THIRD_PARTY_HEADERS_PATTERN = re.compile(r"^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$")
822-
823818
# Pattern for matching FileInfo.BaseName() against test file name
824819
_test_suffixes = ["_test", "_regtest", "_unittest"]
825820
_TEST_FILE_SUFFIX = "(" + "|".join(_test_suffixes) + r")$"
@@ -981,6 +976,16 @@
981976
# This is set by --headers flag.
982977
_hpp_headers: set[str] = set()
983978

979+
# These headers are excluded from [build/include_subdir], [build/include_order], and
980+
# [build/include_alpha]
981+
# The default checks are following
982+
# - Anything not following google file name conventions (containing an
983+
# uppercase character, such as Python.h or nsStringAPI.h, for example).
984+
# - Lua headers.
985+
# Default pattern for third-party headers (uppercase .h or Lua headers).
986+
_THIRD_PARTY_HEADERS_DEFAULT = r"^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$"
987+
_third_party_headers_pattern = re.compile(_THIRD_PARTY_HEADERS_DEFAULT)
988+
984989

985990
class ErrorSuppressions:
986991
"""Class to track all error suppressions for cpplint"""
@@ -1072,6 +1077,15 @@ def ProcessIncludeOrderOption(val):
10721077
PrintUsage("Invalid includeorder value %s. Expected default|standardcfirst")
10731078

10741079

1080+
def ProcessThirdPartyHeadersOption(val):
1081+
"""Sets the regex pattern for third-party headers."""
1082+
global _third_party_headers_pattern
1083+
try:
1084+
_third_party_headers_pattern = re.compile(val)
1085+
except re.error:
1086+
PrintUsage(f"Invalid third_party_headers pattern: {val}")
1087+
1088+
10751089
def IsHeaderExtension(file_extension):
10761090
return file_extension in GetHeaderExtensions()
10771091

@@ -5744,7 +5758,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
57445758
if (
57455759
match
57465760
and IsHeaderExtension(match.group(2))
5747-
and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1))
5761+
and not _third_party_headers_pattern.match(match.group(1))
57485762
):
57495763
error(
57505764
filename,
@@ -5797,7 +5811,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
57975811
third_src_header = True
57985812
break
57995813

5800-
if third_src_header or not _THIRD_PARTY_HEADERS_PATTERN.match(include):
5814+
if third_src_header or not _third_party_headers_pattern.match(include):
58015815
include_state.include_list[-1].append((include, linenum))
58025816

58035817
# We want to ensure that headers appear in the right order:
@@ -7527,6 +7541,8 @@ def ProcessConfigOverrides(filename):
75277541
_root = os.path.join(os.path.dirname(cfg_file), val)
75287542
elif name == "headers":
75297543
ProcessHppHeadersOption(val)
7544+
elif name == "third_party_headers":
7545+
ProcessThirdPartyHeadersOption(val)
75307546
elif name == "includeorder":
75317547
ProcessIncludeOrderOption(val)
75327548
else:
@@ -7711,6 +7727,7 @@ def ParseArguments(args):
77117727
"exclude=",
77127728
"recursive",
77137729
"headers=",
7730+
"third_party_headers=",
77147731
"includeorder=",
77157732
"config=",
77167733
"quiet",
@@ -7770,6 +7787,8 @@ def ParseArguments(args):
77707787
ProcessExtensionsOption(val)
77717788
elif opt == "--headers":
77727789
ProcessHppHeadersOption(val)
7790+
elif opt == "--third_party_headers":
7791+
ProcessThirdPartyHeadersOption(val)
77737792
elif opt == "--recursive":
77747793
recursive = True
77757794
elif opt == "--includeorder":

cpplint_clitest.py

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import subprocess
3838
import sys
3939
import tempfile
40+
import textwrap
4041

4142
import pytest
4243
from testfixtures import compare # type: ignore[import-untyped]
@@ -224,5 +225,57 @@ def test_codelite_sample(self):
224225
self.check_all_in_folder("./samples/codelite-sample", 1)
225226

226227

228+
# Tests for third_party_headers option
229+
def test_third_party_headers_default(tmp_path):
230+
# By default, headers with uppercase letters are treated as third-party and not flagged
231+
cpp = tmp_path / "test.cpp"
232+
cpp.write_text(
233+
textwrap.dedent("""
234+
// Copyright 2025 cpplint
235+
#include "Foo.h"
236+
int main() { return 0; }
237+
""")
238+
)
239+
status, out, err = run_shell_command(BASE_CMD, f"{cpp.name}", cwd=str(tmp_path))
240+
assert status == 0, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
241+
# No include_subdir warning
242+
assert b"build/include_subdir" not in err
243+
244+
245+
def test_third_party_headers_override(tmp_path):
246+
# Override third_party_headers so Foo.h is not recognized as third-party
247+
cpp = tmp_path / "test.cpp"
248+
cpp.write_text(
249+
textwrap.dedent("""
250+
// Copyright 2025 cpplint
251+
#include "Foo.h"
252+
""")
253+
)
254+
# Use a pattern that matches nothing
255+
flag = "--third_party_headers=^Bar.h$"
256+
status, out, err = run_shell_command(BASE_CMD, f"{flag} {cpp.name}", cwd=str(tmp_path))
257+
# Expect a warning about include_subdir
258+
assert status == 1, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
259+
assert b"build/include_subdir" in err
260+
261+
262+
def test_third_party_headers_config(tmp_path):
263+
# Override third_party_headers via config file so Foo.h is not recognized as third-party
264+
cpp = tmp_path / "test.cpp"
265+
cpp.write_text(
266+
textwrap.dedent("""
267+
// Copyright 2025 cpplint
268+
#include "Foo.h"
269+
""")
270+
)
271+
# Write configuration file to override third_party_headers
272+
config = tmp_path / "CPPLINT.cfg"
273+
config.write_text("third_party_headers=^Bar.h$\n")
274+
status, out, err = run_shell_command(BASE_CMD, f"{cpp.name}", cwd=str(tmp_path))
275+
# Expect a warning about include_subdir due to override
276+
assert status == 1, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
277+
assert b"build/include_subdir" in err
278+
279+
227280
if __name__ == "__main__":
228281
pytest.main([__file__])

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy