- A provider result produced after its soft deadline is dropped even when it
is already waiting (the caller was scheduled late or waited on another
plugin first), so the deadline holds on a busy machine. The result is
timestamped when the plugin's thread produces it, so a result that came in
time is still used when it is read late.
- Each precompiled-component write uses its own temporary file: two threads
storing the same component could rename a half-written file into place.
- Tests: the cache-corruption case replaces the file instead of overwriting
the one a running component maps; the yield test no longer counts on a
tick rate; a test that runs a shell script is Unix-only like its
neighbours.
- Plugin web pages declare `@types/node` for their Vite configs instead of
finding the repository's.
- Themes: a plugin theme is an `appearance.theme` value
(`plugin:<id>/<theme>`), offered by Settings › Appearance (and the
preferred themes of Sync with OS), Quick Switch, the toolbar gear menu and
Welcome › Customize. The project window selects it in the plugin host;
picking a built-in theme clears it. While its plugin is off, the built-in
theme of its kind shows and the choice is kept.
- File icon themes: chosen in Settings › Appearance › File icon theme and
kept in `appearance.fileIconTheme`, so every window follows.
- Keymap: plugins' default shortcuts show in Settings › Keymap as the
defaults of their actions: removable, changeable, resettable and part of
conflict checks.
- Problems: a plugin's problems are withdrawn when it stops, fails, is
disabled or uninstalled. Settings › Inspections lists them under Plugins by
plugin name; stored overrides of `plugin:` producers parse correctly.
- Status bar items of plugins are named in the status bar menu and can be
hidden.
- Languages added or removed by plugins refresh Override File Type, the
Code Style pages and Inspections without a restart.
- Uninstalling a plugin deletes the secrets it declared.
- The Settings window follows plugin changes made elsewhere.
- The plugin system is marked Preview (Settings › Plugins, README); Harbor
Night is versioned 0.1.0 like the other official plugins.
- Release: the official plugins are packed, signed (secret
PLUGIN_SIGNING_KEY) and indexed into the release as
`plugins-index.json`; released builds use it as the default marketplace.
Without the key the step is skipped.
- Graphviz: `.dot` / `.gv` files open beside a live preview (a web view
rendering with Graphviz compiled to WebAssembly) in any layout engine,
with zoom, pan, Fit and SVG / PNG export through the save dialog. What
Graphviz reports goes from the page to the plugin's code, which publishes
it as problems on the named line. A DOT language, file icons and a
New Graphviz Graph template.
- Regex Tester: a tool window whose html view sends pattern, flags, text and
replacement as you type; the plugin matches with Rust's regex (linear time)
and answers with matches, groups and the replacement in UTF-16 offsets.
Use Selection and Test Selection take the editor's selection.
- License Header: files without a copyright / SPDX header are reported when
they open and on save; a quick fix and a command add one in the file's
comment syntax (after a shebang or encoding line); a project scan in a
background task reports the rest. Holder and license are settings.
- Harbor Night becomes an official plugin and the one source of the theme
files: `openidea-plugin new --template theme`, the theme docs and tests
start from it.
- Tool windows' renders and events carry the window's active editor, as
commands do, so a view's buttons can act on what the user is editing.
- knip leaves plugins' web pages (projects of their own) alone.
- Remove the Kubernetes official plugin.
- `hello` and `language-toy` move from `plugins/` to
`crates/ide-plugin/tests/fixtures/`: they stay what the host's tests run
against, but are no longer listed as plugins of the repository.
- A `jobs` fixture takes over what only Kubernetes exercised: a tree view
filled by a pinned program, a terminal for the activated entry in the
invoking window, string and number settings, locally and in remote
projects.
- `plugins/` now holds only the official plugins; `build.sh`, CI and the
debug plugin catalog follow.
Install Plugin from Package File now takes an `.oiplugin`, a `.zip` or a
package folder's `plugin.toml`, and goes through the same install page
(capabilities, signature, consent) as every other install.
- A zip may hold the package at its root or in its only folder, as zipping
the folder makes; archiver metadata (`__MACOSX`, `.DS_Store`, `._*`) is
left out. A zip without a `plugin.toml` there, such as an IntelliJ plugin,
is refused with a message saying so. Unsafe paths, links and size limits
are checked as for `.oiplugin` files.
- Picking a `plugin.toml` installs its folder.
Co-authored-by: florentvdry <16673235+florentvdry@users.noreply.github.com>
Plugins can now ship a web page as the UI of a view or custom editor
(`web = "web/index.html"`), so editors built on web libraries are plugins
rather than part of the core.
- Web views: every file under the page's directory is part of the package
(checked, copied on install, covered by the digest and signature) and
served through the `openidea-plugin` URL scheme, under a per-revision
path with a CSP of its own, into an `<iframe sandbox="allow-scripts">`.
An update or reinstall reloads open pages.
- Frame bridge (`window.openidea`), shared by html bodies and web pages:
theme, messages to the plugin's code, `document.get/edit/replace/onChange`
(versioned edits that join the text editor's undo history, Save and dirty
state), `saveFile`/`openFile` through the IDE's dialogs, and IDE shortcuts
the page leaves alone.
- Custom editor layouts: tab, split (Editor and X) or preview over the text
editor, switchable from the tab's actions.
- New points `fileIcons` and `fileTemplates`; new optional capability
`clipboard` for web views.
- Excalidraw official plugin: `.excalidraw` / `.excalidraw.json` open as an
interactive canvas kept in step with the file's text, with self-hosted
fonts, PNG/SVG export, images, file icons, a New Drawing template and
JSON highlighting. Closes#732.
- Fixes: a lock-order deadlock between listing plugins and refreshing
project pins; the dev server ignored edits under `src/features/plugins`.
- `plugins/build.sh` builds and checks web pages; CI typechecks and tests
them.
Co-authored-by: Deng Liu <5108773+dengliu@users.noreply.github.com>
Plugin API (breaking; the plugin system is unreleased):
- Remove the runtime `contributions` interface (register-command,
register-language, register-theme). Commands, languages and themes are
declared in plugin.toml only, so everything a plugin contributes goes
through the install preview and consent. The registry drops runtime
scope, `contribute` and `dispose_runtime`; inline `definition` in
language and theme declarations is gone.
- `completion-item.kind` is a string (the 25 LSP kinds; unknown kinds show
no icon), like the other open-ended kinds.
- `lifecycle.activate` and `commands.run` return `types.error` instead of a
string. The host maps it to the matching error kind, and only `failed`
counts against the plugin: cancelling, a missing grant or an unknown
command does not. The SDK's `Plugin` returns `Result<_, Error>`; plain
messages convert to `Error::Failed`.
Runtime:
- Editor providers of several plugins are called at the same time
(`Actor::submit` + `Pending::wait`): the wait is the slowest plugin's,
not the sum, so each gets the full edit-path budget.
Versioning and tooling:
- Components are checked at install and by `openidea-plugin check` for the
plugin API they were built for; another major or a newer minor is
refused with what to do.
- Tests: the SDK's WIT matches the host's, a simulated next-minor host
links every shipped component, every host function has an SDK wrapper,
released APIs only grow (no snapshot until the first release).
- plugins/build.sh builds every checked-in component, records a source
fingerprint next to it, and `--check` fails on stale components; CI runs
it plus fmt, clippy (host and wasm) and tests for the SDK, the official
plugins and the fixtures.
- The API evolution rules and the checklist for a new host function are in
plugins/README.md; the design notes under docs/ are removed.
- Inject `data-theme` and stable `--openidea-*` colour and font variables
(concrete values; the frame has no IDE stylesheet) into html view bodies.
- Post theme changes to the loaded frame instead of rebuilding srcdoc, so a
theme switch keeps the frame's state; re-send on load to close the race.
- Expose `openidea.theme` / `openidea.onThemeChange` to frame scripts.
- Move `subscribeTheme` / `themeKey` from the Markdown mermaid module to
`src/platform/themeWatch.ts`, shared by both.
- Document the variables in plugins/README.md.
Rework the plugin system per docs/plugin_plan.md (P0–P8):
- Extension-point registry (ide-extension) so new contribution types register
without touching the kernel; languages, run detectors, providers, views and
UI contributions go through it.
- Per-plugin capability consent with a risk-graded ledger; process
capabilities are pinned to resolved binary paths and hashes.
- Async, actor-per-plugin Wasm runtime with lazy activation, cancellation,
events, long-running tasks and idle reclamation.
- Plugin host moved into ide-host, shared by local and remote projects.
- Distribution: install/package tooling (openidea-plugin bin) and a static
market index.
- WIT frozen as openidea:plugin@1.0.0; Rust SDK with mock host.
- Ten official validation plugins under plugins/official.
JDT LS 1.63's ECJ 3.46.200 keeps a constructor's super()/this() call as the first of its statements. Lombok 1.18.48 wrapped that call in the @SneakyThrows try block (ECJ internal error, whole workspace build failed), emitted @NonNull checks before it, and generated constructors without it.
The bundled agent is now 1.18.48-openidea.2: v1.18.48 with lombok#4059 and the upstream constructor-call fix lombok#4089. The new file name gives JDT LS a new workspace, so classes from the previous agent are rebuilt.
Fixes#1000Fixes#830
Java Go to Definition consults the Spring configuration command only inside @Value / getProperty / getRequiredProperty arguments (tree-sitter check), so ordinary Ctrl+click and Ctrl+hover go straight to JDT instead of waiting on a project-wide index rebuild.
The java-usages bundle (1.2.1) keeps its configuration snapshot across editor open/close, builds, saves of non-Java resources and reconciles; it invalidates on Java model changes and unsaved Java edits only.
Fixes#998Fixes#1002
YAML/properties keys stayed inside the generic YAML language server, so Spring configuration bindings and their consumers were unreachable from the editor. A new command in the bundled JDT LS extension (java-usages 1.2.0) resolves keys to @ConfigurationProperties members (prefixes, nested/inherited members, records, constructor aliases, collections), @Value placeholders and PropertyResolver calls, and back from Java to configuration entries; Find Usages merges configuration consumers and declarations with the native Java results. Several profiles or modules are offered as candidates. Closes#796.
Co-authored-by: qjlqyf <109515705+qjlqyf@users.noreply.github.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Java files in mixed Maven projects could not resolve Kotlin types from the same module or upstream reactor modules, because Kotlin compiler output never reached JDT's Java model.
A per-project bridge compiles saved Kotlin sources with the project's own Maven setup into private staging output (a bundled Maven extension redirects outputs and records each module's Kotlin compile result) and mounts the Kotlin classes as marked libraries through a bundled JDT command, leaving m2e/JRE containers and other entries untouched. The last successful snapshot stays mounted while rebuilding; a new one is published when every Kotlin target compiles, even if javac fails, so Java callers of a renamed or removed Kotlin API show their errors in the editor. Kotlin compile failures keep the previous API and are reported under the kotlin-bridge Problems source. Removing the last Kotlin file withdraws the libraries. Changes under build outputs and excluded directories never trigger a rebuild.
Part of #428
lombok.config was ignored in Java builds (e.g. lombok.accessors.chain=true produced void setters), and jdt.ls wrote those classes into target/classes, breaking later Maven builds.
Root cause: Lombok calls getModuleClassLoader(boolean), which newer Equinox removed; the exception is swallowed, Lombok resolves the wrong source path and finds no lombok.config at all, so every config key falls back to its default. Affects every Java project using lombok.config.
Fix: ship Lombok 1.18.48 with the upstream fix projectlombok/lombok#4059 (lombok-1.18.48-openidea.1, embedded in the app, no download) as the jdt.ls agent; the versioned path also resets the jdt.ls workspace so stale output is rebuilt. A user-configured agent still takes precedence. Return to Maven Central once an official release includes the fix (source and checksum in plugins/lombok/README.md).
Verified on macOS: 5 clean builds with chained setters, identical output to official 1.18.48 without lombok.config, the app rebuilds already-poisoned target/classes, and Run works. Windows and Linux not run.
Fixes#565
Find Usages mixed reads and writes of a Java field, including Lombok getter and setter calls, because jdtls has no read/write classification in its references. The usages popup and Find window now have Read and Write toggles. Read-write accesses stay visible in either mode and unclassified results are kept.
Classification comes from a jdtls extension in `plugins/java-usages`, embedded as a jar and installed beside the other bundles. The checked-in jar was rebuilt from source with ECJ and matches byte for byte. Any extension failure falls back to standard references, so a jdtls upgrade can lose the filter but not Find Usages; rebuilding the jar on an upgrade is manual and described in the plugin README. Older installed jars are removed. Other languages keep their plain result count.
Co-authored-by: NingYuanLin <57001533+NingYuanLin@users.noreply.github.com>
HTML files in Angular projects were highlighted as plain HTML. Languages can now declare framework UI modes with root markers (angular.json, node_modules/@angular/core); files under such a root get the framework's editor mode, re-detected when a marker appears or disappears, and the root-marker lookup is shared with language server roots. The Angular Template mode (vendored @codemirror/lang-angular, MIT) adds @if/@for/@switch/@defer/@let blocks, key and animation binding names, and colours {{ }} delimiters.
Lazily loaded editor modes are now loaded before a document's first editor opens, so a file never renders as plain text first (this also left Angular templates uncoloured).
Co-authored-by: nntndfrk <2458463+nntndfrk@users.noreply.github.com>
Run oxfmt once over the whole repository (formatting only, no logic changes) and add `pnpm format:check` to the frontend CI job so unformatted code no longer builds up. `.oxfmtrc.json` now skips the generated theme docs, test fixtures and code blocks inside Markdown.
Co-authored-by: jaw52 <53564781+jaw52@users.noreply.github.com>
Adds Solarized Light, Solarized Dark, One Light and One Dark as built-in themes across the workbench, editor, terminal and Mermaid, keeping the original palettes (MIT notices in THIRD_PARTY_LICENSES.md, mapping in docs/themes.md).
- Native window colours are read from tokens.css at build time (`theme_frame.rs`) instead of a second colour table.
- Startup restores the built-in palette before first paint.
- Editor schemes, the terminal and Mermaid refresh on switches between themes of the same kind.
- The plugin packages of the same themes are removed.
- A test requires every built-in palette theme to define each token (only listed ones may inherit from the base theme), so new tokens can't silently miss them.
Co-authored-by: Claude <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Solarized Light/Dark and One Light/Dark ship as theme plugins (plugins/theme-solarized, plugins/theme-one) with complete UI tokens, editor schemes and terminal colours, and the original palettes' MIT notices. Installing a plugin now also copies its LICENSE/NOTICE/COPYING.
Theme handling that benefits every plugin theme:
- The last plugin theme is restored before first paint (splash, workbench); the native window background follows the theme.
- HSL / color-mix() / var() colours are resolved to RGB for native windows, the Settings window and Mermaid.
- Mermaid, the terminal and editor schemes follow switches between two themes of the same kind.
- An explicitly chosen editor scheme wins over a plugin theme's editor colours.
Supersedes #85.
Co-authored-by: bghtyu <3931591+bghtyu@users.noreply.github.com>
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn
Per the maintainer's decision for #24, no third-party themes are bundled; instead a theme plugin template and docs let the community port themes (IntelliJ also ships few themes, the rest are plugins).
- templates/theme-plugin: manifest-only plugin with an original example (Harbor Night) covering every UI token and an editor scheme (.icls equivalent).
- docs/plugins/themes.md: format, IntelliJ / VS Code porting tables, generated token reference (pnpm gen:theme-docs); drift test fails when tokens.css and the template/reference disagree.
- pnpm theme:import-intellij: dependency-free converter for IntelliJ .theme.json (+ .icls).
- Plugin host: themes may name an editor-scheme merged over the theme; comments allowed in theme files.
- Fixes: a plugin theme's kind now switches the light/dark base; plugin themes go in their own stylesheet so the Appearance accent and editor scheme still layer on top.
Verified: ide-plugin tests, vitest (44), in-app on macOS: installed the template from disk, applied Harbor Night (dark base + teal accent over Islands Light), back to default restored the light theme.
Claude-Session: https://claude.ai/code/session_01VUYsdXA2nkF5v6zsC93dpn