char/avril

(wip) why'd you have to go and make things so complicaaaaated?

git clone https://git.t4t.associates/char/avril

Charlotte Somdocument the new tsc + lsp setupec2ae4a

main
8.9 KiB189 linesraw

avril for VS Code

Native TypeScript language features, live diagnostics, and avril.conf syntax highlighting. The client launches avril lsp directly; it does not run a Deno or JavaScript language server.

Build and install

There are three pieces: the Avril executable, a separately built patched native TypeScript executable, and the VS Code extension. The extension does not bundle either executable. Stock typescript from npm and unpatched native TypeScript executables cannot serve as the LSP backend.

Prerequisites:

  • Current stable Rust, a C compiler toolchain, and curl to build Avril. See README.md at the repository root for the alternative of building V8 from source.
  • Git, Bash, and Go for the patched compiler. Its Go module selects the required toolchain; Go may download it on the first build. No Node/npm install is needed in the TypeScript checkout.
  • Node.js 22.13 or newer (including npm), pnpm 11.27.0, and VS Code 1.90 or newer for the extension. pnpm installs dependencies; vsce still uses npm internally to enumerate them.

1. Build Avril and the patched compiler

Run these commands from the Avril repository root, in a Unix shell:

cargo build --locked -p avril-cli --bin avril

typescript_src=$(mktemp -d)
git clone --filter=blob:none --no-checkout \
  https://github.com/microsoft/TypeScript.git "$typescript_src"
git -C "$typescript_src" checkout --detach b5c34ba0c61a756c8abaf133236dddf982c27f45
bash lib/lsp/typescript/build.sh "$typescript_src" "/absolute/path/to/avril-tsc"

printf 'avril.lsp.executable: %s\n' "$PWD/target/debug/avril"
printf 'avril.lsp.backend: %s\n' "/absolute/path/to/avril-tsc"

Copy the two printed paths for the settings below. The compiler executable is installed outside the temporary checkout and embeds its library declarations; the checkout is not needed at runtime. The script checks the pinned revision, applies bridge.patch, runs the native bridge tests, and builds 7.1.0-dev.20261013.1.

If Go is not on PATH, replace the build.sh command above with:

nix shell nixpkgs#go --command bash lib/lsp/typescript/build.sh \
  "$typescript_src" "/absolute/path/to/avril-tsc"

The script requires a clean checkout and leaves it patched. To rebuild after an Avril patch update, use a fresh checkout rather than rerunning it on the patched one. See lib/lsp/BACKEND.md in the source checkout for the backend contract.

2. Package and install the extension

Still starting from the Avril repository root:

cd editors/vscode
pnpm install --frozen-lockfile --prod=false --ignore-scripts
pnpm run package
code --install-extension avril.vsix --force

If your Node installation does not include npm on PATH, Nix can supply both for packaging: run nix shell nixpkgs#nodejs_24 --command pnpm run package from editors/vscode instead of the plain package command.

Use codium instead of code for VSCodium. Alternatively, choose Extensions: Install from VSIX... and select editors/vscode/avril.vsix. After installing or updating, run Developer: Reload Window.

The extension bundles its client dependencies. Projects do not need an npm install; this adds no npm/Node compatibility to avril guests.

Live language server

  1. Open and trust a local workspace. The client currently uses its first folder; other workspace folders retain their own TypeScript language features.

  2. Set these user settings (executable settings are machine-scoped):

    {
      "avril.lsp.backend": "/absolute/path/to/avril-tsc",
      "avril.lsp.executable": "/absolute/path/to/avril/target/debug/avril"
    }

    Substitute the literal absolute paths printed during the build. These settings do not expand ~, $HOME, or ${workspaceFolder}. Open Preferences: Open User Settings (JSON) to edit them; do not put these machine-scoped paths in the project's .vscode/settings.json. If you built Avril in release mode or installed it separately, use that executable instead. You do not need to set typescript.tsdk.

  3. Keep VS Code's built-in TypeScript and JavaScript Language Features extension enabled. avril suppresses its competing results for the active folder while the language server runs, and restores them when it stops.

  4. With avril.conf directly in the first workspace folder, the language server starts automatically once the backend is configured. Nested configurations do not trigger startup. Without a root configuration, run avril: Start Language Server manually, then open a TS/TSX/JS/JSX file.

