Build an installable plugin ZIP: real README/CHANGELOG, cache-poisoning recovery

- README documents install-from-disk and what actually works today
- jaitest prints the recovery steps when a poisoned build cache makes
  :test report NO-SOURCE, and AGENTS.md records the failure mode
This commit is contained in:
hgranthorner
2026-08-04 10:42:10 -04:00
parent f52b8c5899
commit 746647d27d
4 changed files with 69 additions and 137 deletions

View File

@@ -171,6 +171,20 @@ formatting is idempotent for the formatter.
`NoSuchFileException: .../in-progress-results-generic.bin`, and no XML is
written. It is infrastructure, not a test failure — `./jaitest` retries once
automatically. Do not go debugging the test that "failed".
- **A poisoned build cache can make tests silently vanish.** Symptom:
`BUILD SUCCESSFUL`, `:compileTestKotlin FROM-CACHE`, `:test NO-SOURCE`, and
`build/classes/kotlin/test` is empty. The cache stored an empty output
directory from a build whose outputs were deleted underneath it, and the entry
is keyed by input hash so it never gets replaced. This is the exact failure
mode `./jaitest`'s "total tests = 0 is a failure" rule exists to catch.
Recover with:
```bash
./jaigradle --stop
rm -rf build .gradle ~/.gradle/caches/build-cache-1
./jaitest
```
- **`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

View File

@@ -1,5 +1,13 @@
<!-- Keep a Changelog guide -> https://keepachangelog.com -->
# Intellijai Changelog
# Jai Plugin Changelog
## [Unreleased]
### Added
- `.jai` file type, icon, and language registration
- Hand-written Jai lexer covering the full token set of the compiler's own lexer,
including nesting block comments and here-strings
- Syntax highlighting and a colour settings page
- Comment/uncomment support and brace matching, including `.{` and `.[`

174
README.md
View File

@@ -1,152 +1,54 @@
# Intellijai
# Jai plugin for IntelliJ IDEA
[![Twitter Follow](https://img.shields.io/badge/follow-%40JBPlatform-1DA1F2?logo=twitter)](https://twitter.com/JBPlatform)
[![Developers Forum](https://img.shields.io/badge/JetBrains%20Platform-Join-blue)][jb:forum]
Support for the [Jai](https://jai.community) programming language.
Everything here is derived from the local Jai distribution at `~/.local/jai`,
never from online material (see `AGENTS.md`).
## Overview
## What works today
This repository implements an IntelliJ Platform plugin.
- `.jai` file type with its own icon
- Syntax highlighting: keywords, built-in type names, compiler directives
(`#import`, `#run`, …), notes (`@Cleanup`), numbers (hex / binary / hexfloat /
`_` separators), strings, here-strings (`#string DONE … DONE`), nesting block
comments, operators, `---`, `$`/`$$`, `it` / `it_index`
- Colour settings page (**Settings → Editor → Color Scheme → Jai**)
- Comment / uncomment (`//` and nesting `/* */`)
- Brace matching, including the Jai-only `.{` struct-literal and `.[`
array-literal openers
## Demo Functionality
Not yet: parser and PSI, so no structure view, go-to-definition, completion,
formatting, or inspections. See `docs/BUILD_PLAN.md` for the phase plan.
The sample plugin adds a `My Tool Window` tool window with a simple functionality of shuffling a random number.
## Install it locally
## Plugin structure
A generated project contains the following content structure:
```
.
├── .run/ Predefined Run/Debug Configurations
├── gradle
│ ├── wrapper/ Gradle Wrapper
│ ├── libs.versions.toml Version catalog
├── src Plugin sources
│ └── main
│ ├── kotlin/ Kotlin production sources
│ └── resources/ Plugin resources
│ ├── META-INF/ Plugin configuration file and logo
│ └── messages/ Message bundles
├── .gitignore Git ignoring rules
├── build.gradle.kts Gradle build configuration
├── gradle.properties Gradle configuration properties
├── gradlew *nix Gradle Wrapper script
├── gradlew.bat Windows Gradle Wrapper script
├── README.md This file
└── settings.gradle.kts Gradle project settings
```bash
./jaigradle buildPlugin
# -> build/distributions/intellijai-1.0.0-SNAPSHOT.zip
```
In addition to the configuration files, the most crucial part is the `src` directory, which contains our implementation
and the manifest for our plugin [plugin.xml][file:plugin.xml].
In the IDE: **Settings → Plugins → ⚙ → Install Plugin from Disk…**, pick that
ZIP, restart when prompted. Requires build 253 (2025.3) or newer; verified
compatible with IU-253, IU-261 and IU-262 by the JetBrains Plugin Verifier.
> [!NOTE]
> To use Java in your plugin, create the `/src/main/java` directory.
To try it, open any file from `~/.local/jai/how_to/`.
The plugin logo is placed in `src/main/resources/META-INF/pluginIcon.svg`. See [Plugin Logo][docs:logo] for more
information and logo requirements.
Uninstall or update the same way — installing a new ZIP over the old one
replaces it.
## Build script
## Develop
The [build.gradle.kts][file:build.gradle.kts] is the core of the project definition. It applies three Gradle plugins:
| Plugin | Description |
|-----------------------------------|----------------------------------------------------------------------------------|
| `org.jetbrains.kotlin.jvm` | Adds Kotlin support |
| `org.jetbrains.changelog` | Simplifies patching the [CHANGELOG.md][file:CHANGELOG.md] file |
| `org.jetbrains.intellij.platform` | The [IntelliJ Platform Gradle Plugin][docs:intellij-platform-gradle-plugin-docs] |
The `intellijPlatform` dependencies block selects the IDE to compile against:
```kotlin
intellijIdea("2025.3.5")
```bash
./jaigradle test # or ./jaitest, which reports the JUnit XML
./jaigradle check # full verification
```
See [Target Versions][docs:target-version] for more information.
Never call `./gradlew` directly: there is no JDK on `PATH`, and `./jaigradle`
resolves one via mise first. Read `AGENTS.md` before changing anything.
The `intellijPlatform` dependencies block also contains a dependency on the platform testing framework:
Key docs:
```kotlin
testFramework(TestFrameworkType.Platform)
```
See [Testing][docs:testing] for more information
## Plugin configuration file
The plugin configuration file is a [plugin.xml][file:plugin.xml] file located in the `src/main/resources/META-INF`
directory. It provides general information about the plugin, its dependencies, extensions, and listeners.
You can read more about this file in the [Plugin Configuration File][docs:plugin.xml] section of our documentation.
### Plugin ID and name
Generated plugin ID and name may require adjustment.
These values are generated based on _Group ID_ and _Artifact ID_ provided in the IDE Plugin wizard. It is recommended to
review `<id>` and `<name>` elements in the plugin.xml file, and adjust them if needed.
Please note that Gradle properties `rootProject.name` and `project.group` don't need to match the `<id>` and `<name>`
elements. There is no IntelliJ Platform-related reason they should as they serve different functions.
## Predefined Run/Debug configurations
Within the default project structure, there is a `.run` directory provided containing predefined *Run/Debug
configurations* that expose corresponding Gradle tasks:
| Configuration name | Description |
|---------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| Run IDE with Plugin | Runs [`:runIde`][docs:intellij-platform-gradle-plugin-runIde] IntelliJ Platform Gradle Plugin task. Use the *Debug* icon for plugin debugging. |
| Run Tests | Runs [`:check`][gradle:lifecycle-tasks] Gradle task. |
| Run Verifications | Runs [`:verifyPlugin`][docs:intellij-platform-gradle-plugin-verifyPlugin] IntelliJ Platform Gradle Plugin task to check the plugin compatibility against the specified IntelliJ IDEs. |
> [!NOTE]
> You can find the logs from the running task in the `idea.log` tab.
## Publishing the plugin
> [!TIP]
> Make sure to follow all guidelines listed in [Publishing a Plugin][docs:publishing] to follow all recommended and
required steps.
Releasing a plugin to [JetBrains Marketplace](https://plugins.jetbrains.com) is a straightforward operation that uses
the `publishPlugin` Gradle task provided by
the [intellij-platform-gradle-plugin][docs:intellij-platform-gradle-plugin-docs].
You can also upload the plugin to the [JetBrains Plugin Repository](https://plugins.jetbrains.com/plugin/upload)
manually via UI.
## Useful links
- [IntelliJ Platform SDK Plugin SDK][docs]
- [IntelliJ Platform Gradle Plugin Documentation][docs:intellij-platform-gradle-plugin-docs]
- [IntelliJ Platform Explorer][jb:ipe]
- [JetBrains Marketplace Quality Guidelines][jb:quality-guidelines]
- [IntelliJ Platform UI Guidelines][jb:ui-guidelines]
- [JetBrains Marketplace Paid Plugins][jb:paid-plugins]
- [IntelliJ SDK Code Samples][gh:code-samples]
[docs]: https://plugins.jetbrains.com/docs/intellij
[docs:plugin.xml]: https://plugins.jetbrains.com/docs/intellij/plugin-configuration-file.html?from=IJPluginReadmeFile
[docs:publishing]: https://plugins.jetbrains.com/docs/intellij/publishing-plugin.html?from=IJPluginReadmeFile
[docs:intellij-platform-gradle-plugin-docs]: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin.html?from=IJPluginReadmeFile
[docs:intellij-platform-gradle-plugin-runIde]: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-tasks.html?from=IJPluginReadmeFile#runIde
[docs:intellij-platform-gradle-plugin-verifyPlugin]: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-tasks.html?from=IJPluginReadmeFile#verifyPlugin
[docs:logo]: https://plugins.jetbrains.com/docs/intellij/plugin-icon-file.html?from=IJPluginReadmeFile
[docs:target-version]: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html?from=IJPluginReadmeFile#target-versions
[docs:testing]: https://plugins.jetbrains.com/docs/intellij/tools-intellij-platform-gradle-plugin-dependencies-extension.html?from=IJPluginReadmeFile#testing
[file:build.gradle.kts]: ./build.gradle.kts
[file:CHANGELOG.md]: ./CHANGELOG.md
[file:gradle.properties]: ./gradle.properties
[file:plugin.xml]: ./src/main/resources/META-INF/plugin.xml
[gh:code-samples]: https://github.com/JetBrains/intellij-sdk-code-samples
[gradle:lifecycle-tasks]: https://docs.gradle.org/current/userguide/java_plugin.html#lifecycle_tasks
[jb:github]: https://github.com/JetBrains/.github/blob/main/profile/README.md
[jb:forum]: https://platform.jetbrains.com/
[jb:quality-guidelines]: https://plugins.jetbrains.com/docs/marketplace/quality-guidelines.html
[jb:paid-plugins]: https://plugins.jetbrains.com/docs/marketplace/paid-plugins-marketplace.html
[jb:ipe]: https://jb.gg/ipe
[jb:ui-guidelines]: https://jetbrains.github.io/ui
| File | What it is |
| --- | --- |
| `AGENTS.md` | how to work in this repo; current state |
| `docs/JAI_LANGUAGE_REFERENCE.md` | the language, transcribed from the compiler |
| `docs/BUILD_PLAN.md` | phased plan and testing strategy |

View File

@@ -38,6 +38,14 @@ echo
echo "=== JUnit XML ==="
if [ ${#xml[@]} -eq 0 ]; then
echo "NO TEST XML PRODUCED — tests did not run."
echo
echo "If Gradle reported ':test NO-SOURCE' while the sources clearly exist, the"
echo "build cache holds a poisoned entry with empty compileTestKotlin outputs"
echo "(a concurrent build had its outputs deleted mid-run). Recover with:"
echo
echo " ./jaigradle --stop"
echo " rm -rf build .gradle ~/.gradle/caches/build-cache-1"
echo " ./jaitest"
exit 1
fi