Checks a C++ codebase against the C++ Style Guide and reports every finding with its rule ID, linked to the rule:
Engine/src/Engine/Gpu/Shader.h:1:1: MUST CPP-07.1: start every header with #pragma once, not an include guard [chopper]
Engine/src/Engine/Gpu/Shader.cpp:42:5: MUST NOT CPP-08.1: no `new` outside allocators and containers; use CreateScope / CreateRef [chopper]
It runs three kinds of check:
- clang-format with the guide's
.clang-format(chapter 6). - clang-tidy with the guide's
.clang-tidy, when it finds acompile_commands.json. With Premake:premake5 ninja, thenninja -t compdb > compile_commands.json(orbear -- makewith the Makefiles). With CMake:-DCMAKE_EXPORT_COMPILE_COMMANDS=ON. Build once before linting, so generated files such as the precompiled header exist; the kit says so when clang-tidy could not compile a file. - The guide's own checks for rules neither tool expresses:
#pragma once,using namespacein headers, relative includes, macro prefixes,// namespace Xcomments, platform headers outsidePlatform/, test file placement, TODO owners, log format strings, assert messages and more.checks.jsonlists them all.
The repository's own .clang-format and .clang-tidy are used when it has them; otherwise the kit's copies (the guide's appendix, verbatim) are.
Run it
Needs Python 3.9+, and clang-format and clang-tidy 19 for the tool checks (pip install clang-format~=19.1.0 clang-tidy~=19.1.0 works everywhere).
python3 chopper_lint.py # the current folder
python3 chopper_lint.py Engine/src Sandbox # some folders
python3 chopper_lint.py --compile-commands build/compile_commands.json
python3 chopper_lint.py --code ENG --strict # set the macro prefix; fail on SHOULD too
python3 chopper_lint.py --list-checks # what it checks
Folders named vendor, third_party, external, build, bin and bin-int are skipped, as are generated *.gen.* files.
Exit status: 1 when a MUST or MUST NOT rule is broken (any finding with --strict), else 0.
In GitHub Actions
- uses: actions/checkout@v4
- uses: carson-hopper/chopper.dev/content/styleguides/cpp/lint@main
with:
paths: Engine/src Sandbox/src
# compile-commands: build/compile_commands.json # enables clang-tidy
Findings appear as annotations on the pull request. Pin @main to a commit SHA for reproducible runs.
Silencing a finding
On the same line or the line above, with a reason:
auto* block = new (storage) Block(); // chopper-lint: allow CPP-08.1 (pool allocator)
For a whole file: // chopper-lint: allow-file CPP-08.1.