The server follows real avril configuration, imports, packages, and declarations. Unsaved imports and disk/config changes refresh automatically. No manifest or generated tsconfig is needed. The editor may populate the permitted cache, but never writes lockfiles or application files.

Use avril.lsp.options for CLI policy flags, for example ["--offline", "--frozen"]. Restart the language server after changing launch settings. avril: Stop Language Server shuts down the server and native child and prevents automatic restarts until you run avril: Start Language Server or reload the window. Set avril.lsp.autoStart to false to opt out persistently. Use avril.lsp.preferences for native TypeScript preferences (for example, {"referencesCodeLensEnabled": true, "includeInlayParameterNameHints": "all"}). These update live; omitted preferences preserve native defaults. Creating a root avril.conf starts the server; removing it stops an automatically started server. Untrusted workspaces cannot start it.

Avril uses the native TypeScript language-service results for completion and resolution, navigation, rename, symbols, formatting, semantic tokens, inlay hints, call hierarchy, code actions, and the other capabilities advertised by the server. Type hierarchy is not advertised because the pinned native backend does not implement it. Workspace sources remain editable; acquired npm files open as immutable avril-builtin:/dependencies/ documents. HTTPS, HTTP, and builtin declarations open through read-only avril-https:, avril-http:, and avril-builtin: providers. The native backend's server capabilities are exposed directly; resolution and edits remain subject to Avril's project authority. The server currently rebuilds complete generations; broader discovery and checking-context limitations are listed in lib/lsp/README.md in the source checkout.

Verify the setup

Open a TypeScript file and check hover, completion, and Go to Definition. For a known example, open lib/lsp/tests/fixture from this repository as the workspace folder, then open main.tsx: hovering localValue should show its literal type 42, and Go to Definition should reach dep file.ts.

If startup fails, open View: Toggle Output and select avril. Check that both executable paths exist, the backend was built with this repository's patch, the workspace is trusted, and avril.conf is directly in its first folder (or start the server manually). The extension launches avril lsp; you do not need to run it separately in a terminal.

After rebuilding either executable, run avril: Stop Language Server, then avril: Start Language Server to replace the running processes. Repackage and reinstall the VSIX only when the extension itself changes.

Validation

Run the client lifecycle, ownership, CodeLens conversion, and read-only document URI roundtrip tests with pnpm test from editors/vscode/.

From the repository root, after installing client dependencies:

export AVRIL_LSP_BACKEND=/absolute/path/to/avril-tsc
export AVRIL_LSP_AVRIL="$PWD/target/debug/avril"
profile=$(mktemp -d /tmp/avril-editor-test.XXXXXX)
xvfb-run -a codium --wait --verbose --disable-gpu --ozone-platform=x11 \
  --user-data-dir="$profile/user" --extensions-dir="$profile/extensions" \
  --skip-welcome --skip-release-notes --disable-workspace-trust \
  --extensionDevelopmentPath="$PWD/editors/vscode" \
  --extensionTestsPath="$PWD/editors/vscode/tests/editor.cjs" \
  "$PWD/lib/lsp/tests/fixture" > "$profile/test.log" 2>&1
grep AVRIL_EDITOR_TESTS_PASSED "$profile/test.log"

The actual extension-host test invokes hover, definition, completion, signature help, rename, and references CodeLens providers; it also runs the resolved CodeLens command through VS Code's built-in references UI. It checks unsaved edits and diagnostics, and opens real builtin declarations. It also checks automatic startup and restoration/suppression of built-in TypeScript diagnostics across server stop/start. It never saves fixture application files. The trust override is for this known fixture only; systems without Chromium sandbox support may also need --no-sandbox for the isolated test window. Require the success marker: some editor versions exit zero even when extension tests fail. Tests are excluded from the packaged extension.

Run the server's live/protocol/lifecycle and native API regression tests using the commands in lib/lsp/README.md in the source checkout.

