# 21. Tooling

> Chapter 21: the everyday tools: editor support through the language server, the formatter, the test runner with RSpec and xUnit styles, the REPL, toolchains, and telemetry.

Canonical: https://alice-lang.org/documentation/learn/tooling/

[Documentation index](https://alice-lang.org/documentation/llms.txt) · [Complete book](https://alice-lang.org/llms-full.txt)

A language is also its tools. You have used `alice run`, `check`, `explain` and `prove` throughout the book. This chapter covers the ones that make daily work pleasant: the editor integration, the formatter, the test runner, the REPL, version management, and what Alice does and does not send about you.

## Editors

Alice includes a **language server**, `alice lsp`, which editors talk to through the Language Server Protocol. It gives you errors as you type, completion including .NET members, hover documentation, go to definition, signature help, formatting, and NuGet package suggestions inside `alice.toml`.

Install the extension for your editor:

- **VS Code and VSCodium:** the "Alice language" extension, from the Visual Studio Marketplace or Open VSX.
- **Zed:** the Alice extension from the [extensions repository](https://github.com/alicelanguage/extensions).
- **Any other LSP client:** run `alice lsp --stdio`.

The `alice` command must be on your PATH, or configured in the extension's settings. [Editor setup](https://alice-lang.org/documentation/tools/editors.md) lists the settings.

## Formatting: `alice fmt`

`alice fmt` rewrites `.al` files in the one standard layout: it re-indents by block structure with two spaces, aligns `when` and `rescue` with their opener, removes trailing spaces and extra blank lines, and ends each file with one newline. Strings, comments and heredoc bodies are never changed. Running it twice changes nothing the second time.

```sh
alice fmt            # format every .al file in the project
alice fmt --check    # change nothing; list unformatted files and exit with status 1
```

Use `--check` in CI, and let your editor format on save.

## Testing: `alice test`

`alice test` builds the project, then compiles every file in `test/` together with the sources and runs the tests. Top-level code in `src/` does not run during tests. You met the simplest style in chapter 1: methods named `test_...` with `assert` and `assert_equal`. Two richer styles are built in.

**RSpec style**, familiar from Ruby. `describe` groups examples, `it` names one, and `expect(...).to` states what should hold:

```alice project="test/total_spec_test.al"
describe "total_cents" do
  it "multiplies price by quantity" do
    expect(total_cents(250, 3)).to eq(750)
  end

  it "is zero for no cups" do
    expect(total_cents(250, 0)).to eq(0)
  end

  it "raises on overflow" do
    expect { total_cents(Int32::MAX, 2) }.to raise_error(typeof(OverflowException))
  end
end
```

```text
test/total_spec_test.al
  total_cents
    ✓ multiplies price by quantity (2 ms)
    ✓ is zero for no cups
    ✓ raises on overflow (1.3 ms)

3 examples, 0 failures in 1.52s
```

When an example fails, the report shows what was expected, what came out, the source line, and the command to rerun only that example:

```text
Failures:

  1) total_cents is zero for no cups
     expected 0 to eq 1
     expected: 1
          got: 0
     # test/total_spec_test.al:6

3 examples, 1 failures in 1.66s

Rerun failed:
  alice test test/total_spec_test.al:6 # total_cents is zero for no cups
```

Matchers include `eq`, `be_nil`, `be_true`, `be_empty`, `be_within(d).of(x)`, `include`, `start_with`, `match` and `raise_error`. Hooks `before` and `after` run around each example.

**xUnit style** uses attributes: `@[Test]` on a method, and `@[Cases(1, 2, 3)]` to run it once per value.

Useful options: `alice test file.al:LINE` runs one example, `-e TEXT` filters by name, `--fail-fast` stops at the first failure, `--order random --seed N` shuffles reproducibly, and `--format junit` writes XML for CI systems.

## The REPL

`alice repl`, or `alice` with no arguments, starts an interactive session. Type an expression and see its value and type:

```text
alice> x = 21
21 :: Int32
alice> x * 2
42 :: Int32
```

Each input compiles together with the earlier ones, so definitions persist and values keep their static types. Multi-line `def`, `class` and `do` blocks continue until they are closed. A few commands help while exploring: `:type EXPR` shows a type without running, `:emit CODE` shows the generated C#, `:time EXPR` times it, and `?Math.Sqrt` shows documentation. Inside a project, the REPL sees the project's packages.

## Versions: toolchains

The installer manages Alice versions, like `rustup` does for Rust:

```sh
alice toolchain install nightly   # or stable, or an exact version
alice toolchain pin 0.14.0        # writes ./alice-toolchain for this directory tree
alice +nightly run app.al         # use another version once
alice toolchain show              # the active version, and why
alice self update                 # the newest release on your channel
alice doctor                      # check the .NET SDK, PATH and toolchains
```

Commit the `alice-toolchain` file, so that everyone on the project, and CI, uses the same compiler.

## Telemetry

Alice 0.14 sends nothing: telemetry is disabled in this release, and the CLI neither asks, records nor sends.

```sh
alice telemetry
```

```text
   Telemetry disabled in this release (nothing is asked, recorded or sent)
```

The design for later releases is opt-in: nothing is sent unless you answer yes, `alice telemetry show` prints exactly what one event would contain, and `alice telemetry off` withdraws consent. Programs you build with Alice never contain telemetry. The full field list is in the [telemetry document](https://github.com/alicelanguage/alice/blob/main/docs/telemetry.md).

## Project: CI for the tea shop

Put the checks of the last chapters into one CI job, in the order of cost:

```yaml
name: ci
on: [push, pull_request]
jobs:
  check:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - name: Install Alice
        run: |
          curl -fsSL https://alice-lang.org/install.sh | sh
          echo "$HOME/.alice/bin" >> "$GITHUB_PATH"
      - run: alice fmt --check
      - run: alice check --strict
      - run: alice test --format junit > test-results.xml
      - run: alice prove --check
      - run: alice build --release
```

Formatting fails fastest, strict type checking next, then tests, proofs and the release build.

:::caution\[Common mistakes]

- **The editor cannot find `alice`.** The extension starts `alice lsp`; put `~/.alice/bin` on PATH or set the path in the extension's settings.
- **Formatting by hand.** Let `alice fmt` do it, and check with `--check` in CI.
- **Tests that depend on top-level code.** Top-level statements in `src/` do not run during tests; call methods.
- **Side effects in the REPL.** Earlier inputs re-run with output muted, so file writes repeat. Use `:reset`.
- **Unpinned compiler versions in CI.** Commit an `alice-toolchain` file.
  :::

## Exercises

1. Write an RSpec-style test for `with_tip` from chapter 1's exercises, with one example for 750 and one for 0.
2. Which command fails a CI job when a file is not formatted, without changing it?
3. How do you run only the example on line 10 of `test/tip_test.al`?

<details>
<summary>Answers</summary>

1. Answer:

   ```alice skip="project test: compiled with src/ by alice test"
   describe "with_tip" do
     it "adds ten percent, rounded down" do
       expect(with_tip(750)).to eq(825)
     end

     it "keeps zero at zero" do
       expect(with_tip(0)).to eq(0)
     end
   end
   ```

2. `alice fmt --check`.

3. `alice test test/tip_test.al:10`.

</details>

## Summary

- `alice lsp` powers editor support: diagnostics, completion, hover, definitions and formatting.
- `alice fmt` applies the one standard layout; `--check` verifies it in CI.
- `alice test` runs `test_` methods, RSpec-style `describe`/`it`/`expect` and xUnit-style `@[Test]` tests, with focused reruns and JUnit output.
- `alice repl` evaluates expressions with their static types.
- Toolchains pin compiler versions per directory. Telemetry is disabled in 0.14.

[Chapter 22](https://alice-lang.org/documentation/learn/agents.md) shows how these tools let AI coding agents work on Alice code safely.

## Continue reading

- Previous: [20. WebAssembly](https://alice-lang.org/documentation/learn/webassembly.md)
- Next: [22. Alice for AI agents](https://alice-lang.org/documentation/learn/agents.md)
