# Contributing
Contributions are welcome.
## Cache invalidation between builds
If you notice rebuilds happening when switching between `cargo clippy`, `cargo test`, and `cargo run`, it's likely due to environment variable changes (especially `CC`, `CXX`, etc.).
The `.envrc` file unsets compiler-related variables that can invalidate cargo's fingerprint cache. Make sure to reload your direnv environment:
```bash
direnv allow
```
If that does not work, have a look using this environment variable:
```bash
CARGO_LOG=cargo::core::compiler::fingerprint=info cargo build
```
## Adding new lints
Always start from valid Nu shell code. Experiment with different versions of the same Nu fragment to find out the limitations and possibilities that Nu has compared to other shells.
You can compare by running: `nu -c 'TEST'` and `bash -c 'TEST'`.
The first thing you might want to do for a new rule is investigate how Nu parses the fragment. Nu has a built-in command that allows you to interactively explore
```bash
ast --json benches/fixtures/small_file.nu | get block | from json | explore
```
If you are using Bash (or Claude is calling Bash), call the Nu interpreter from a Bash shell to show a JSON representation. This JSON representation is easier to read:
```bash
nu -c 'ast --json benches/fixtures/small_file.nu | get block'
```
Please follow a somewhat predictable test file structure. Currently the convention is to have three different test files for each new rule:
- `detect_bad.rs`: for the `assert_detects` assertions
- `ignore_good.rs`: for the `assert_ignores` assertions
- `generated_fix.rs`: for assertions about the contents of the replacement text or help text (optional if it is too hard to provide fixes, but recommended)
## Debugging
Use `lldb` extension to step through code.
You should call the free function `instrument()` inside, at the beginning of a test to show simple debug output generated by the macros of the `log` crate in the library code.
Then run the tests with the RUST_LOG environment variable:
```bash
RUST_LOG=debug cargo test test_detect_unnecessary_variable_simple -- --nocapture
```
(It would be possible to use the [test-log](https://crates.io/crates/test-log) crate but I prefered a custom formatter displaying file links.)
## Testing
Debugging is primarily done with the tests.
```bash
cargo test
```
Tests follow a pattern where each rule has 'detect', 'fix' and 'ignore' tests.
## Linting
Please run linter and formatter before submitting PRs. Many optional and restrictive rules of Clippy have been turned on.
This will attempt to auto-fix violations in the Rust code.
```bash
cargo clippy --fix --allow-dirty --all-targets
```
Check if everything was fixed:
```bash
cargo clippy --all-targets
```
```bash
cargo fmt
```
## Benchmarks
Quick benchmark for performance testing:
```bash
cargo bench --bench lint_performance lint_small_file
```
Comparative benchmarks
```bash
git checkout main
cargo bench --bench lint_performance lint_with_violations -- --save-baseline main
git checkout branch
cargo bench --bench lint_performance lint_with_violations -- --baseline main
```