Skip to content

Commit edd37f1

Browse files
authored
docs: add AI Coding Guide for cpp-linter-hooks (#172)
1 parent 0374df0 commit edd37f1

File tree

1 file changed

+113
-0
lines changed

1 file changed

+113
-0
lines changed

.github/copilot-instructions.md

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
# cpp-linter-hooks AI Coding Guide
2+
3+
## Project Overview
4+
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.
5+
6+
## Architecture
7+
8+
### Entry Points & Flow
9+
- **Entry scripts**: `clang-format-hook` and `clang-tidy-hook` (defined in `pyproject.toml`)
10+
- **Hook definitions**: `.pre-commit-hooks.yaml` configures both hooks with `types_or: [c++, c]`
11+
- **Execution pattern**: Parse args → resolve/install tool version → subprocess.run → return (exit_code, output)
12+
13+
### Core Modules
14+
- **`clang_format.py`**: Wraps clang-format with `-i` (in-place), supports `--verbose` and `--dry-run` modes
15+
- Returns `-1` for dry-run to distinguish from actual failures
16+
- **`clang_tidy.py`**: Wraps clang-tidy, forces exit code 1 if "warning:" or "error:" in output
17+
- **`util.py`**: Version resolution and pip-based tool installation
18+
- `_resolve_version()`: Supports partial matches (e.g., "20" → "20.1.7")
19+
- `DEFAULT_CLANG_FORMAT_VERSION` and `DEFAULT_CLANG_TIDY_VERSION` read from `pyproject.toml`
20+
- **`versions.py`**: Auto-generated by `scripts/update_versions.py` (runs weekly via GitHub Actions)
21+
22+
### Version Management Pattern
23+
```python
24+
# Users can specify partial versions
25+
--version=21 # Resolves to latest 21.x.x
26+
--version=21.1 # Resolves to latest 21.1.x
27+
--version=21.1.8 # Exact version
28+
```
29+
30+
## Development Workflows
31+
32+
### Local Testing
33+
```bash
34+
# Test hooks locally without installing
35+
pre-commit try-repo ./.. clang-format --verbose --all-files
36+
pre-commit try-repo ./.. clang-tidy --verbose --all-files
37+
38+
# Run test suite
39+
uv run pytest -vv # All tests
40+
uv run coverage run -m pytest # With coverage
41+
uv run pytest -m benchmark # Performance tests only
42+
```
43+
44+
### Adding/Modifying Features
45+
1. **Update hook logic** in `cpp_linter_hooks/{clang_format,clang_tidy}.py`
46+
2. **Add tests** in `tests/test_*.py` with `@pytest.mark.benchmark` for performance tracking
47+
3. **Test with sample files** in `testing/` directory (use `good.c` as expected output)
48+
4. **Update README.md** if user-facing behavior changes
49+
50+
### Dependency Management
51+
- **Uses `uv`** for all dev operations (not pip directly)
52+
- **Pin versions**: Default tool versions in `pyproject.toml` dependencies section
53+
- **Update versions**: Run `python scripts/update_versions.py` (auto-runs weekly on Monday 2 AM UTC)
54+
55+
## Project-Specific Conventions
56+
57+
### Return Value Pattern
58+
All hook functions return `Tuple[int, str]`:
59+
- `(0, "")` → Success
60+
- `(1, output)` → Failure (print output)
61+
- `(-1, output)` → Dry-run mode (clang-format only, convert to success in main)
62+
63+
### Testing Conventions
64+
- Use `tmp_path` fixture to avoid modifying repo files
65+
- Parametrize version tests: `@pytest.mark.parametrize` with versions 16-21
66+
- Mark performance-sensitive tests with `@pytest.mark.benchmark`
67+
- Compare formatted output against `testing/good.c` for correctness
68+
69+
### Argument Handling
70+
```python
71+
# Standard pattern in both hooks
72+
parser = ArgumentParser()
73+
parser.add_argument("--version", default=DEFAULT_VERSION)
74+
hook_args, other_args = parser.parse_known_args(args)
75+
# ... install tool if needed ...
76+
command = ["tool-name"] + other_args # Pass through unknown args
77+
```
78+
79+
## Critical Files
80+
81+
- **`pyproject.toml`**: Defines entry points, dependencies, default versions
82+
- **`versions.py`**: Auto-updated; DO NOT edit manually (see comment)
83+
- **`.pre-commit-hooks.yaml`**: Hook metadata for pre-commit framework
84+
- **`testing/run.sh`**: Integration test script used in CI
85+
86+
## Integration Points
87+
88+
### PyPI Dependencies
89+
- Fetches available versions from `https://pypi.org/pypi/{package}/json`
90+
- Filters out pre-release versions using regex pattern `(alpha|beta|rc|dev|a\d+|b\d+)`
91+
- Installs via `subprocess.run([sys.executable, "-m", "pip", "install", f"{tool}=={version}"])`
92+
93+
### Pre-commit Framework
94+
- Hooks run in parallel (`require_serial: false`) for performance
95+
- File type filtering via `types_or: [c++, c]`
96+
- Users configure via `.pre-commit-config.yaml` with `args:` list
97+
98+
## Common Tasks
99+
100+
**Add support for a new argument:**
101+
1. Add to ArgumentParser in hook module
102+
2. Pass to subprocess command or handle in Python
103+
3. Add test case in `tests/test_*.py`
104+
105+
**Update default tool versions:**
106+
1. Edit `dependencies` in `pyproject.toml`
107+
2. Run tests to ensure compatibility
108+
3. Update version in README examples
109+
110+
**Debug hook failures:**
111+
- Add `--verbose` to clang-format args for detailed output
112+
- Check `testing/run.sh` for integration test patterns
113+
- Use `pre-commit run --verbose` for detailed pre-commit logs

0 commit comments

Comments
 (0)