initial commit
This commit is contained in:
145
AGENTS.md
Normal file
145
AGENTS.md
Normal file
@@ -0,0 +1,145 @@
|
||||
# AGENTS.md — Jai IntelliJ Plugin
|
||||
|
||||
Orientation for agents working on this repo. Read this first.
|
||||
|
||||
**Goal:** an IntelliJ plugin for the **Jai** programming language.
|
||||
|
||||
**Hard rule:** do **not** research Jai online — public material is outdated and
|
||||
wrong. The only source of truth is the local install at `~/.local/jai`
|
||||
(`how_to/`, `modules/`, `examples/`). Researching *IntelliJ plugin development*
|
||||
online is fine and encouraged.
|
||||
|
||||
---
|
||||
|
||||
## Run anything with `./jaigradle`
|
||||
|
||||
```bash
|
||||
./jaigradle test # unit tests
|
||||
./jaigradle check # full verification
|
||||
./jaigradle tasks # discover tasks
|
||||
```
|
||||
|
||||
**Never call `./gradlew` directly.** There is no JDK on `PATH` and `JAVA_HOME`
|
||||
is unset in a fresh shell. `./jaigradle` resolves the JDK via mise, then
|
||||
delegates. It works from an environment with no Java at all.
|
||||
|
||||
Do not try to fix this with `org.gradle.java.home` in `gradle.properties` —
|
||||
already tried, it does not work, because `gradlew` is a shell script that needs
|
||||
a JVM to launch *itself* before it ever reads that property.
|
||||
|
||||
**Java must be 21+.** The IntelliJ Platform test-framework jars are Java 21
|
||||
bytecode (class major version 65); on JDK 17 every test fails with
|
||||
`UnsupportedClassVersionError`. `mise.toml` pins `java = "temurin-21"`.
|
||||
|
||||
Note that `./jaigradle compileKotlin` **passes on JDK 17** — the template
|
||||
sources never touch the test framework. Compiling is not evidence the toolchain
|
||||
is correct. Run tests.
|
||||
|
||||
---
|
||||
|
||||
## Verify with the JUnit XML, not the exit code
|
||||
|
||||
A green `test` task does not prove tests ran. Always confirm:
|
||||
|
||||
```bash
|
||||
cat build/test-results/test/*.xml | head -3
|
||||
```
|
||||
|
||||
Look for `tests="N"` with `failures="0" errors="0"` and **N > 0**.
|
||||
|
||||
Last verified state (all green):
|
||||
|
||||
```text
|
||||
TEST-dev.hgh.HarnessSmokeTest.xml -> tests=2 skipped=0 failures=0 errors=0
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Current state
|
||||
|
||||
### Done
|
||||
|
||||
- `docs/JAI_LANGUAGE_REFERENCE.md` — language reference derived from
|
||||
`~/.local/jai`, keywords/tokens transcribed from the compiler's own lexer.
|
||||
**Read this before writing any lexer or parser code.**
|
||||
- `docs/BUILD_PLAN.md` — phased plan, testing strategy, risks, open questions.
|
||||
- `mise.toml` → `java = "temurin-21"` (was 17, which was broken).
|
||||
- `jaigradle` — JDK-resolving Gradle wrapper. Executable, verified.
|
||||
- `src/test/kotlin/dev/hgh/HarnessSmokeTest.kt` — proves the platform boots
|
||||
headlessly. **If this fails, no other test can be trusted.**
|
||||
|
||||
### Not done — pick up here
|
||||
|
||||
1. **`git init`.** Still not a repository. Do this first; there is no rollback
|
||||
point right now. Add `.kotlin` to `.gitignore` (currently untracked and
|
||||
unignored).
|
||||
2. **Strip the template.** `src/main/kotlin/MyToolWindowFactory.kt`,
|
||||
`MyMessageBundle.kt`, `messages/MyMessageBundle.properties`, and the
|
||||
`toolWindow` registration + `resource-bundle` in `plugin.xml` are all
|
||||
JetBrains scaffold and must go. `plugin.xml` metadata (name, vendor,
|
||||
description) is still placeholder text.
|
||||
3. **Phase 1: lexer** — see the plan.
|
||||
|
||||
### Open questions for the user (unanswered)
|
||||
|
||||
Scope (Phases 0–4 vs 0–7), compiler integration, target IDEs, JDK policy. See
|
||||
`docs/BUILD_PLAN.md` §6. Scope is the one that most affects the work.
|
||||
|
||||
---
|
||||
|
||||
## Architecture decisions already made
|
||||
|
||||
Both are justified in `docs/BUILD_PLAN.md` §2. Do not silently reverse them.
|
||||
|
||||
- **Hand-written lexer, not JFlex.** Jai here-strings (`#string DONE … DONE`)
|
||||
have a *runtime-captured* terminator, which a DFA generator cannot express.
|
||||
Nested block comments need a depth counter. Both would end up as hand-written
|
||||
Java inside JFlex actions anyway.
|
||||
- **Grammar-Kit BNF for parser + PSI.** Verified headless: the plugin ID is
|
||||
`org.jetbrains.intellij.platform.grammarkit`, bundled in the IntelliJ Platform
|
||||
Gradle Plugin since 2.12.0 (we run 2.18.1). `generateLexer` / `generateParser`
|
||||
already appear in `./jaigradle tasks --all` — no extra dependency needed.
|
||||
- **Ship highlighting before the parser.** Highlighting needs only the lexer.
|
||||
|
||||
---
|
||||
|
||||
## The test corpus is the main asset
|
||||
|
||||
`~/.local/jai` holds **714 `.jai` files, 16.4 MB** of real code by the language
|
||||
authors. Use it as the primary correctness gate instead of hand-written samples.
|
||||
|
||||
The highest-value assertion, per the plan: lex every file and check the
|
||||
concatenation of all token texts reproduces the source **byte for byte**. An
|
||||
IntelliJ lexer must tile its input with no gaps or overlaps, so this single
|
||||
invariant over 16 MB catches nearly every lexer bug — with no fixture boot and
|
||||
no human review. Also assert no `BAD_CHARACTER` and that every `advance()`
|
||||
strictly increases the offset (catches infinite loops, which hang the IDE rather
|
||||
than failing visibly).
|
||||
|
||||
Same idea later: zero `PsiErrorElement` across the corpus for the parser;
|
||||
formatting is idempotent for the formatter.
|
||||
|
||||
---
|
||||
|
||||
## Environment gotchas
|
||||
|
||||
- **Stale Gradle daemons.** Mixing JDK 17 and 21 daemons caused
|
||||
`Timeout waiting to lock journal cache`. Fix: `./jaigradle --stop`.
|
||||
- **`timeout` does not exist on this macOS box.** Do not use it in scripts.
|
||||
- **Noisy test stderr.** Fixture runs log Vue/JS `PluginException`s from bundled
|
||||
plugins. Tests pass regardless, but real failures can be buried — check the
|
||||
XML. Narrowing the test fixture later would help.
|
||||
- **`runIde` is never required.** Everything is verifiable headlessly; that is a
|
||||
hard project requirement, not a preference. Do not ask the user to open an IDE
|
||||
to check your work.
|
||||
|
||||
---
|
||||
|
||||
## Working agreement
|
||||
|
||||
- Verify claims by running commands; prefer empirical checks over docs. Several
|
||||
plan decisions came from testing assumptions that turned out false.
|
||||
- Keep the working tree clean — revert throwaway probes.
|
||||
- Generated sources (once Grammar-Kit is wired up) go in `src/main/gen`, are
|
||||
committed, and are **never hand-edited**; regenerate instead.
|
||||
- Update this file when project state changes.
|
||||
Reference in New Issue
Block a user