# Wire `textDocument/didClose`

**Effort:** S · **Impact:** M · **Immediate roc UX:** yes

## Repro (broken today)

1. Build and run `roc experimental-lsp` (or point Helix/Neovim at it).
2. Open a Roc file that produces diagnostics (e.g. a deliberate type error).
3. Confirm squiggles / `publishDiagnostics` for that URI.
4. Close the buffer/tab **without** quitting the editor.
5. Observe:
   - Diagnostics for the closed URI **remain** in the client (sticky squiggles / problem list entry), and/or
   - Server still holds the buffer in `DocumentStore` (memory grows as you open/close many files over a session).

**Why:** Capabilities advertise `openClose: true`, but only `didOpen` / `didChange` are registered. `DocumentStore.remove` exists and is unused by any notification handler.

## Evidence

- Cap: `src/lsp/capabilities.zig` → `buildCapabilities` (`openClose: true`)
- Handlers map: `src/lsp/server.zig` → `notification_handlers` (no `textDocument/didClose`)
- Store API ready: `src/lsp/document_store.zig` → `DocumentStore.remove`

## Goal

When the client sends `textDocument/didClose`, the server must:

1. Remove the URI from `DocumentStore`.
2. Publish an empty diagnostics list for that URI (clear sticky client state).

## Fix shape

1. Add `src/lsp/handlers/did_close.zig` mirroring `did_open.zig` (parse `textDocument.uri` only).
2. Call `doc_store.remove(uri)`.
3. Send `textDocument/publishDiagnostics` with `diagnostics: []` for that URI (reuse `publishDiagnostics` path or a thin helper on `Server`).
4. Register `.{ "textDocument/didClose", &DidCloseHandler.call }` in `notification_handlers`.
5. Integration test: init → didOpen (with error source) → didClose → assert store has no URI and outbound traffic includes empty diagnostics for that URI.

## Acceptance

- [ ] Closing a buffer clears diagnostics for that URI in a real editor (or integration test asserting the notification).
- [ ] `doc_store.get(uri)` is null after close in a unit/integration test.
- [ ] Opening the same path again still works (fresh upsert + check).

## Out of scope

- Dependency-graph / BuildEnv eviction for closed files (nice follow-up; not required for this hand-off).
- Async / cancelable checks.
