Skip to content

Commit 5d234ef

Browse files
hyperpolymathclaude
andcommitted
feat(res-to-affine): land tree-sitter grammar build pipeline (Phase 2a, Refs #57)
Phase 2 of the `.res → .affine` migration assistant (#57) replaces the Phase-1 line-regex scanner with a tree-sitter AST walker. The grammar itself is manifest-vendored in `editors/tree-sitter-rescript/` (since #314), but the actual build pipeline that turns the manifest into a loadable parser had not been wired up. This commit is that wiring. - `justfile` gains an `install-grammar` recipe that wraps the existing `editors/tree-sitter-rescript/scripts/install.sh` so the bootstrap step is a discoverable `just` recipe alongside `build`/`test`/etc. - `editors/tree-sitter-rescript/scripts/install.sh` updates its error message when the `tree-sitter` CLI is missing to point at both the Rust-native install (`cargo install tree-sitter-cli`, the repo's preferred path for CLI tooling per CLAUDE.md) and the existing Node-based one (`npm install -g tree-sitter-cli`). The script behaviour is unchanged when the CLI is present. - `.github/workflows/ci.yml` gains a `migration-assistant` job that installs the tree-sitter CLI via npm (the fast CI path — a pre-built binary, ~5 s vs. ~5 min for `cargo install` from source), runs `just install-grammar`, verifies `tools/vendor/tree-sitter-rescript/ src/parser.c` was produced, and smoke-parses the existing `tools/res-to-affine/test/fixtures/sample.res` fixture. The job sits alongside `vscode-smoke` as a Node-using carve-out under the same reasoning (manifest dep on an npm-distributed tool whose binary output is what we actually consume; no new TS source in this repo). - `editors/tree-sitter-rescript/README.md` documents the dual install path, the new justfile recipe, and the CI gate. Phase 2b (the actual walker — `walker.ml`, AST-based detection of `side-effect-import`, `--engine` CLI flag, snapshot tests vs. the regex scanner) stacks on top of this branch. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent de19c49 commit 5d234ef

4 files changed

Lines changed: 100 additions & 3 deletions

File tree

.github/workflows/ci.yml

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,3 +119,63 @@ jobs:
119119
# Headless display required because @vscode/test-electron launches
120120
# the real Electron-based VS Code binary.
121121
run: xvfb-run -a npm test
122+
123+
migration-assistant:
124+
# Build pinned tree-sitter-rescript grammar consumed by the
125+
# `.res → .affine` migration assistant (#57 Phase 2). The grammar
126+
# is manifest-vendored (`editors/tree-sitter-rescript/package.json`)
127+
# so this job exists to (a) verify the install script and pinned
128+
# commit still build cleanly and (b) gate `tools/res-to-affine/`
129+
# walker work that depends on the generated parser.
130+
runs-on: ubuntu-latest
131+
132+
steps:
133+
- name: Checkout code
134+
uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2
135+
136+
- name: Set up Node.js
137+
uses: actions/setup-node@48b55a011bda9f5d6aeb4c2d9c7362e8dae4041e # v4
138+
with:
139+
node-version: "20"
140+
141+
- name: Install tree-sitter CLI
142+
# npm install of tree-sitter-cli is the fast CI path (~5 s vs.
143+
# ~5 min for `cargo install tree-sitter-cli`). The repo's
144+
# preferred local path is cargo (see editors/tree-sitter-rescript/
145+
# README.md) — both produce the same `tree-sitter` binary that
146+
# the install script invokes via `command -v`. The version
147+
# tracks `tree-sitter-rescript`'s package.json devDependency
148+
# range.
149+
run: npm install -g tree-sitter-cli@^0.25.0
150+
151+
- name: Build pinned tree-sitter-rescript grammar
152+
run: just install-grammar
153+
154+
- name: Verify generated parser
155+
# `tree-sitter generate` is supposed to drop src/parser.c into
156+
# the cloned grammar. If it didn't, the install path is broken
157+
# and Phase-2 walker work cannot proceed; fail loudly here
158+
# rather than at the OCaml link step in a downstream PR.
159+
run: |
160+
test -f tools/vendor/tree-sitter-rescript/src/parser.c \
161+
|| { echo "error: parser.c not produced by tree-sitter generate" >&2; exit 1; }
162+
echo "parser.c size: $(wc -c < tools/vendor/tree-sitter-rescript/src/parser.c) bytes"
163+
164+
- name: Smoke-parse a sample .res file
165+
# Sanity-check that the grammar actually parses a non-trivial
166+
# ReScript source. Picks the existing res-to-affine test fixture
167+
# so any drift in the pinned commit's syntactic surface area
168+
# surfaces here rather than at walker-rule writing time.
169+
run: |
170+
shopt -s nullglob
171+
fixtures=(tools/res-to-affine/test/fixtures/*.res)
172+
if [ ${#fixtures[@]} -eq 0 ]; then
173+
echo "no .res fixtures to smoke-parse; skipping"
174+
exit 0
175+
fi
176+
tree-sitter parse \
177+
--quiet \
178+
"${fixtures[0]}" \
179+
--paths tools/vendor/tree-sitter-rescript \
180+
> /dev/null
181+
echo "smoke-parsed: ${fixtures[0]}"

editors/tree-sitter-rescript/README.md

Lines changed: 27 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,38 @@ snapshots, since AST shapes may shift.
2525

2626
## Install
2727

28+
From the repo root:
29+
2830
```sh
29-
./scripts/install.sh
31+
just install-grammar # justfile recipe
32+
# or directly:
33+
./editors/tree-sitter-rescript/scripts/install.sh
3034
```
3135

3236
This writes a `tree-sitter-rescript` directory under `tools/vendor/`
3337
(gitignored — same convention as the WASI adapter pinning), containing
34-
the generated parser. Requires `git` and `tree-sitter` CLI on PATH.
38+
the generated parser. Requires `git` and the `tree-sitter` CLI on PATH.
39+
40+
The `tree-sitter` CLI can be installed either way:
41+
42+
```sh
43+
cargo install tree-sitter-cli # Rust-native, repo-preferred
44+
npm install -g tree-sitter-cli # Node-based, also fine
45+
```
46+
47+
CI installs via `npm` for speed (`tree-sitter-cli` from npm is a pre-built
48+
binary, ~5 s install). The `cargo` path builds from source (~5 min on a
49+
cold cache) and is the recommended local install because it keeps the
50+
contributor toolchain centred on Rust rather than Node. The
51+
`package.json` in this directory pins the version range; bump it in
52+
sync when the upstream grammar pin moves.
53+
54+
## Continuous integration
55+
56+
The `migration-assistant` job in `.github/workflows/ci.yml` runs `just
57+
install-grammar` on every PR, then smoke-parses
58+
`tools/res-to-affine/test/fixtures/sample.res`. If the pinned commit
59+
stops building cleanly, this job is the first signal.
3560

3661
## Why manifest, not copy
3762

editors/tree-sitter-rescript/scripts/install.sh

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ BUILD_DIR="${REPO_ROOT}/tools/vendor/tree-sitter-rescript"
1515

1616
if ! command -v tree-sitter >/dev/null 2>&1; then
1717
echo "error: tree-sitter CLI not found on PATH" >&2
18-
echo " install via: npm install -g tree-sitter-cli" >&2
18+
echo " install via either:" >&2
19+
echo " cargo install tree-sitter-cli (Rust-native, repo-preferred)" >&2
20+
echo " npm install -g tree-sitter-cli (Node-based, also fine)" >&2
1921
exit 2
2022
fi
2123

justfile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,16 @@ regen-idaptik-wasm:
123123
dune exec affinescript -- tea-bridge -o ../../idaptik/public/assets/wasm/titlescreen.wasm
124124
@echo "[AffineTEA] titlescreen.wasm regenerated"
125125

126+
# ── Tooling (manifest-driven dev deps) ────────────────────────────────────────
127+
128+
# Fetch + build the pinned tree-sitter-rescript grammar used by the
129+
# `.res → .affine` migration assistant (#57 Phase 2). Output is written
130+
# to `tools/vendor/tree-sitter-rescript/` (gitignored). Requires the
131+
# `tree-sitter` CLI on PATH — install via `cargo install tree-sitter-cli`
132+
# (Rust-native, repo-preferred) or `npm install -g tree-sitter-cli`.
133+
install-grammar:
134+
./editors/tree-sitter-rescript/scripts/install.sh
135+
126136
# ── Validation ────────────────────────────────────────────────────────────────
127137

128138
# Verify golden path end-to-end

0 commit comments

Comments
 (0)