diff --git a/.clang-tidy b/.clang-tidy new file mode 100644 index 0000000..243a59c --- /dev/null +++ b/.clang-tidy @@ -0,0 +1,44 @@ +--- +# Broad families, minus the checks that fight the domain rather than help it. +# Each exclusion is deliberate: +# +# bugprone-branch-clone false positive on `if constexpr` +# bugprone-easily-swappable-parameters h(i, j), check_equal_size(a, b) +# bugprone-throwing-static-init* only fires on the test fixtures, +# the header itself has no globals +# misc-include-cleaner noisy for a single umbrella header +# modernize-use-nodiscard 57 sites; annotating the API with +# [[nodiscard]] is a decision to make +# on purpose, not a lint fix +# modernize-use-trailing-return-type style the project does not use +# portability-avoid-pragma-once #pragma once is a deliberate choice +# readability-function-cognitive-* binary()/ternary() are inherently so +# readability-identifier-length i, j, f, g, da, daa are the notation +# readability-magic-numbers the constants are the formulas +# readability-math-missing-parentheses precedence is the notation as well +# readability-named-parameter unused parameters in tag types +Checks: > + bugprone-*, + clang-analyzer-*, + misc-*, + modernize-*, + performance-*, + portability-*, + readability-*, + -bugprone-branch-clone, + -bugprone-easily-swappable-parameters, + -bugprone-throwing-static-initialization, + -misc-include-cleaner, + -modernize-use-nodiscard, + -modernize-use-trailing-return-type, + -portability-avoid-pragma-once, + -readability-function-cognitive-complexity, + -readability-identifier-length, + -readability-magic-numbers, + -readability-math-missing-parentheses, + -readability-named-parameter + +# Only our own headers. Eigen, doctest and pybind11 are not ours to fix. +HeaderFilterRegex: 'include/hyperjet/.*\.h$' + +FormatStyle: file diff --git a/justfile b/justfile new file mode 100644 index 0000000..a30acae --- /dev/null +++ b/justfile @@ -0,0 +1,31 @@ +# Format all C++ sources in place +format: + uv run --only-group dev clang-format -i include/hyperjet/*.h python/src/*.h python/src/*.cpp test/src/*.cpp benchmark/src/*.cpp + +# Generate the compilation database that clang-tidy needs +compile-db: + #!/usr/bin/env bash + set -euo pipefail + # The test build is the right entry point: it instantiates the templates, and + # an uninstantiated template is never analysed. + args=(-Stest -Bbuild/tidy -DCMAKE_BUILD_TYPE=Debug + -DCMAKE_EXPORT_COMPILE_COMMANDS=ON + -DCMAKE_POLICY_VERSION_MINIMUM=3.5) + # AppleClang knows the macOS SDK implicitly, the standalone clang-tidy does + # not, so the sysroot has to end up in the compilation database. + if [ "$(uname)" = Darwin ]; then + args+=("-DCMAKE_OSX_SYSROOT=$(xcrun --show-sdk-path)") + fi + cmake "${args[@]}" > /dev/null + +# One invocation for all units rather than run-clang-tidy.py: with only two of +# them the parallel driver is no faster, and it reports every finding in the +# header once per unit instead of once. + +# Run clang-tidy over the test translation units +tidy: compile-db + uv run --only-group tidy clang-tidy -p build/tidy --quiet test/src/*.cpp + +# Same, applying the fixes clang-tidy can make itself +tidy-fix: compile-db + uv run --only-group tidy clang-tidy -p build/tidy --quiet --fix test/src/*.cpp diff --git a/pyproject.toml b/pyproject.toml index b352e27..05499b1 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -33,6 +33,9 @@ Repository = "https://github.com/oberbichler/HyperJet" [dependency-groups] dev = ["clang-format>=19.0", "ruff>=0.11"] +# Separate group: the clang-tidy wheel is ~44 MB against ~2 MB for +# clang-format, and the format CI job has no use for it. +tidy = ["clang-tidy>=19.0"] test = ["pytest>=8.0"] [tool.scikit-build] diff --git a/uv.lock b/uv.lock index fa16340..e93dae4 100644 --- a/uv.lock +++ b/uv.lock @@ -27,6 +27,25 @@ wheels = [ { url = "https://files.pythonhosted.org/packages/ce/2d/35c5301c6d04f4babf218ad9716c061abebb8a56a1bbad167a86dfe966d3/clang_format-22.1.5-py2.py3-none-win_arm64.whl", hash = "sha256:4f5ac3b91bb5700c43cb96beb32e360a5aa6a7f94105d7900054f6496554d9b9", size = 1344987, upload-time = "2026-05-06T13:12:20.88Z" }, ] +[[package]] +name = "clang-tidy" +version = "22.1.8" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b9/d0/f9dc63658854dc4508270daab0e10a34a61330d35c53cfe679b692e57560/clang_tidy-22.1.8.tar.gz", hash = "sha256:d81205d15cc82eea10e9e3b65e99732bb0bc77144535648a4a1f77d9cb4eda50", size = 11746, upload-time = "2026-07-14T10:30:19.551Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/86/14/27f6ed1ffdf3fcc53d4482a5f1292b39751c7426ca70deca8bb7d04f5dae/clang_tidy-22.1.8-py2.py3-none-macosx_10_9_x86_64.whl", hash = "sha256:04b6c97bcdc032763d0d924531def281acd0b5a939bcc79994cbf3c6fe83e1ae", size = 31672907, upload-time = "2026-07-14T10:29:37.701Z" }, + { url = "https://files.pythonhosted.org/packages/01/23/949977d4304e30eeef80206b37a9305084926ea06b99708961fcbf27913f/clang_tidy-22.1.8-py2.py3-none-macosx_11_0_arm64.whl", hash = "sha256:916d7cbc9590e719459738fedc5ba76ac91f128d671390e574a0779014c84d73", size = 30823043, upload-time = "2026-07-14T10:29:41.887Z" }, + { url = "https://files.pythonhosted.org/packages/ac/b7/61ed8c319f2d9ddb9762a550a6fee434bdef7bdc46d5a4b50929f1c90ec0/clang_tidy-22.1.8-py2.py3-none-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1eaddaa7415e8c5e39aeefbfd15174f1ab2a671c86f7ebb200eb523cf9465559", size = 42155015, upload-time = "2026-07-14T10:29:45.608Z" }, + { url = "https://files.pythonhosted.org/packages/82/19/0f2668f8f5e2452b096a2b898f2b6bcecbceb6dd0c7f75d1755ce1f18d8b/clang_tidy-22.1.8-py2.py3-none-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1a3de07ba82d4403d8b692ae63a5520d4db5c606014c92c24bbcef9259057bf1", size = 44070377, upload-time = "2026-07-14T10:29:49.58Z" }, + { url = "https://files.pythonhosted.org/packages/6c/61/7c0c87952090de362d18703a8a2206ae30129c811c66f9d01f4094d59e87/clang_tidy-22.1.8-py2.py3-none-manylinux_2_28_i686.whl", hash = "sha256:879a53cc5ba9824197f97e83bd86686f9c159da18afd004e8f6d161c985f9b31", size = 49709888, upload-time = "2026-07-14T10:29:53.323Z" }, + { url = "https://files.pythonhosted.org/packages/87/78/cbe472f8a2f29df7c982f1a3782f515059f3e1488c668c946ac04df79dab/clang_tidy-22.1.8-py2.py3-none-manylinux_2_31_armv7l.whl", hash = "sha256:79d109db0bc74c4f20253ea997f73eac4fa6ec26171fa08c05fb82dd3ee94bc1", size = 40445704, upload-time = "2026-07-14T10:29:57.312Z" }, + { url = "https://files.pythonhosted.org/packages/e2/e0/be72d44c059a936af7d4b355d0c844e934d7f4c3c4eba578783d7fc486d2/clang_tidy-22.1.8-py2.py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:788200119549b80e3b3cc4c1ecc422b6bec6e2559ea2116494fe6c72092ec4c2", size = 41319020, upload-time = "2026-07-14T10:30:01.303Z" }, + { url = "https://files.pythonhosted.org/packages/97/34/223288ebf27f33b3842ab750ab5915ef3244f7802d4f7633dacf7a195ab2/clang_tidy-22.1.8-py2.py3-none-musllinux_1_2_i686.whl", hash = "sha256:8ad32751aa4697575fb34faabe70ee497aa32d31d4dfffe25f2655797dff1c2c", size = 51914038, upload-time = "2026-07-14T10:30:05.637Z" }, + { url = "https://files.pythonhosted.org/packages/8d/d1/a8019bfe6dcb103a081ffc0a869cb2b463a826e5005030d0abf211278b53/clang_tidy-22.1.8-py2.py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:19d11334f5f9af90a655e5ca46b1e472d44ec025a8d10fef95accb3ea19b8c60", size = 46732713, upload-time = "2026-07-14T10:30:10Z" }, + { url = "https://files.pythonhosted.org/packages/c1/ad/6bb2c2a0a7255ca624dca7ee172678b215c62ce79891a487f8ccc90bc48b/clang_tidy-22.1.8-py2.py3-none-win32.whl", hash = "sha256:182dc0b73688add32cd02595d510c0b010f77a645774dbb04e296d347c1a014f", size = 23553468, upload-time = "2026-07-14T10:30:13.42Z" }, + { url = "https://files.pythonhosted.org/packages/54/af/0580f6145d8a0c218844208a6c90ce539a4bdf65a66b672e6b4604a81c0a/clang_tidy-22.1.8-py2.py3-none-win_amd64.whl", hash = "sha256:df9bf841ecbf501d08b6fa34523be840f59b1a76d16b6ee5edb0e5c7c22b59c2", size = 26666952, upload-time = "2026-07-14T10:30:16.843Z" }, +] + [[package]] name = "colorama" version = "0.4.6" @@ -58,6 +77,9 @@ dev = [ test = [ { name = "pytest" }, ] +tidy = [ + { name = "clang-tidy" }, +] [package.metadata] requires-dist = [ @@ -73,6 +95,7 @@ dev = [ { name = "ruff", specifier = ">=0.11" }, ] test = [{ name = "pytest", specifier = ">=8.0" }] +tidy = [{ name = "clang-tidy", specifier = ">=19.0" }] [[package]] name = "iniconfig"