diff --git a/README.md b/README.md index d70173f..7d755ad 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Add this configuration to your `.pre-commit-config.yaml` file: ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 # Use the tag or commit you want + rev: v1.4.2 # Use the tag or commit you want hooks: - id: clang-format args: [--style=Google] # Other coding style: LLVM, GNU, Chromium, Microsoft, Mozilla, WebKit. @@ -71,7 +71,7 @@ To use custom configurations like `.clang-format` and `.clang-tidy`: ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-format args: [--style=file] # Loads style from .clang-format file @@ -80,7 +80,7 @@ repos: ``` > [!TIP] -> The `rev` tag (e.g. `v1.4.1`) is the **project** version, not the clang tool version. Each release bundles a default version of `clang-format` and `clang-tidy` — check the [release notes](https://github.com/cpp-linter/cpp-linter-hooks/releases) to see which tool version a given `rev` ships with. To pin an exact tool version independently of the project release, use `--version` as shown below. +> The `rev` tag (e.g. `v1.4.2`) is the **project** version, not the clang tool version. Each release bundles a default version of `clang-format` and `clang-tidy` — check the [release notes](https://github.com/cpp-linter/cpp-linter-hooks/releases) to see which tool version a given `rev` ships with. To pin an exact tool version independently of the project release, use `--version` as shown below. ### Custom Clang Tool Version @@ -89,7 +89,7 @@ To use specific versions of clang-format and clang-tidy (using Python wheel pack ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-format args: [--style=file, --version=21] # Specifies version @@ -113,7 +113,7 @@ automatically — no configuration needed for most projects: ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-tidy args: [--checks=.clang-tidy] @@ -228,7 +228,7 @@ Use -header-filter=.* to display errors from all non-system headers. Use -system ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 # requires the version that introduced --fix + rev: v1.4.2 # requires the version that introduced --fix hooks: - id: clang-tidy args: [--checks=.clang-tidy, --fix] @@ -247,7 +247,7 @@ repos: ```yaml - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-format args: [--style=file, --version=21] @@ -262,7 +262,7 @@ or `-j`: ```yaml - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-tidy args: [--checks=.clang-tidy, --version=21, --jobs=4] @@ -291,7 +291,7 @@ This approach ensures that only modified files are checked, further speeding up ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.1 + rev: v1.4.2 hooks: - id: clang-format args: [--style=file, --version=21, --verbose] # Shows processed files diff --git a/cpp_linter_hooks/__init__.py b/cpp_linter_hooks/__init__.py index e69de29..06f93c0 100644 --- a/cpp_linter_hooks/__init__.py +++ b/cpp_linter_hooks/__init__.py @@ -0,0 +1 @@ +"""Pre-commit hooks for clang-format and clang-tidy.""" diff --git a/cpp_linter_hooks/clang_format.py b/cpp_linter_hooks/clang_format.py index bc99d4b..7378524 100644 --- a/cpp_linter_hooks/clang_format.py +++ b/cpp_linter_hooks/clang_format.py @@ -1,3 +1,5 @@ +"""Pre-commit hook wrapper for clang-format.""" + import subprocess import sys from argparse import ArgumentParser @@ -14,6 +16,7 @@ def run_clang_format(args=None) -> Tuple[int, str]: + """Run clang-format with hook-specific arguments removed.""" hook_args, other_args = parser.parse_known_args(args) _, version_error = resolve_install_with_diagnostics( "clang-format", hook_args.version, hook_args.verbose @@ -65,6 +68,7 @@ def _print_verbose_info(command: list, retval: int, output: str) -> None: def main() -> int: + """Run clang-format as a command-line entry point.""" retval, output = run_clang_format() # pragma: no cover # Print output for errors, but not for dry-run mode diff --git a/cpp_linter_hooks/clang_tidy.py b/cpp_linter_hooks/clang_tidy.py index 5f1efa9..a013048 100644 --- a/cpp_linter_hooks/clang_tidy.py +++ b/cpp_linter_hooks/clang_tidy.py @@ -1,3 +1,5 @@ +"""Pre-commit hook wrapper for clang-tidy.""" + from concurrent.futures import ThreadPoolExecutor import subprocess import sys @@ -43,6 +45,7 @@ def _positive_int(value: str) -> int: + """Parse a positive integer for the --jobs option.""" jobs = int(value) if jobs < 1: raise ArgumentTypeError("--jobs must be greater than 0") @@ -61,6 +64,7 @@ def _positive_int(value: str) -> int: def _find_compile_commands() -> Optional[str]: + """Return the first common directory containing compile_commands.json.""" for d in COMPILE_DB_SEARCH_DIRS: if (Path(d) / "compile_commands.json").exists(): return d @@ -68,6 +72,7 @@ def _find_compile_commands() -> Optional[str]: def _compile_commands_not_found_message(path: Optional[str] = None) -> str: + """Build a user-facing message for missing compile_commands.json files.""" if path is None: return "No compile_commands.json was found in common build directories.\n\n" + ( COMPILE_COMMANDS_HINT @@ -113,6 +118,7 @@ def _resolve_compile_db( def _looks_like_compile_db_error(output: str) -> bool: + """Return whether clang-tidy output indicates a compile database problem.""" lower_output = output.lower() compile_db_error = "compile_commands.json" in lower_output and any( pattern in lower_output @@ -135,6 +141,7 @@ def _looks_like_compile_db_error(output: str) -> bool: def _looks_like_msvc_error(output: str) -> bool: + """Return whether clang-tidy output indicates an MSVC setup problem.""" lower_output = output.lower() cl_driver_error = "cl.exe" in lower_output and any( pattern in lower_output @@ -155,6 +162,7 @@ def _looks_like_msvc_error(output: str) -> bool: def _append_guidance(output: str) -> str: + """Append troubleshooting guidance when clang-tidy output matches known errors.""" hints: List[str] = [] if _looks_like_compile_db_error(output) and COMPILE_COMMANDS_HINT not in output: hints.append(COMPILE_COMMANDS_HINT) @@ -183,10 +191,12 @@ def _exec_clang_tidy(command) -> Tuple[int, str]: def _looks_like_source_file(path: str) -> bool: + """Return whether a path has a recognized C or C++ source suffix.""" return Path(path).suffix.lower() in SOURCE_FILE_SUFFIXES def _split_source_files(args: List[str]) -> Tuple[List[str], List[str]]: + """Split clang-tidy options from trailing source file arguments.""" split_idx = len(args) source_files: List[str] = [] for idx in range(len(args) - 1, -1, -1): @@ -198,13 +208,17 @@ def _split_source_files(args: List[str]) -> Tuple[List[str], List[str]]: def _combine_outputs(results: List[Tuple[int, str]]) -> str: + """Join non-empty clang-tidy outputs from multiple executions.""" return "\n".join(output.rstrip("\n") for _, output in results if output) def _exec_parallel_clang_tidy( command_prefix: List[str], source_files: List[str], jobs: int ) -> Tuple[int, str]: + """Run clang-tidy over source files in parallel and combine the results.""" + def run_file(source_file: str) -> Tuple[int, str]: + """Run clang-tidy for a single source file.""" return _exec_clang_tidy(command_prefix + [source_file]) with ThreadPoolExecutor(max_workers=min(jobs, len(source_files))) as executor: @@ -215,6 +229,7 @@ def run_file(source_file: str) -> Tuple[int, str]: def run_clang_tidy(args=None) -> Tuple[int, str]: + """Run clang-tidy with hook-specific argument handling.""" hook_args, other_args = parser.parse_known_args(args) _, version_error = resolve_install_with_diagnostics( "clang-tidy", hook_args.version, hook_args.verbose @@ -266,6 +281,7 @@ def run_clang_tidy(args=None) -> Tuple[int, str]: def main() -> int: + """Run clang-tidy as a command-line entry point.""" retval, output = run_clang_tidy() if retval != 0: print(output) diff --git a/cpp_linter_hooks/util.py b/cpp_linter_hooks/util.py index 781a23b..57db142 100644 --- a/cpp_linter_hooks/util.py +++ b/cpp_linter_hooks/util.py @@ -1,3 +1,5 @@ +"""Shared helpers for resolving and installing clang tool wheels.""" + import sys import shutil import subprocess @@ -35,10 +37,12 @@ def get_version_from_dependency(tool: str) -> Optional[str]: def _versions_for_tool(tool: str) -> List[str]: + """Return supported Python wheel versions for a clang tool.""" return CLANG_FORMAT_VERSIONS if tool == "clang-format" else CLANG_TIDY_VERSIONS def _default_version_for_tool(tool: str) -> Optional[str]: + """Return the default Python wheel version for a clang tool.""" return ( DEFAULT_CLANG_FORMAT_VERSION if tool == "clang-format" @@ -47,6 +51,7 @@ def _default_version_for_tool(tool: str) -> Optional[str]: def _supported_versions_message(tool: str) -> str: + """Build a user-facing list of supported wheel versions for a clang tool.""" versions = ", ".join(_versions_for_tool(tool)) return f"Supported {tool} wheel versions: {versions}" @@ -66,6 +71,7 @@ def _resolve_version(versions: List[str], user_input: Optional[str]) -> Optional # define a function to parse version strings into tuples for comparison def parse_version(v: str): + """Convert a dotted version string into an integer tuple.""" return tuple(map(int, v.split("."))) # return the latest version diff --git a/examples/cmake/README.md b/examples/cmake/README.md index 3c6656b..5331742 100644 --- a/examples/cmake/README.md +++ b/examples/cmake/README.md @@ -7,7 +7,7 @@ If you already have a CMake project, you need **two files**: ```yaml repos: - repo: https://github.com/cpp-linter/cpp-linter-hooks - rev: v1.4.0 + rev: v1.4.2 hooks: - id: clang-format args: [--style=file, --version=21]