# Contributing to groxide

## Prerequisites

- **Rust stable** (MSRV 1.88): `rustup toolchain install stable`
- **Rust nightly**: Required for rustdoc JSON generation. Install with `rustup toolchain install nightly`

## Building

```sh
# Check (faster than build during development)
cargo check

# Build
cargo build

# Install locally
cargo install --path .
```

The binary is called `grox`.

## Testing

```sh
# Run all tests
cargo test

# Run a specific test
cargo test test_name

# Run ignored tests (e.g., network-dependent or slow tests)
cargo test -- --ignored

# Run integration tests only
cargo test --test cli_happy
cargo test --test cli_errors
```

### Snapshot tests

This project uses [insta](https://insta.rs/) for snapshot testing. When code changes cause snapshot diffs:

```sh
# Update snapshots non-interactively
INSTA_UPDATE=always cargo test
```

Do **not** use `cargo insta accept` (it requires an interactive terminal).

### Test fixture

Tests use a fixture crate at `test-fixtures/groxide_test_api/` with a pre-generated rustdoc JSON file. Don't `cd` into the fixture directory to run tests; always run from the project root.

### Cache invalidation

After changing `src/index_builder.rs`, clear the index cache before testing:

```sh
rm -rf target/groxide/
```

## Pre-commit checks

Before every commit, all three checks must pass:

```sh
cargo fmt -- --check
cargo clippy --all-targets
cargo test
```

## Code style

- **No `.unwrap()` in library code.** Use `?`, `.expect("invariant: reason")`, or combinators.
- **No `.clone()` to silence the borrow checker.** Fix the ownership design.
- **Match all enum variants explicitly.** No wildcard `_` on enums we control.
- **Error handling:** `thiserror` for error types, `?` for propagation, `.map_err()` for context.
- **Prefer `&str` over `String`** in function arguments.
- **Doc comments** on all public items, starting with a third-person verb ("Returns the...", "Creates a...").
- **Test names:** `{action}_{outcome}_{condition}` (e.g., `lookup_returns_found_when_exact_path_matches`).
- **Pedantic clippy:** Lint levels are configured in `Cargo.toml` under `[lints]`.

## Project structure

```
src/
  main.rs           Entry point (~15 lines)
  lib.rs            Orchestration (run function)
  cli.rs            CLI definition (clap derive)
  error.rs          Error types and exit codes
  types.rs          Core domain types
  resolve.rs        Crate resolution
  docgen.rs         Rustdoc JSON generation
  index_builder.rs  Index builder (4-pass algorithm)
  cache.rs          Disk cache
  query.rs          Query engine
  search.rs         Full-text search
  signature.rs      Signature rendering
  external.rs       External crate fetching
  stdlib.rs         Standard library support
  render/
    mod.rs          Render dispatch
    text.rs         Plain text output (single-item default view)
    brief.rs        Brief mode output (names only)
    docs.rs         Full docs mode output
    list.rs         List mode output (recursive)
    json.rs         JSON output
    ambiguous.rs    Ambiguous match display
tests/              Integration tests
test-fixtures/      Test fixture crate
```

## License

By contributing, you agree that your contributions will be licensed under the same terms as the project: MIT OR Apache-2.0.
