This is a demo plugin that showcases Iona language support in IntelliJ-based IDEs. It teaches the IDE to understand .iona source files: it lexes and parses them into a PSI tree, colours them, resolves local references, surfaces real diagnostics from the Iona compiler, and runs a file straight from the editor. It is a compact reference implementation, not a production language plugin.
- 📄 File recognition:
.ionafiles are associated with the Iona language and icon. - 🎨 Syntax highlighting: a JFlex lexer drives keyword, literal, comment, and operator colouring.
- 🌳 PSI and parsing: a Grammar-Kit grammar builds a full PSI tree of declarations, types, statements, and expressions.
- 🔗 Go to definition: bare identifier uses resolve to their declaration within the same file.
- 🩺 Live diagnostics: runs the Iona compiler off the EDT and renders its errors and warnings as editor annotations.
▶️ Run configuration: build and run a single.ionafile from a gutter icon or the Run/Debug Configurations dialog.
This is a demo and is not published to the JetBrains Marketplace. Run it from source:
git clone https://github.com/broken-bytes/Iona-IntelliJ-Plugin
cd Iona-IntelliJ-Plugin
./gradlew runIderunIde launches a sandbox IDE with the plugin installed.
On Apple Silicon, the IntelliJ Platform run tasks require an aarch64 JVM. If you hit Unsupported JVM architecture: 'x86_64', point Gradle at an arm64 JDK (for example the JetBrains Runtime) via org.gradle.java.home in ~/.gradle/gradle.properties.
The diagnostics and run features shell out to the Iona compiler, so the plugin needs to know how to invoke it. The command is resolved in this order, and the first match wins:
| Source | Example |
|---|---|
| JVM system property | -Diona.diagnostics.cmd="dotnet /path/to/Iona.dll" |
| Environment variable | IONA_DIAGNOSTICS_CMD="dotnet /path/to/Iona.dll" |
| Config file | first non-blank line of ~/.iona-diagnostics |
If none is set, the language features still work and only compiler diagnostics and Run are disabled (a hint is logged).
Iona maps types like Console onto the .NET BCL (System.Console). For the compiler's front-end to resolve them, set IONA_SDK_DIR to your .NET shared framework directory. Otherwise the compiler reports C0004 "Top level definition Console is not defined".
# find your runtime path with: dotnet --list-runtimes
set -gx IONA_SDK_DIR /usr/local/share/dotnet/shared/Microsoft.NETCore.App/10.0.3- Configure the compiler command (see above) and open any
.ionafile. - Syntax highlighting and go to definition (⌘+click) work immediately.
- Errors from the compiler appear inline as you edit.
- Click the gutter icon next to a file (or create an Iona run configuration) to build and run it. Extra compiler arguments go in the configuration's Program arguments field, and the target file is appended automatically.
.iona file
└─ IonaFileType file association
└─ IonaParserDefinition JFlex lexer + Grammar-Kit parser, builds the PSI
└─ IonaSyntaxHighlighter token to colour
└─ IonaReference identifier to declaration (file-local)
└─ IonaExternalAnnotator runs the Iona compiler for diagnostics
└─ dev.iona.ide.run run configuration type (build and run a file)
The compiler boundary is deliberately thin. IonaToolchain owns all process and command knowledge and parses the compiler's --emit-diagnostics-json output into plain data, while the ide layer adapts that data to IntelliJ's annotation and execution models.
Built with Kotlin and the IntelliJ Platform Gradle Plugin, with the lexer and parser generated by JFlex and Grammar-Kit.
./gradlew build # compile, generate lexer and parser, run tests, verify the plugin
./gradlew test # run the test suite (IntelliJ platform test framework, JUnit 4)
./gradlew runIde # sandbox IDESource layout:
| Package | Responsibility |
|---|---|
dev.iona.lang |
language, file type, lexer, parser, PSI, highlighting |
dev.iona.toolchain |
compiler invocation and diagnostics JSON model (IDE-agnostic) |
dev.iona.ide.annotator |
external annotator and span to offset mapping |
dev.iona.ide.run |
run configuration type |
As a showcase, the scope is intentionally narrow:
- Reference resolution is file-local. There is no cross-file, standard-library, or
use-import resolution. - Diagnostics require a configured compiler, and renaming declarations is not supported.
- Linebreaks are currently treated as whitespace by the parser.
Demo project. See the repository for license details.
