Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Specify Third Party Headers #388

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 30 additions & 11 deletions cpplint.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@
[--filter=-x,+y,...]
[--counting=total|toplevel|detailed] [--root=subdir]
[--repository=path]
[--linelength=digits] [--headers=x,y,...]
[--linelength=digits] [--headers=x,y,...] [--third_party_headers=pattern]
[--recursive]
[--exclude=path]
[--extensions=hpp,cpp,...]
Expand Down Expand Up @@ -240,6 +240,8 @@
The header extensions that cpplint will treat as .h in checks. Values are
automatically added to --extensions list.
(by default, only files with extensions %s will be assumed to be headers)
third_party_headers=pattern
Regex for identifying third-party headers to exclude from include checks.

Examples:
--headers=%s
Expand All @@ -256,6 +258,7 @@
linelength=80
root=subdir
headers=x,y,...
third_party_headers=pattern

"set noparent" option prevents cpplint from traversing directory tree
upwards looking for more .cfg files in parent directories. This option
Expand Down Expand Up @@ -812,14 +815,6 @@
r")$"
)


# These headers are excluded from [build/include] and [build/include_order]
# checks:
# - Anything not following google file name conventions (containing an
# uppercase character, such as Python.h or nsStringAPI.h, for example).
# - Lua headers.
_THIRD_PARTY_HEADERS_PATTERN = re.compile(r"^(?:[^/]*[A-Z][^/]*\.h|lua\.h|lauxlib\.h|lualib\.h)$")

# Pattern for matching FileInfo.BaseName() against test file name
_test_suffixes = ["_test", "_regtest", "_unittest"]
_TEST_FILE_SUFFIX = "(" + "|".join(_test_suffixes) + r")$"
Expand Down Expand Up @@ -981,6 +976,16 @@
# This is set by --headers flag.
_hpp_headers: set[str] = set()

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


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


def ProcessThirdPartyHeadersOption(val):
"""Sets the regex pattern for third-party headers."""
global _third_party_headers_pattern
try:
_third_party_headers_pattern = re.compile(val)
except re.error:
PrintUsage(f"Invalid third_party_headers pattern: {val}")


def IsHeaderExtension(file_extension):
return file_extension in GetHeaderExtensions()

Expand Down Expand Up @@ -5744,7 +5758,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
if (
match
and IsHeaderExtension(match.group(2))
and not _THIRD_PARTY_HEADERS_PATTERN.match(match.group(1))
and not _third_party_headers_pattern.match(match.group(1))
):
error(
filename,
Expand Down Expand Up @@ -5797,7 +5811,7 @@ def CheckIncludeLine(filename, clean_lines, linenum, include_state, error):
third_src_header = True
break

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

# We want to ensure that headers appear in the right order:
Expand Down Expand Up @@ -7527,6 +7541,8 @@ def ProcessConfigOverrides(filename):
_root = os.path.join(os.path.dirname(cfg_file), val)
elif name == "headers":
ProcessHppHeadersOption(val)
elif name == "third_party_headers":
ProcessThirdPartyHeadersOption(val)
elif name == "includeorder":
ProcessIncludeOrderOption(val)
else:
Expand Down Expand Up @@ -7711,6 +7727,7 @@ def ParseArguments(args):
"exclude=",
"recursive",
"headers=",
"third_party_headers=",
"includeorder=",
"config=",
"quiet",
Expand Down Expand Up @@ -7770,6 +7787,8 @@ def ParseArguments(args):
ProcessExtensionsOption(val)
elif opt == "--headers":
ProcessHppHeadersOption(val)
elif opt == "--third_party_headers":
ProcessThirdPartyHeadersOption(val)
elif opt == "--recursive":
recursive = True
elif opt == "--includeorder":
Expand Down
53 changes: 53 additions & 0 deletions cpplint_clitest.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
import subprocess
import sys
import tempfile
import textwrap

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


# Tests for third_party_headers option
def test_third_party_headers_default(tmp_path):
# By default, headers with uppercase letters are treated as third-party and not flagged
cpp = tmp_path / "test.cpp"
cpp.write_text(
textwrap.dedent("""
// Copyright 2025 cpplint
#include "Foo.h"
int main() { return 0; }
""")
)
status, out, err = run_shell_command(BASE_CMD, f"{cpp.name}", cwd=str(tmp_path))
assert status == 0, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
# No include_subdir warning
assert b"build/include_subdir" not in err


def test_third_party_headers_override(tmp_path):
# Override third_party_headers so Foo.h is not recognized as third-party
cpp = tmp_path / "test.cpp"
cpp.write_text(
textwrap.dedent("""
// Copyright 2025 cpplint
#include "Foo.h"
""")
)
# Use a pattern that matches nothing
flag = "--third_party_headers=^Bar.h$"
status, out, err = run_shell_command(BASE_CMD, f"{flag} {cpp.name}", cwd=str(tmp_path))
# Expect a warning about include_subdir
assert status == 1, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
assert b"build/include_subdir" in err


def test_third_party_headers_config(tmp_path):
# Override third_party_headers via config file so Foo.h is not recognized as third-party
cpp = tmp_path / "test.cpp"
cpp.write_text(
textwrap.dedent("""
// Copyright 2025 cpplint
#include "Foo.h"
""")
)
# Write configuration file to override third_party_headers
config = tmp_path / "CPPLINT.cfg"
config.write_text("third_party_headers=^Bar.h$\n")
status, out, err = run_shell_command(BASE_CMD, f"{cpp.name}", cwd=str(tmp_path))
# Expect a warning about include_subdir due to override
assert status == 1, f"stdout\n{out.decode('utf-8')}\nstderr\n{err.decode('utf-8')}"
assert b"build/include_subdir" in err


if __name__ == "__main__":
pytest.main([__file__])
Loading