# Contributing

Contributions are welcome.

## 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
```
