-
Notifications
You must be signed in to change notification settings - Fork 5
docs: add AI Coding Guide for cpp-linter-hooks #172
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
Merged
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,113 @@ | ||
| # cpp-linter-hooks AI Coding Guide | ||
|
|
||
| ## Project Overview | ||
| Pre-commit hooks wrapper that auto-installs and runs clang-format and clang-tidy from Python wheels. Supports Python 3.9-3.14 across Windows, Linux, and macOS. | ||
|
|
||
| ## Architecture | ||
|
|
||
| ### Entry Points & Flow | ||
| - **Entry scripts**: `clang-format-hook` and `clang-tidy-hook` (defined in `pyproject.toml`) | ||
| - **Hook definitions**: `.pre-commit-hooks.yaml` configures both hooks with `types_or: [c++, c]` | ||
| - **Execution pattern**: Parse args → resolve/install tool version → subprocess.run → return (exit_code, output) | ||
|
|
||
| ### Core Modules | ||
| - **`clang_format.py`**: Wraps clang-format with `-i` (in-place), supports `--verbose` and `--dry-run` modes | ||
| - Returns `-1` for dry-run to distinguish from actual failures | ||
| - **`clang_tidy.py`**: Wraps clang-tidy, forces exit code 1 if "warning:" or "error:" in output | ||
| - **`util.py`**: Version resolution and pip-based tool installation | ||
| - `_resolve_version()`: Supports partial matches (e.g., "20" → "20.1.7") | ||
| - `DEFAULT_CLANG_FORMAT_VERSION` and `DEFAULT_CLANG_TIDY_VERSION` read from `pyproject.toml` | ||
| - **`versions.py`**: Auto-generated by `scripts/update_versions.py` (runs weekly via GitHub Actions) | ||
|
|
||
| ### Version Management Pattern | ||
| ```python | ||
| # Users can specify partial versions | ||
| --version=21 # Resolves to latest 21.x.x | ||
| --version=21.1 # Resolves to latest 21.1.x | ||
| --version=21.1.8 # Exact version | ||
| ``` | ||
|
|
||
| ## Development Workflows | ||
|
|
||
| ### Local Testing | ||
| ```bash | ||
| # Test hooks locally without installing | ||
| pre-commit try-repo ./.. clang-format --verbose --all-files | ||
| pre-commit try-repo ./.. clang-tidy --verbose --all-files | ||
|
|
||
| # Run test suite | ||
| uv run pytest -vv # All tests | ||
| uv run coverage run -m pytest # With coverage | ||
| uv run pytest -m benchmark # Performance tests only | ||
| ``` | ||
|
|
||
| ### Adding/Modifying Features | ||
| 1. **Update hook logic** in `cpp_linter_hooks/{clang_format,clang_tidy}.py` | ||
| 2. **Add tests** in `tests/test_*.py` with `@pytest.mark.benchmark` for performance tracking | ||
| 3. **Test with sample files** in `testing/` directory (use `good.c` as expected output) | ||
| 4. **Update README.md** if user-facing behavior changes | ||
|
|
||
| ### Dependency Management | ||
| - **Uses `uv`** for all dev operations (not pip directly) | ||
| - **Pin versions**: Default tool versions in `pyproject.toml` dependencies section | ||
| - **Update versions**: Run `python scripts/update_versions.py` (auto-runs weekly on Monday 2 AM UTC) | ||
|
|
||
| ## Project-Specific Conventions | ||
|
|
||
| ### Return Value Pattern | ||
| All hook functions return `Tuple[int, str]`: | ||
| - `(0, "")` → Success | ||
| - `(1, output)` → Failure (print output) | ||
| - `(-1, output)` → Dry-run mode (clang-format only, convert to success in main) | ||
|
|
||
| ### Testing Conventions | ||
| - Use `tmp_path` fixture to avoid modifying repo files | ||
| - Parametrize version tests: `@pytest.mark.parametrize` with versions 16-21 | ||
| - Mark performance-sensitive tests with `@pytest.mark.benchmark` | ||
| - Compare formatted output against `testing/good.c` for correctness | ||
|
|
||
| ### Argument Handling | ||
| ```python | ||
| # Standard pattern in both hooks | ||
| parser = ArgumentParser() | ||
| parser.add_argument("--version", default=DEFAULT_VERSION) | ||
| hook_args, other_args = parser.parse_known_args(args) | ||
| # ... install tool if needed ... | ||
| command = ["tool-name"] + other_args # Pass through unknown args | ||
| ``` | ||
|
|
||
| ## Critical Files | ||
|
|
||
| - **`pyproject.toml`**: Defines entry points, dependencies, default versions | ||
| - **`versions.py`**: Auto-updated; DO NOT edit manually (see comment) | ||
| - **`.pre-commit-hooks.yaml`**: Hook metadata for pre-commit framework | ||
| - **`testing/run.sh`**: Integration test script used in CI | ||
|
|
||
| ## Integration Points | ||
|
|
||
| ### PyPI Dependencies | ||
| - Fetches available versions from `https://pypi.org/pypi/{package}/json` | ||
| - Filters out pre-release versions using regex pattern `(alpha|beta|rc|dev|a\d+|b\d+)` | ||
| - Installs via `subprocess.run([sys.executable, "-m", "pip", "install", f"{tool}=={version}"])` | ||
|
|
||
| ### Pre-commit Framework | ||
| - Hooks run in parallel (`require_serial: false`) for performance | ||
| - File type filtering via `types_or: [c++, c]` | ||
| - Users configure via `.pre-commit-config.yaml` with `args:` list | ||
|
|
||
| ## Common Tasks | ||
|
|
||
| **Add support for a new argument:** | ||
| 1. Add to ArgumentParser in hook module | ||
| 2. Pass to subprocess command or handle in Python | ||
| 3. Add test case in `tests/test_*.py` | ||
|
|
||
| **Update default tool versions:** | ||
| 1. Edit `dependencies` in `pyproject.toml` | ||
| 2. Run tests to ensure compatibility | ||
| 3. Update version in README examples | ||
|
|
||
| **Debug hook failures:** | ||
| - Add `--verbose` to clang-format args for detailed output | ||
| - Check `testing/run.sh` for integration test patterns | ||
| - Use `pre-commit run --verbose` for detailed pre-commit logs | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🧩 Analysis chain
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 1223
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 98
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 405
🏁 Script executed:
# Read the pre-commit workflow file to see how try-repo is used there cat .github/workflows/pre-commit.ymlRepository: cpp-linter/cpp-linter-hooks
Length of output: 314
🌐 Web query:
pre-commit try-repo documentation syntax path argument💡 Result:
pre-commit try-reposyntax is:repois the “Repository to source hooks from” (positional argument). It can be a git repo URL or a local filesystem path to a repo checkout (for example:../path/to/my-hooks). [1][2]hook(optional) is a single hook id to run; if omitted, it will generate a config snippet / run the repo’s hooks per your selection. [1]--ref/--rev; if you don’t specify it,try-repouses the repo’sHEAD. [1]Example with a local path:
[2]
Example with a remote + ref:
[1]
Sources: [1] https://www.mankier.com/1/pre-commit-try-repo [2] https://blog.dagworks.io/p/custom-pre-commit-hooks-for-safer
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 98
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 1281
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 85
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 695
🏁 Script executed:
Repository: cpp-linter/cpp-linter-hooks
Length of output: 1225
Fix pre-commit try-repo path from
./..to.Lines 35-36 use
./..as the repository path, which resolves to the parent directory rather than the current repository. When running these commands from the repository root (as the documentation context indicates), the path should be.instead:Suggested fix
📝 Committable suggestion
🤖 Prompt for AI Agents