1# avril for VS Code
2
3Native TypeScript language features, live diagnostics, and `avril.conf` syntax
4highlighting. The client launches `avril lsp` directly;
5it does not run a Deno or JavaScript language server.
6
7## Build and install
8
9There are three pieces: the Avril executable, a separately built **patched
10native TypeScript executable**, and the VS Code extension. The extension does
11not bundle either executable. Stock `typescript` from npm and unpatched native
12TypeScript executables cannot serve as the LSP backend.
13
14Prerequisites:
15
16- Current stable Rust, a C compiler toolchain, and curl to build Avril. See
17  `README.md` at the repository root for the alternative of building V8 from
18  source.
19- Git, Bash, and Go for the patched compiler. Its Go module selects the required
20  toolchain; Go may download it on the first build. No Node/npm install is needed
21  in the TypeScript checkout.
22- Node.js 22.13 or newer (including npm), pnpm 11.27.0, and VS Code 1.90 or newer
23  for the extension. pnpm installs dependencies; `vsce` still uses npm internally
24  to enumerate them.
25
26### 1. Build Avril and the patched compiler
27
28Run these commands from the **Avril repository root**, in a Unix shell:
29
30```sh
31cargo build --locked -p avril-cli --bin avril
32
33typescript_src=$(mktemp -d)
34git clone --filter=blob:none --no-checkout \
35  https://github.com/microsoft/TypeScript.git "$typescript_src"
36git -C "$typescript_src" checkout --detach b5c34ba0c61a756c8abaf133236dddf982c27f45
37bash lib/lsp/typescript/build.sh "$typescript_src" "/absolute/path/to/avril-tsc"
38
39printf 'avril.lsp.executable: %s\n' "$PWD/target/debug/avril"
40printf 'avril.lsp.backend: %s\n' "/absolute/path/to/avril-tsc"
41```
42
43Copy the two printed paths for the settings below. The compiler executable is
44installed outside the temporary checkout and embeds its library declarations;
45the checkout is not needed at runtime. The script checks the pinned revision,
46applies `bridge.patch`, runs the native bridge tests, and builds
47`7.1.0-dev.20261013.1`.
48
49If Go is not on PATH, replace the `build.sh` command above with:
50
51```sh
52nix shell nixpkgs#go --command bash lib/lsp/typescript/build.sh \
53  "$typescript_src" "/absolute/path/to/avril-tsc"
54```
55
56The script requires a clean checkout and leaves it patched. To rebuild after an
57Avril patch update, use a fresh checkout rather than rerunning it on the patched
58one. See `lib/lsp/BACKEND.md` in the source checkout for the backend contract.
59
60### 2. Package and install the extension
61
62Still starting from the Avril repository root:
63
64```sh
65cd editors/vscode
66pnpm install --frozen-lockfile --prod=false --ignore-scripts
67pnpm run package
68code --install-extension avril.vsix --force
69```
70
71If your Node installation does not include npm on PATH, Nix can supply both for
72packaging: run `nix shell nixpkgs#nodejs_24 --command pnpm run package` from
73`editors/vscode` instead of the plain package command.
74
75Use `codium` instead of `code` for VSCodium. Alternatively, choose **Extensions:
76Install from VSIX...** and select `editors/vscode/avril.vsix`. After installing or
77updating, run **Developer: Reload Window**.
78
79The extension bundles its client dependencies. Projects do not need an npm
80install; this adds no npm/Node compatibility to avril guests.
81
82## Live language server
83
841. Open and trust a local workspace. The client currently uses its first folder;
85   other workspace folders retain their own TypeScript language features.
862. Set these **user settings** (executable settings are machine-scoped):
87
88   ```json
89   {
90     "avril.lsp.backend": "/absolute/path/to/avril-tsc",
91     "avril.lsp.executable": "/absolute/path/to/avril/target/debug/avril"
92   }
93   ```
94
95   Substitute the literal absolute paths printed during the build. These
96   settings do not expand `~`, `$HOME`, or `${workspaceFolder}`. Open
97   **Preferences: Open User Settings (JSON)** to edit them; do not put these
98   machine-scoped paths in the project's `.vscode/settings.json`. If you built
99   Avril in release mode or installed it separately, use that executable instead.
100   You do not need to set `typescript.tsdk`.
101
1023. Keep VS Code's built-in **TypeScript and JavaScript Language Features**
103   extension enabled. avril suppresses its competing results for the active
104   folder while the language server runs, and restores them when it stops.
1054. With `avril.conf` directly in the first workspace folder, the language server
106   starts automatically once the backend is configured. Nested configurations
107   do not trigger startup. Without a root configuration, run **avril: Start
108   Language Server** manually, then open a TS/TSX/JS/JSX file.
109
110The server follows real avril configuration, imports, packages, and declarations.
111Unsaved imports and disk/config changes refresh automatically. No manifest or
112generated tsconfig is needed. The editor may populate the permitted cache,
113but never writes lockfiles or application files.
114
115Use `avril.lsp.options` for CLI policy flags, for example
116`["--offline", "--frozen"]`. Restart the language server after changing launch
117settings. **avril: Stop Language Server** shuts down the server and native child
118and prevents automatic restarts until you run **avril: Start Language Server**
119or reload the window. Set `avril.lsp.autoStart` to `false` to opt out persistently.
120Use `avril.lsp.preferences` for native TypeScript preferences (for example,
121`{"referencesCodeLensEnabled": true, "includeInlayParameterNameHints": "all"}`).
122These update live; omitted preferences preserve native defaults.
123Creating a root `avril.conf` starts the server; removing it stops an automatically
124started server. Untrusted workspaces cannot start it.
125
126Avril uses the native TypeScript language-service results for completion and
127resolution, navigation, rename, symbols, formatting, semantic tokens, inlay
128hints, call hierarchy, code actions, and the other capabilities advertised by
129the server. Type hierarchy is not advertised because the pinned native backend
130does not implement it. Workspace sources remain editable; acquired npm files
131open as immutable `avril-builtin:/dependencies/` documents. HTTPS, HTTP, and
132builtin declarations open through read-only `avril-https:`, `avril-http:`, and
133`avril-builtin:` providers. The native backend's server capabilities are exposed
134directly; resolution and edits remain subject to Avril's project authority.
135The server currently rebuilds complete generations; broader discovery and
136checking-context limitations are listed in `lib/lsp/README.md` in the source
137checkout.
138
139## Verify the setup
140
141Open a TypeScript file and check hover, completion, and **Go to Definition**.
142For a known example, open `lib/lsp/tests/fixture` from this repository as the
143workspace folder, then open `main.tsx`: hovering `localValue` should show its
144literal type `42`, and Go to Definition should reach `dep file.ts`.
145
146If startup fails, open **View: Toggle Output** and select **avril**. Check that
147both executable paths exist, the backend was built with this repository's patch,
148the workspace is trusted, and `avril.conf` is directly in its first folder (or
149start the server manually). The extension launches `avril lsp`; you do not need
150to run it separately in a terminal.
151
152After rebuilding either executable, run **avril: Stop Language Server**, then
153**avril: Start Language Server** to replace the running processes. Repackage and
154reinstall the VSIX only when the extension itself changes.
155
156## Validation
157
158Run the client lifecycle, ownership, CodeLens conversion, and read-only document
159URI roundtrip tests with `pnpm test` from `editors/vscode/`.
160
161From the repository root, after installing client dependencies:
162
163```sh
164export AVRIL_LSP_BACKEND=/absolute/path/to/avril-tsc
165export AVRIL_LSP_AVRIL="$PWD/target/debug/avril"
166profile=$(mktemp -d /tmp/avril-editor-test.XXXXXX)
167xvfb-run -a codium --wait --verbose --disable-gpu --ozone-platform=x11 \
168  --user-data-dir="$profile/user" --extensions-dir="$profile/extensions" \
169  --skip-welcome --skip-release-notes --disable-workspace-trust \
170  --extensionDevelopmentPath="$PWD/editors/vscode" \
171  --extensionTestsPath="$PWD/editors/vscode/tests/editor.cjs" \
172  "$PWD/lib/lsp/tests/fixture" > "$profile/test.log" 2>&1
173grep AVRIL_EDITOR_TESTS_PASSED "$profile/test.log"
174```
175
176The actual extension-host test invokes hover, definition, completion, signature
177help, rename, and references CodeLens providers; it also runs the resolved CodeLens
178command through VS Code's built-in references UI. It checks unsaved edits and
179diagnostics, and opens real builtin declarations.
180It also checks automatic startup and restoration/suppression of built-in
181TypeScript diagnostics across server stop/start.
182It never saves fixture application files. The trust override is for this known
183fixture only; systems without Chromium sandbox support may also need
184`--no-sandbox` for the isolated test window. Require the success marker: some
185editor versions exit zero even when extension tests fail. Tests are excluded
186from the packaged extension.
187
188Run the server's live/protocol/lifecycle and native API regression tests using the
189commands in `lib/lsp/README.md` in the source checkout.