Compare commits

...
Author SHA1 Message Date
l0ng-ai ac7139c94d feat(plugins): open two texts in the diff viewer (API 1.7)
Plugins could show their own content in an editor tab (open-content-tab) but
could open the diff viewer only as the reply to one of that tab's actions. A
review plugin (a merge request's files, say) had no way to show a file's
before and after.

views.open-diff opens two texts in the invoking window's diff viewer, with
optional labels and title and a file name that picks the syntax highlighting;
web views send { op: "open-diff", ... }. The SDK wraps it as host::open_diff
with a mock. The plugin API moves to 1.7.0 (1.6.0 is released) and the checked-in
components are rebuilt.
2026-11-13 11:47:06 +08:00
174 changed files with 493 additions and 285 deletions

No files matched your search

+1 -1
View File
@@ -34,7 +34,7 @@ use std::path::{Component, Path, PathBuf};
pub const MANIFEST_FILE: &str = "plugin.toml"; pub const MANIFEST_FILE: &str = "plugin.toml";
/// The plugin API (engine) version this host implements. /// The plugin API (engine) version this host implements.
pub const ENGINE_VERSION: &str = "1.6.0"; pub const ENGINE_VERSION: &str = "1.7.0";
/// The 0.1 API, still accepted for contribution-only packages and 0.1 components. /// The 0.1 API, still accepted for contribution-only packages and 0.1 components.
pub const LEGACY_API: &str = "0.1"; pub const LEGACY_API: &str = "0.1";
/// Marketplace categories, in the order they are shown. /// Marketplace categories, in the order they are shown.
+13
View File
@@ -1531,6 +1531,19 @@ impl HostApi for PluginApi {
} }
Ok(()) Ok(())
} }
fn open_diff(
&self,
client: &str,
diff: ide_plugin::ContentDiff,
file_name: Option<String>,
) -> Result<(), HostError> {
super::execution::validate_diff(&diff)?;
if let Some(name) = &file_name {
super::execution::label(name, 256)?;
}
self.shared.sink.emit(Some(client), PluginEvent::OpenDiff { plugin_id: self.id().into(), diff, file_name });
Ok(())
}
fn reply_content_tab( fn reply_content_tab(
&self, &self,
client: &str, client: &str,
+13 -8
View File
@@ -72,14 +72,19 @@ pub(super) fn validate_reply(reply: &ContentTabReply) -> Result<(), HostError> {
return Err(HostError::Invalid("content status or error too long".into())); return Err(HostError::Invalid("content status or error too long".into()));
} }
if let Some(diff) = &reply.diff { if let Some(diff) = &reply.diff {
body(&diff.left)?; validate_diff(diff)?;
body(&diff.right)?; }
for value in [&diff.left_label, &diff.right_label].into_iter().flatten() { Ok(())
label(value, 128)?; }
}
if let Some(title) = &diff.title { pub(super) fn validate_diff(diff: &ide_plugin::ContentDiff) -> Result<(), HostError> {
label(title, 256)?; body(&diff.left)?;
} body(&diff.right)?;
for value in [&diff.left_label, &diff.right_label].into_iter().flatten() {
label(value, 128)?;
}
if let Some(title) = &diff.title {
label(title, 256)?;
} }
Ok(()) Ok(())
} }
@@ -188,6 +188,7 @@ pub fn forwarded(event: &PluginEvent) -> bool {
PluginEvent::RunTargetsChanged PluginEvent::RunTargetsChanged
| PluginEvent::WindowRequest { .. } | PluginEvent::WindowRequest { .. }
| PluginEvent::ContentTabReply { .. } | PluginEvent::ContentTabReply { .. }
| PluginEvent::OpenDiff { .. }
| PluginEvent::DecorationsChanged { .. } | PluginEvent::DecorationsChanged { .. }
| PluginEvent::EditorOpen { .. } | PluginEvent::EditorOpen { .. }
| PluginEvent::EditorRanges { .. } | PluginEvent::EditorRanges { .. }
+3
View File
@@ -218,6 +218,9 @@ pub enum PluginEvent {
/// Reply to a content action in this window. /// Reply to a content action in this window.
#[serde(rename_all = "camelCase")] #[serde(rename_all = "camelCase")]
ContentTabReply { plugin_id: String, request_id: String, reply: ide_plugin::ContentTabReply }, ContentTabReply { plugin_id: String, request_id: String, reply: ide_plugin::ContentTabReply },
/// Open two texts in this window's diff viewer.
#[serde(rename_all = "camelCase")]
OpenDiff { plugin_id: String, diff: ide_plugin::ContentDiff, file_name: Option<String> },
/// Plugins, their status or their contributions changed: re-fetch `plugin_list`. /// Plugins, their status or their contributions changed: re-fetch `plugin_list`.
CommandsChanged, CommandsChanged,
+20
View File
@@ -6352,6 +6352,26 @@ fn api14_stage3_configurations_test_results_and_content_actions_use_real_exports
assert!(f.host.parse_test_results("main", "plugin:execution:dynamic", "trap".into()).unwrap().is_none()); assert!(f.host.parse_test_results("main", "plugin:execution:dynamic", "trap".into()).unwrap().is_none());
} }
#[cfg(unix)]
#[test]
fn a_plugin_command_opens_a_diff_in_its_window() {
let f = execution_fixture();
f.take_events();
f.run("execution", "diff", None).unwrap();
f.host.flush_events_at(Instant::now() + Duration::from_secs(3));
assert!(eventually(|| {
f.events.lock().iter().any(|(client, event)| {
client.as_deref() == Some("main")
&& matches!(event, PluginEvent::OpenDiff { plugin_id, diff, file_name }
if plugin_id == "execution"
&& diff.left == "before\n"
&& diff.right == "after\n"
&& diff.title.as_deref() == Some("Review")
&& file_name.as_deref() == Some("src/review.rs"))
})
}));
}
#[test] #[test]
fn api14_fixture_exports_test_selection() { fn api14_fixture_exports_test_selection() {
let f = fixture(Limits::default()); let f = fixture(Limits::default());
+6 -1
View File
@@ -55,7 +55,7 @@ use views_bindings::exports::openidea::plugin::view_provider as wit_view;
use views_bindings::openidea::plugin::view_types as wit_vt; use views_bindings::openidea::plugin::view_types as wit_vt;
/// The API version of the world above, `major.minor` of [`host_api`]. /// The API version of the world above, `major.minor` of [`host_api`].
pub const API_VERSION: &str = "1.6"; pub const API_VERSION: &str = "1.7";
const EPOCH_TICK: Duration = Duration::from_millis(10); const EPOCH_TICK: Duration = Duration::from_millis(10);
pub(crate) const MAX_TEXT: usize = 1 << 20; pub(crate) const MAX_TEXT: usize = 1 << 20;
pub(crate) const MAX_TITLE: usize = 256; pub(crate) const MAX_TITLE: usize = 256;
@@ -170,6 +170,11 @@ pub trait HostApi: Send + Sync {
let _ = (client, tab, cancel, timeout); let _ = (client, tab, cancel, timeout);
Err(HostError::Failed("content tabs unavailable".into())) Err(HostError::Failed("content tabs unavailable".into()))
} }
/// Opens a diff of two texts in the invoking window.
fn open_diff(&self, client: &str, diff: crate::ContentDiff, file_name: Option<String>) -> Result<(), HostError> {
let _ = (client, diff, file_name);
Err(HostError::Failed("diffs unavailable".into()))
}
/// Answers a content action in the invoking window. /// Answers a content action in the invoking window.
fn reply_content_tab(&self, client: &str, request: &str, reply: crate::ContentTabReply) -> Result<(), HostError> { fn reply_content_tab(&self, client: &str, request: &str, reply: crate::ContentTabReply) -> Result<(), HostError> {
let _ = (client, request, reply); let _ = (client, request, reply);
+6
View File
@@ -1770,6 +1770,12 @@ impl views::Host for StoreData {
) )
.map_err(to_wit)) .map_err(to_wit))
} }
fn open_diff(&mut self, diff: views::ContentDiff, file_name: Option<String>) -> Fallible<()> {
if let Err(e) = self.require_window() {
return Ok(Err(e));
}
Ok(self.host.open_diff(self.invocation.client.as_deref().unwrap(), diff.into(), file_name).map_err(to_wit))
}
fn reply_content_tab(&mut self, request_id: String, reply: views::ContentTabReply) -> Fallible<()> { fn reply_content_tab(&mut self, request_id: String, reply: views::ContentTabReply) -> Fallible<()> {
if let Err(e) = self.require_window() { if let Err(e) = self.require_window() {
return Ok(Err(e)); return Ok(Err(e));
+5 -5
View File
@@ -91,15 +91,15 @@ fn the_sdk_carries_the_hosts_wit() {
#[test] #[test]
fn the_version_check_runs_compatible_components_and_explains_the_rest() { fn the_version_check_runs_compatible_components_and_explains_the_rest() {
let host = v("1.6.0"); let host = v("1.7.0");
for ok in ["1.0.0", "1.3.0", "1.4.7", "1.5.0", "1.6.0", "1.0.0-rc.1"] { for ok in ["1.0.0", "1.3.0", "1.4.7", "1.5.0", "1.6.0", "1.7.0", "1.0.0-rc.1"] {
assert_eq!(check_api(&v(ok), &host), Ok(()), "{ok}"); assert_eq!(check_api(&v(ok), &host), Ok(()), "{ok}");
} }
let newer = check_api(&v("1.7.0"), &host).unwrap_err(); let newer = check_api(&v("1.8.0"), &host).unwrap_err();
assert!(newer.contains("1.7") && newer.contains("update OpenIDEA"), "{newer}"); assert!(newer.contains("1.8") && newer.contains("update OpenIDEA"), "{newer}");
assert!(check_api(&v("2.0.0"), &host).unwrap_err().contains("update OpenIDEA")); assert!(check_api(&v("2.0.0"), &host).unwrap_err().contains("update OpenIDEA"));
let older = check_api(&v("0.2.0"), &host).unwrap_err(); let older = check_api(&v("0.2.0"), &host).unwrap_err();
assert!(older.contains("rebuild it with the 1.6 SDK"), "{older}"); assert!(older.contains("rebuild it with the 1.7 SDK"), "{older}");
// 0.x: every minor is its own API. // 0.x: every minor is its own API.
assert_eq!(check_api(&v("0.2.0"), &v("0.2.5")), Ok(())); assert_eq!(check_api(&v("0.2.0"), &v("0.2.5")), Ok(()));
assert!(check_api(&v("0.1.0"), &v("0.2.0")).is_err()); assert!(check_api(&v("0.1.0"), &v("0.2.0")).is_err());
Binary file not shown.
@@ -1 +1 @@
005d9da29eb7d713a97ff872051e408f653030434d837835843298553c9e12e0 3c7f35facd15ee8380ccb6475b7c051d500e38346b711e1805077becd0c75f75
Binary file not shown.
@@ -1 +1 @@
6359ef4271f38374889412bd926d9aa735f59a8ce047ffcb06c47976444196cf 3879822d975695c6258e95286b0e64c5ee1e3265876501efaf0e577b38f8222b
Binary file not shown.
@@ -1 +1 @@
6f560f3d0d7737150d2dfa09c3b801bd3b4c3a52cef9893ed8fc045809fe33e1 228ae888bf556ce5cedc7843eb20e92f221d9e1f640f3c6c595bed3fd6be6051
Binary file not shown.
@@ -1 +1 @@
4024af2d55d7fe4e8c456efd7e0c497ade4b2c5959e9108ff218f4a669e920f4 41de239b6f723020b38eb2b67f642b7c88cc88c79117c3072ba122633afc418c
Binary file not shown.
@@ -1 +1 @@
4ca977f53a18e9e8f869d34e027a15abece9e97b9331e23d4f71af721b104611 78c5ed3c756498c7619b46c3622ae7a59461c61c747b45caecd79b341ee654de
Binary file not shown.
@@ -1 +1 @@
3d12a00f81e0db1b0902c2ddebfd6454a056f15b97add80b22a0333722568dc8 ee848321e53cb181536e6158570dbb4ab02a6fd2a1a064b068803ac7da7f3448
Binary file not shown.
@@ -1 +1 @@
95d89e411216f50d0b34bee110c6bfc9b8fbcb2ffaae2e912c3609f7bf678b2c b587de945875a98f1d4ca20fab7cf94fb4dc6d848136aa19ab0e0e5319155a80
@@ -40,6 +40,10 @@ title = "write"
id = "content" id = "content"
title = "content" title = "content"
[[contributes.commands]]
id = "diff"
title = "diff"
[[contributes.commands]] [[contributes.commands]]
id = "events" id = "events"
title = "events" title = "events"
+12
View File
@@ -78,6 +78,18 @@ impl Plugin for Execution {
})?; })?;
Ok(None) Ok(None)
} }
"diff" => {
host::open_diff(
&ContentDiff {
left: "before\n".into(),
right: "after\n".into(),
title: Some("Review".into()),
..Default::default()
},
Some("src/review.rs"),
)?;
Ok(None)
}
"events" => host::storage::get("events"), "events" => host::storage::get("events"),
"validation" => host::storage::get("validation"), "validation" => host::storage::get("validation"),
_ => Err(Error::NotFound(id.into())), _ => Err(Error::NotFound(id.into())),
Binary file not shown.
@@ -1 +1 @@
dd4b6c5153892a4f3facb3f23cb1d92da39a3977985b8abf4eaa9558decfa4a9 1c8776dcae35d2d49dd6c1e32b0cdd354de1eb0f72a473245a2c47368b89ec30
Binary file not shown.
@@ -1 +1 @@
325bc15cd28933d9687bc3c316008f921f48a4a69d7528c6b367fa0ff22489b8 2a517cbffd6d3cdda37117d8ca8815978a09995923fc3d5aa5af7020afdac56a
Binary file not shown.
@@ -1 +1 @@
abe706392e04ef5a14f9feab88e0c0d6a9e96bee7de771b61deeb65e7d9e0a7c dbd912b1f8488ecd446af07b5dcaef55d44bce57c1a55be5c0b0fb33e2697903
Binary file not shown.
@@ -1 +1 @@
fb3677946021b30d226e2e3d422c352645c2065c93057c0a645246520860fc90 efdc84cd2bedb3989b03d19b569d09958f26e502db65db4dd786eb3438a7c407
Binary file not shown.
@@ -1 +1 @@
a01852ead9004ac1558028da19a1ae96ccd035775484089fd39f14263082daf1 be6bc15ee42a5e21781ba54f548007351a46b669882ee4491da20ff556927a06
Binary file not shown.
@@ -1 +1 @@
bf00050b7bb9911680a94fd36aaeb83fc96d94030e8ceef51d1723c3950253f9 e5c3a3beda750dff27d7b823676d53f15b7c76b8ad539594cd913bd178d750da
Binary file not shown.
@@ -1 +1 @@
d00a07d9d51e7ca117cec59070d2812d4d1efb2730b60a6f171c8fd12903d055 322de3299f0413101c02358836e7df7e06e58cbb22c11897664564abbb8af090
Binary file not shown.
@@ -1 +1 @@
0aa0ee56e8bacd4d218bafecdec7f4b6249381fad6e31f8b2ee89fd88b16d710 d768ff6a4a466cc6f1d72499df3ccb4ae76872436b8eddff27f62aa156331a37
Binary file not shown.
@@ -1 +1 @@
e06955818969808e6695fba9178727239e343bc4542efbf56262dd407175fd8a 57aea107b2c10e4d30fa3785ac4c6566f1b40908a18a3859aca8be047fac9518
@@ -1 +1 @@
7af67673471d49f97aa2cc131b5deddfc78ee7fc203901eba12f4970a5b13f75 c98bcc89750e26e738d7115a7c0454fde25367a0a23bdc2ff95fb5a5dacc9f98
Binary file not shown.
@@ -1 +1 @@
e81d2454a61977ab69dc8b5c3c617627c559c4e340337a3d43309daeb9b1c12d a4c23b93a14eda705cb18c88bbc2373d1ef3f96031ff2df21b8b092b50633996
+3 -3
View File
@@ -5,9 +5,9 @@ wit_bindgen::generate!({
inline: " inline: "
package fixture:misbehave; package fixture:misbehave;
world misbehave { world misbehave {
include openidea:plugin/plugin-syntax@1.6.0; include openidea:plugin/plugin-syntax@1.7.0;
export openidea:plugin/providers@1.6.0; export openidea:plugin/providers@1.7.0;
export openidea:plugin/file-actions@1.6.0; export openidea:plugin/file-actions@1.7.0;
} }
", ",
path: "../../../../../wit", path: "../../../../../wit",
Binary file not shown.
@@ -1 +1 @@
123ae68df6baa3b5983349ba05fb441ec67fddcb32cab566b0d02e443bb4800e aec002b3dd310068e69a6ae67a49d30655bf8baea9153a110a407e9d408e6880
Binary file not shown.
@@ -1 +1 @@
7b26a4ec36b496f9a4f5e029ef557707961a281e31508863c989a5a5abd5e225 08ece563c3b55c2b86e68fbb0815ddcbb63beb6f1f6c32b8dbdbee558a4a66c1
Binary file not shown.
@@ -1 +1 @@
67f278ade12d11b1445ac3d448853ec46282f2f3e2b2299c6c8fe0dfb4fc86cd 450845edf234a1cc78cd6cfc0b812a89f3a2e41484689cc1e1b05be66873d4eb
Binary file not shown.
@@ -1 +1 @@
8cf9210844a1968f485e6e747f6dff4a1fdf0a628e2945f731d8289dd01f8385 61b735de5ef61dcd0ea8e640c2ad004e84a63fe4dfd7872ffb5e04d6d81dc9a9
Binary file not shown.
@@ -1 +1 @@
263e6ab4b54593f09ae2cf71e9a191acb95ed744cc16bbaf9a9263e41614e99a 36776367782eaa4b8b8121f4a665dd8e68525a4836bff1c92bc16770cce14929
Binary file not shown.
@@ -1 +1 @@
682a712b6c75ad0c0da24476f87c77a76b248c201d4d31923a79fda053b76b90 f6311d232a99356b02a398b2ce3db0865c425f435a8d201157719178ba2b97c7
Binary file not shown.
@@ -1 +1 @@
c5718b3978f21291cfff7a00233ba68d545a5977bc3e90c546b4380528295446 fe1d26665e3c816ed43fc720acabad03a37b7924bccd4dd8c357fd156947b3c7
Binary file not shown.
@@ -1 +1 @@
186b30c785fae23d18c5efe8fa63f6526d23d9d141580deef7ee7009310a88c3 76bab8e48235f9f066f5b9bbfdd9398916b6c3ed73c072c543d80595130519f7
Binary file not shown.
@@ -1 +1 @@
cb3a1c4a0518aa3f3e689337e8f4249180e5b3753b0e7bfaba8c974f89f6ef7a f9ed2eac306229f76b05d0c4a4fb2f0ed8d81a1dfc5eb50d044bbe10c9206a5f
Binary file not shown.
@@ -1 +1 @@
fa97682ca30cb0ad1392ff1bab4d99ea6d9ccb2654feedfdc130d11adb7df93b f2d83d9f56da072d38a1552195af8a9d4edc11888c645627d5dd1e4a46afc4df
@@ -19,7 +19,7 @@ The plugin host runs **where the project is**: in the desktop app for local proj
## The interface ## The interface
The API is defined in WIT, in `wit/` (package `openidea:plugin@1.6.0`). A plugin is a component targeting the `plugin` world (or `plugin-syntax`). The guest SDK `sdk/rust/openidea-plugin` wraps it in a typed Rust API and carries a copy of `wit/`; `crates/ide-plugin/tests/api_compat.rs` checks the copies are identical. The API is defined in WIT, in `wit/` (package `openidea:plugin@1.7.0`). A plugin is a component targeting the `plugin` world (or `plugin-syntax`). The guest SDK `sdk/rust/openidea-plugin` wraps it in a typed Rust API and carries a copy of `wit/`; `crates/ide-plugin/tests/api_compat.rs` checks the copies are identical.
Released API versions are frozen. wasmtime resolves interface names by semver, but function types must match exactly, so a released 1.x only grows: new interfaces and new optional exports, never changed records or variants. See _Evolving the plugin API_ in `plugins/README.md` before touching `wit/`. Released API versions are frozen. wasmtime resolves interface names by semver, but function types must match exactly, so a released 1.x only grows: new interfaces and new optional exports, never changed records or variants. See _Evolving the plugin API_ in `plugins/README.md` before touching `wit/`.
+1 -1
View File
@@ -3,7 +3,7 @@ title: "API reference"
description: "Every interface of the openidea:plugin WIT package, with a one-line summary and a link to its source." description: "Every interface of the openidea:plugin WIT package, with a one-line summary and a link to its source."
--- ---
The plugin API is the WIT package `openidea:plugin@1.6.0` in [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit). The WIT files are the reference: each interface, type and function is documented in comments there. 1.6.0 is the version on `main`; the latest released version is 1.4.0, whose WIT is kept in [`sdk/rust/openidea-plugin/tests/api/released/`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin/tests/api/released). The plugin API is the WIT package `openidea:plugin@1.7.0` in [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit). The WIT files are the reference: each interface, type and function is documented in comments there. 1.7.0 is the version on `main`; the latest released version is 1.6.0, whose WIT is kept in [`sdk/rust/openidea-plugin/tests/api/released/`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin/tests/api/released).
<Info> <Info>
A generated API reference is planned. Until then, use the WIT files below, `cargo doc` for the Rust SDK A generated API reference is planned. Until then, use the WIT files below, `cargo doc` for the Rust SDK
+1 -1
View File
@@ -9,7 +9,7 @@ A code plugin is a WebAssembly **component** (component model, WASI preview 2) t
| Part | Where | Role | | Part | Where | Role |
| ---------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- | | ---------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------- |
| Plugin API | [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) | The contract: the WIT package `openidea:plugin@1.6.0`, its interfaces and worlds | | Plugin API | [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) | The contract: the WIT package `openidea:plugin@1.7.0`, its interfaces and worlds |
| Rust SDK | [`sdk/rust/openidea-plugin`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin) | Typed wrappers over the WIT, the `Plugin` trait, `register_plugin!`, and a mock host for `cargo test` | | Rust SDK | [`sdk/rust/openidea-plugin`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin) | Typed wrappers over the WIT, the `Plugin` trait, `register_plugin!`, and a mock host for `cargo test` |
| Packages | [`crates/ide-extension`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-extension) | The manifest, capabilities and their risk, the grant ledger, contribution points, `.oiplugin` packages and the marketplace index | | Packages | [`crates/ide-extension`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-extension) | The manifest, capabilities and their risk, the grant ledger, contribution points, `.oiplugin` packages and the marketplace index |
| Runtime | [`crates/ide-plugin`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-plugin) | The wasmtime engine, one `Store` per plugin, limits, and one actor thread per active plugin | | Runtime | [`crates/ide-plugin`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-plugin) | The wasmtime engine, one `Store` per plugin, limits, and one actor thread per active plugin |
+11 -9
View File
@@ -281,6 +281,7 @@ With `engines.openidea = "^1.3"`, a page can send JSON messages through
| `pty-spawn`, `pty-input`, `pty-resize`, `pty-kill`, `pty-ack` | An interactive PTY owned by the frame; output arrives as `pty-data`, `pty-exit`, `pty-error`. At most 8 sessions per plugin. | | `pty-spawn`, `pty-input`, `pty-resize`, `pty-kill`, `pty-ack` | An interactive PTY owned by the frame; output arrives as `pty-data`, `pty-exit`, `pty-error`. At most 8 sessions per plugin. |
| `open-log-tab` | A read-only editor tab following a program's output, with argument toggles. | | `open-log-tab` | A read-only editor tab following a program's output, with argument toggles. |
| `open-content-tab` | An editor tab on content the plugin supplies, with toolbar actions answered by `content-tab-reply`. | | `open-content-tab` | An editor tab on content the plugin supplies, with toolbar actions answered by `content-tab-reply`. |
| `open-diff` | API 1.7: the diff viewer on two texts (`left`, `right`, optional labels, `title` and `fileName` for highlighting). |
The message fields and limits are in the The message fields and limits are in the
[plugin guide](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md#web-frame-ptys-api-13); [plugin guide](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md#web-frame-ptys-api-13);
@@ -338,15 +339,16 @@ divider. The host asks after the item's `select` event and again after `refresh_
These are called from a command or event of a window: These are called from a command or event of a window:
| Function | Opens | | Function | Opens |
| ----------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `host::open_location(path, line, column)` | A project file in an editor, caret at the position (`project.read`; a file in the plugin's private directory also works). | | `host::open_location(path, line, column)` | A project file in an editor, caret at the position (`project.read`; a file in the plugin's private directory also works). |
| `host::open_editor(path, selection)` | API 1.4: open a project file and select a range. | | `host::open_editor(path, selection)` | API 1.4: open a project file and select a range. |
| `host::open_terminal(title, program, args)` | A Terminal tab running an approved `process:<program>` in the project root. | | `host::open_terminal(title, program, args)` | A Terminal tab running an approved `process:<program>` in the project root. |
| `host::open_terminal_session(key, title, &cmd)` | API 1.4: a keyed terminal; reopening the key focuses it. Write to it with `host::write_terminal(key, text)`; its exit arrives as a `terminal-exited` event. | | `host::open_terminal_session(key, title, &cmd)` | API 1.4: a keyed terminal; reopening the key focuses it. Write to it with `host::write_terminal(key, text)`; its exit arrives as a `terminal-exited` event. |
| `host::open_log_tab(key, title, &log)` | API 1.3: the read-only log tab, from a `ProcessLog`. At most 32 per window; not yet in remote projects. | | `host::open_log_tab(key, title, &log)` | API 1.3: the read-only log tab, from a `ProcessLog`. At most 32 per window; not yet in remote projects. |
| `host::open_content_tab(&ContentTab { .. })` | API 1.4: a content editor tab without a web view; actions arrive as `content-tab-action` events, answered with `host::reply_content_tab`. | | `host::open_content_tab(&ContentTab { .. })` | API 1.4: a content editor tab without a web view; actions arrive as `content-tab-action` events, answered with `host::reply_content_tab`. |
| `host::output_append(channel, text)` | API 1.4: a read-only **Output** tab per channel (32 channels, 1 MiB each); `output_clear`, `output_reveal`. | | `host::open_diff(&ContentDiff { .. }, file_name)` | API 1.7: the diff viewer on two texts, such as a review's file before and after; `file_name` picks the syntax highlighting. |
| `host::output_append(channel, text)` | API 1.4: a read-only **Output** tab per channel (32 channels, 1 MiB each); `output_clear`, `output_reveal`. |
```rust ```rust
use openidea_plugin::{ContentAction, ContentTab, host}; use openidea_plugin::{ContentAction, ContentTab, host};
+2 -2
View File
@@ -36,8 +36,8 @@ Code plugins are WebAssembly components targeting the `plugin` world in [`wit/`]
| | | | | |
| ------------------------- | ------------------------------------------------------------ | | ------------------------- | ------------------------------------------------------------ |
| Latest released API | **1.4.0**, shipped with OpenIDEA 0.1.40 | | Latest released API | **1.6.0**, shipped with OpenIDEA 0.1.43 |
| In development | **1.6.0** on the `main` branch, planned for the next release | | In development | **1.7.0** on the `main` branch, planned for the next release |
| Format of the WIT package | `openidea:plugin@<version>` | | Format of the WIT package | `openidea:plugin@<version>` |
Declare the API your plugin needs with `engines.openidea` in the manifest, for example `engines.openidea = "^1.4"`. Declare the API your plugin needs with `engines.openidea` in the manifest, for example `engines.openidea = "^1.4"`.
+11 -10
View File
@@ -3,7 +3,7 @@ title: "API versions and compatibility"
description: "engines.openidea, the plugin API versions from 1.0 to 1.6, and the rules that keep released plugins loading in newer IDEs." description: "engines.openidea, the plugin API versions from 1.0 to 1.6, and the rules that keep released plugins loading in newer IDEs."
--- ---
The plugin API has one version number: the version of the WIT package in [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) (`openidea:plugin@1.6.0` on `main`). The host's engine version and the SDK's `API_VERSION` always agree with it, and the SDK carries an identical copy of the WIT files. The plugin API has one version number: the version of the WIT package in [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) (`openidea:plugin@1.7.0` on `main`). The host's engine version and the SDK's `API_VERSION` always agree with it, and the SDK carries an identical copy of the WIT files.
<Note> <Note>
The plugin system is a preview. The compatibility rules below hold for released 1.x versions; what is still unreleased The plugin system is a preview. The compatibility rules below hold for released 1.x versions; what is still unreleased
@@ -12,15 +12,16 @@ The plugin API has one version number: the version of the WIT package in [`wit/`
## Versions ## Versions
| API | Shipped with | Highlights | | API | Shipped with | Highlights |
| ----- | ---------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----- | ------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.0.0 | OpenIDEA 0.1.36 | The base API: commands, events, storage, tasks, project and editor access, VCS, diagnostics, network and secrets, processes, declarative views and custom editors, settings, editor providers, syntax provider | | 1.0.0 | OpenIDEA 0.1.36 | The base API: commands, events, storage, tasks, project and editor access, VCS, diagnostics, network and secrets, processes, declarative views and custom editors, settings, editor providers, syntax provider |
| 1.1.0 | OpenIDEA 0.1.37 | `vcs.remotes`, `ui.copy-to-clipboard`, `ui.open-url`, opening a project file at a line from a view | | 1.1.0 | OpenIDEA 0.1.37 | `vcs.remotes`, `ui.copy-to-clipboard`, `ui.open-url`, opening a project file at a line from a view |
| 1.2.0 | OpenIDEA 0.1.38 | Background document indexers, pickers, input boxes and confirmations, plugin context keys for `when` clauses, the files selected in the Project view, a manifest `icon`, the `viewItem.context` menu | | 1.2.0 | OpenIDEA 0.1.38 | Background document indexers, pickers, input boxes and confirmations, plugin context keys for `when` clauses, the files selected in the Project view, a manifest `icon`, the `viewItem.context` menu |
| 1.3.0 | OpenIDEA 0.1.39 | Commit message and before-commit checks, Services detail panes, diagnostics while typing, hover, inlay hints, semantic tokens, file-changing code actions, HTTP endpoints, files outside the project (`fs.read`/`fs.write`, `project.write`, private plugin directory), batched `files-changed` events and path filters, workspace symbols, long-running processes, notifications with buttons, translations, multi-page settings, file template variables, web view PTYs, log tabs and content tabs | | 1.3.0 | OpenIDEA 0.1.39 | Commit message and before-commit checks, Services detail panes, diagnostics while typing, hover, inlay hints, semantic tokens, file-changing code actions, HTTP endpoints, files outside the project (`fs.read`/`fs.write`, `project.write`, private plugin directory), batched `files-changed` events and path filters, workspace symbols, long-running processes, notifications with buttons, translations, multi-page settings, file template variables, web view PTYs, log tabs and content tabs |
| 1.4.0 | OpenIDEA 0.1.40 | `net.http:`, `ipc:`, `ide.commands` and `database.sources` capabilities; editor and project snapshots, decorations, text search, Problems, Git log/blame/diff; output channels; OAuth loopback; runs, terminal sessions, run configurations, test result parsing and run targets; formatting and other language features; embedded languages; snippets; more menu locations; database sources; MCP tools | | 1.4.0 | OpenIDEA 0.1.40 | `net.http:`, `ipc:`, `ide.commands` and `database.sources` capabilities; editor and project snapshots, decorations, text search, Problems, Git log/blame/diff; output channels; OAuth loopback; runs, terminal sessions, run configurations, test result parsing and run targets; formatting and other language features; embedded languages; snippets; more menu locations; database sources; MCP tools |
| 1.5.0 | Planned for the next release | `Project::notify` (a notification in one project's window), the `net:ask` capability, run target validation, per-command run target working-directory arguments | | 1.5.0 | OpenIDEA 0.1.41 | `Project::notify` (a notification in one project's window), the `net:ask` capability, run target validation, per-command run target working-directory arguments |
| 1.6.0 | In development on `main` | Bounded, project-bound background WebSockets for event-stream plugins | | 1.6.0 | OpenIDEA 0.1.43 | Bounded, project-bound background WebSockets for event-stream plugins |
| 1.7.0 | In development on `main` | `views.open-diff`: two texts in the diff viewer, such as a review's file before and after |
The full list of what each version added is in [`plugins/README.md`](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md). The full list of what each version added is in [`plugins/README.md`](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md).
@@ -19,7 +19,7 @@ description: "插件系统的内部实现:扩展内核、每个插件一个 ac
## 接口 ## 接口
API 用 WIT 定义,位于 `wit/`(包名 `openidea:plugin@1.6.0`)。插件是面向 `plugin` world(或 `plugin-syntax`)的组件。插件端 SDK `sdk/rust/openidea-plugin` 把它封装成类型化的 Rust API,并带有一份 `wit/` 副本;`crates/ide-plugin/tests/api_compat.rs` 检查两份是否一致。 API 用 WIT 定义,位于 `wit/`(包名 `openidea:plugin@1.7.0`)。插件是面向 `plugin` world(或 `plugin-syntax`)的组件。插件端 SDK `sdk/rust/openidea-plugin` 把它封装成类型化的 Rust API,并带有一份 `wit/` 副本;`crates/ide-plugin/tests/api_compat.rs` 检查两份是否一致。
已发布的 API 版本是冻结的。wasmtime 按 semver 解析接口名,但函数类型必须完全一致,所以已发布的 1.x 只能增加:新的接口和新的可选导出,不能修改已有的 record 或 variant。改 `wit/` 之前请先读 `plugins/README.md` 里的 _Evolving the plugin API_。 已发布的 API 版本是冻结的。wasmtime 按 semver 解析接口名,但函数类型必须完全一致,所以已发布的 1.x 只能增加:新的接口和新的可选导出,不能修改已有的 record 或 variant。改 `wit/` 之前请先读 `plugins/README.md` 里的 _Evolving the plugin API_。
+1 -1
View File
@@ -3,7 +3,7 @@ title: "API 参考"
description: "openidea:plugin WIT 包中的每个 interface:一句话说明及源码链接。" description: "openidea:plugin WIT 包中的每个 interface:一句话说明及源码链接。"
--- ---
插件 API 是 [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) 中的 WIT 包 `openidea:plugin@1.6.0`。WIT 文件就是参考文档:每个 interface、类型和函数都在注释中有说明。1.6.0 是 `main` 上的版本;最新已发布版本是 1.4.0,其 WIT 保存在 [`sdk/rust/openidea-plugin/tests/api/released/`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin/tests/api/released)。 插件 API 是 [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) 中的 WIT 包 `openidea:plugin@1.7.0`。WIT 文件就是参考文档:每个 interface、类型和函数都在注释中有说明。1.7.0 是 `main` 上的版本;最新已发布版本是 1.6.0,其 WIT 保存在 [`sdk/rust/openidea-plugin/tests/api/released/`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin/tests/api/released)。
<Info> <Info>
自动生成的 API 参考正在计划中。在此之前,请参考下面的 WIT 文件、Rust SDK 的 `cargo 自动生成的 API 参考正在计划中。在此之前,请参考下面的 WIT 文件、Rust SDK 的 `cargo
+1 -1
View File
@@ -9,7 +9,7 @@ description: "插件代码如何运行:WebAssembly 组件、WIT world、宿主
| 部分 | 位置 | 作用 | | 部分 | 位置 | 作用 |
| -------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- | | -------- | ---------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------- |
| 插件 API | [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) | 契约:WIT 包 `openidea:plugin@1.6.0`、其中的 interface 和 world | | 插件 API | [`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) | 契约:WIT 包 `openidea:plugin@1.7.0`、其中的 interface 和 world |
| Rust SDK | [`sdk/rust/openidea-plugin`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin) | WIT 的类型化封装、`Plugin` trait、`register_plugin!`,以及给 `cargo test` 用的模拟宿主 | | Rust SDK | [`sdk/rust/openidea-plugin`](https://github.com/l0ng-ai/openidea/tree/main/sdk/rust/openidea-plugin) | WIT 的类型化封装、`Plugin` trait、`register_plugin!`,以及给 `cargo test` 用的模拟宿主 |
| 插件包 | [`crates/ide-extension`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-extension) | 清单、能力及其风险等级、授权记录、贡献点、`.oiplugin` 包和插件市场索引 | | 插件包 | [`crates/ide-extension`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-extension) | 清单、能力及其风险等级、授权记录、贡献点、`.oiplugin` 包和插件市场索引 |
| 运行时 | [`crates/ide-plugin`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-plugin) | wasmtime 引擎、每个插件一个 `Store`、各项限制、每个活跃插件一个 actor 线程 | | 运行时 | [`crates/ide-plugin`](https://github.com/l0ng-ai/openidea/tree/main/crates/ide-plugin) | wasmtime 引擎、每个插件一个 `Store`、各项限制、每个活跃插件一个 actor 线程 |
+16 -14
View File
@@ -248,11 +248,12 @@ Vite + React 页面由 `plugins/build.sh official/graphviz` 构建到 `web/`,
声明 `engines.openidea = "^1.3"` 后,页面可以通过 `openidea.postMessage` 发送 JSON 消息,请 IDE 打开更多东西。 声明 `engines.openidea = "^1.3"` 后,页面可以通过 `openidea.postMessage` 发送 JSON 消息,请 IDE 打开更多东西。
这些协议只运行通过 `process:<program>` 授权的程序,工作目录是窗口所在的受信任项目根目录,从不经过 shell: 这些协议只运行通过 `process:<program>` 授权的程序,工作目录是窗口所在的受信任项目根目录,从不经过 shell:
| `op` | 打开什么 | | `op` | 打开什么 |
| ------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------- | | ------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `pty-spawn`、`pty-input`、`pty-resize`、`pty-kill`、`pty-ack` | 归该 frame 所有的交互式 PTY;输出以 `pty-data`、`pty-exit`、`pty-error` 返回。每个插件最多 8 个会话。 | | `pty-spawn`、`pty-input`、`pty-resize`、`pty-kill`、`pty-ack` | 归该 frame 所有的交互式 PTY;输出以 `pty-data`、`pty-exit`、`pty-error` 返回。每个插件最多 8 个会话。 |
| `open-log-tab` | 只读编辑器标签页,持续显示程序输出,可带参数开关。 | | `open-log-tab` | 只读编辑器标签页,持续显示程序输出,可带参数开关。 |
| `open-content-tab` | 内容由插件提供的编辑器标签页,带工具栏操作,用 `content-tab-reply` 回复。 | | `open-content-tab` | 内容由插件提供的编辑器标签页,带工具栏操作,用 `content-tab-reply` 回复。 |
| `open-diff` | API 1.7:在差异查看器中对比两段文本(`left`、`right`,可选标签、`title`,以及用于高亮的 `fileName`)。 |
消息字段和限制见 [插件指南](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md#web-frame-ptys-api-13); 消息字段和限制见 [插件指南](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md#web-frame-ptys-api-13);
`crates/ide-plugin/tests/fixtures/` 下已构建的 `web-pty`、`web-log`、`web-content` 测试插件演示了这些协议。 `crates/ide-plugin/tests/fixtures/` 下已构建的 `web-pty`、`web-log`、`web-content` 测试插件演示了这些协议。
@@ -303,15 +304,16 @@ impl Details for MyPlugin {
以下函数需在窗口的命令或事件中调用: 以下函数需在窗口的命令或事件中调用:
| 函数 | 打开什么 | | 函数 | 打开什么 |
| ----------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- | | ------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
| `host::open_location(path, line, column)` | 在编辑器中打开项目文件并定位光标(`project.read`;插件私有目录中的文件也可以)。 | | `host::open_location(path, line, column)` | 在编辑器中打开项目文件并定位光标(`project.read`;插件私有目录中的文件也可以)。 |
| `host::open_editor(path, selection)` | API 1.4:打开项目文件并选中一个范围。 | | `host::open_editor(path, selection)` | API 1.4:打开项目文件并选中一个范围。 |
| `host::open_terminal(title, program, args)` | 在项目根目录运行已批准 `process:<program>` 的终端标签页。 | | `host::open_terminal(title, program, args)` | 在项目根目录运行已批准 `process:<program>` 的终端标签页。 |
| `host::open_terminal_session(key, title, &cmd)` | API 1.4:带 key 的终端;再次使用同一 key 会聚焦它。用 `host::write_terminal(key, text)` 写入;退出时收到 `terminal-exited` 事件。 | | `host::open_terminal_session(key, title, &cmd)` | API 1.4:带 key 的终端;再次使用同一 key 会聚焦它。用 `host::write_terminal(key, text)` 写入;退出时收到 `terminal-exited` 事件。 |
| `host::open_log_tab(key, title, &log)` | API 1.3:基于 `ProcessLog` 的只读日志标签页。每个窗口最多 32 个;暂不支持远程项目。 | | `host::open_log_tab(key, title, &log)` | API 1.3:基于 `ProcessLog` 的只读日志标签页。每个窗口最多 32 个;暂不支持远程项目。 |
| `host::open_content_tab(&ContentTab { .. })` | API 1.4:不依赖网页视图的内容编辑器标签页;操作以 `content-tab-action` 事件送达,用 `host::reply_content_tab` 回复。 | | `host::open_content_tab(&ContentTab { .. })` | API 1.4:不依赖网页视图的内容编辑器标签页;操作以 `content-tab-action` 事件送达,用 `host::reply_content_tab` 回复。 |
| `host::output_append(channel, text)` | API 1.4:每个通道一个只读 **输出** 标签页(32 个通道,各 1 MiB);另有 `output_clear`、`output_reveal`。 | | `host::open_diff(&ContentDiff { .. }, file_name)` | API 1.7:在差异查看器中对比两段文本,例如评审中某个文件的修改前后;`file_name` 决定语法高亮。 |
| `host::output_append(channel, text)` | API 1.4:每个通道一个只读 **输出** 标签页(32 个通道,各 1 MiB);另有 `output_clear`、`output_reveal`。 |
```rust ```rust
use openidea_plugin::{ContentAction, ContentTab, host}; use openidea_plugin::{ContentAction, ContentTab, host};
+2 -2
View File
@@ -36,8 +36,8 @@ OpenIDEA 插件可以为 IDE 增加命令、编辑器功能、工具窗口、主
| | | | | |
| -------------- | ----------------------------------------------- | | -------------- | ----------------------------------------------- |
| 最新已发布 API | **1.4.0**,随 OpenIDEA 0.1.40 发布 | | 最新已发布 API | **1.6.0**,随 OpenIDEA 0.1.43 发布 |
| 开发中 | `main` 分支上的 **1.6.0**,计划随下一个版本发布 | | 开发中 | `main` 分支上的 **1.7.0**,计划随下一个版本发布 |
| WIT 包名 | `openidea:plugin@<version>` | | WIT 包名 | `openidea:plugin@<version>` |
在清单里用 `engines.openidea` 声明插件需要的 API,例如 `engines.openidea = "^1.4"`。 在清单里用 `engines.openidea` 声明插件需要的 API,例如 `engines.openidea = "^1.4"`。
+11 -10
View File
@@ -3,21 +3,22 @@ title: "API 版本与兼容"
description: "engines.openidea、插件 API 从 1.0 到 1.6 的各个版本,以及让已发布插件在新 IDE 中继续加载的规则。" description: "engines.openidea、插件 API 从 1.0 到 1.6 的各个版本,以及让已发布插件在新 IDE 中继续加载的规则。"
--- ---
插件 API 只有一个版本号:[`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) 中 WIT 包的版本(`main` 上是 `openidea:plugin@1.6.0`)。宿主的引擎版本和 SDK 的 `API_VERSION` 始终与它一致,SDK 里也带着一份完全相同的 WIT 文件。 插件 API 只有一个版本号:[`wit/`](https://github.com/l0ng-ai/openidea/tree/main/wit) 中 WIT 包的版本(`main` 上是 `openidea:plugin@1.7.0`)。宿主的引擎版本和 SDK 的 `API_VERSION` 始终与它一致,SDK 里也带着一份完全相同的 WIT 文件。
<Note>插件系统目前是预览版。下面的兼容规则适用于已发布的 1.x 版本;`main` 上尚未发布的内容在发布前仍可能变化。</Note> <Note>插件系统目前是预览版。下面的兼容规则适用于已发布的 1.x 版本;`main` 上尚未发布的内容在发布前仍可能变化。</Note>
## 版本历史 ## 版本历史
| API | 随哪个版本发布 | 主要内容 | | API | 随哪个版本发布 | 主要内容 |
| ----- | -------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ----- | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| 1.0.0 | OpenIDEA 0.1.36 | 基础 API:命令、事件、存储、任务、项目和编辑器访问、VCS、诊断、网络与密钥、进程、声明式视图和自定义编辑器、设置、编辑器 provider、syntax provider | | 1.0.0 | OpenIDEA 0.1.36 | 基础 API:命令、事件、存储、任务、项目和编辑器访问、VCS、诊断、网络与密钥、进程、声明式视图和自定义编辑器、设置、编辑器 provider、syntax provider |
| 1.1.0 | OpenIDEA 0.1.37 | `vcs.remotes`、`ui.copy-to-clipboard`、`ui.open-url`,从视图中打开项目文件的指定行 | | 1.1.0 | OpenIDEA 0.1.37 | `vcs.remotes`、`ui.copy-to-clipboard`、`ui.open-url`,从视图中打开项目文件的指定行 |
| 1.2.0 | OpenIDEA 0.1.38 | 后台文档索引器;选择器、输入框和确认框;插件自定义的 `when` 上下文键;项目视图中选中的文件;清单 `icon`;`viewItem.context` 菜单 | | 1.2.0 | OpenIDEA 0.1.38 | 后台文档索引器;选择器、输入框和确认框;插件自定义的 `when` 上下文键;项目视图中选中的文件;清单 `icon`;`viewItem.context` 菜单 |
| 1.3.0 | OpenIDEA 0.1.39 | 提交信息和提交前检查、Services 详情面板、输入时诊断、悬停、内嵌提示、语义 token、改动文件的代码操作、HTTP 端点、项目外文件(`fs.read`/`fs.write`、`project.write`、插件私有目录)、批量 `files-changed` 事件和路径过滤、工作区符号、长时间运行的进程、带按钮的通知、翻译、多页设置、文件模板变量、Web 视图 PTY、日志标签页和内容标签页 | | 1.3.0 | OpenIDEA 0.1.39 | 提交信息和提交前检查、Services 详情面板、输入时诊断、悬停、内嵌提示、语义 token、改动文件的代码操作、HTTP 端点、项目外文件(`fs.read`/`fs.write`、`project.write`、插件私有目录)、批量 `files-changed` 事件和路径过滤、工作区符号、长时间运行的进程、带按钮的通知、翻译、多页设置、文件模板变量、Web 视图 PTY、日志标签页和内容标签页 |
| 1.4.0 | OpenIDEA 0.1.40 | `net.http:`、`ipc:`、`ide.commands` 和 `database.sources` 能力;编辑器与项目快照、装饰、文本搜索、问题视图、Git log/blame/diff;输出通道;OAuth 回环;运行、终端会话、运行配置、测试结果解析和运行目标;格式化等语言功能;嵌入语言;代码片段;更多菜单位置;数据库数据源;MCP 工具 | | 1.4.0 | OpenIDEA 0.1.40 | `net.http:`、`ipc:`、`ide.commands` 和 `database.sources` 能力;编辑器与项目快照、装饰、文本搜索、问题视图、Git log/blame/diff;输出通道;OAuth 回环;运行、终端会话、运行配置、测试结果解析和运行目标;格式化等语言功能;嵌入语言;代码片段;更多菜单位置;数据库数据源;MCP 工具 |
| 1.5.0 | 计划随下一个版本发布 | `Project::notify`(只在某个项目的窗口中显示通知)、`net:ask` 能力、运行目标启动前校验、运行目标按命令设置工作目录参数 | | 1.5.0 | OpenIDEA 0.1.41 | `Project::notify`(只在某个项目的窗口中显示通知)、`net:ask` 能力、运行目标启动前校验、运行目标按命令设置工作目录参数 |
| 1.6.0 | `main` 上开发中 | 面向事件流插件、受容量限制且绑定项目的后台 WebSocket | | 1.6.0 | OpenIDEA 0.1.43 | 面向事件流插件、受容量限制且绑定项目的后台 WebSocket |
| 1.7.0 | `main` 上开发中 | `views.open-diff`:在差异查看器中对比两段文本,例如评审中某个文件的修改前后 |
每个版本新增内容的完整列表见 [`plugins/README.md`](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md)。 每个版本新增内容的完整列表见 [`plugins/README.md`](https://github.com/l0ng-ai/openidea/blob/main/plugins/README.md)。
+15 -3
View File
@@ -36,7 +36,7 @@ sdk/rust/openidea-plugin/ # the Rust SDK (host API, Plugin trait, mock host)
crates/ide-plugin/tests/fixtures/ # test plugins: hello, jobs, language-toy, misbehave, semantic-tokens, hover, commit, inlay-hints crates/ide-plugin/tests/fixtures/ # test plugins: hello, jobs, language-toy, misbehave, semantic-tokens, hover, commit, inlay-hints
``` ```
The plugin API is defined in [`wit/`](../wit/) (`openidea:plugin@1.6.0`, world The plugin API is defined in [`wit/`](../wit/) (`openidea:plugin@1.7.0`, world
`plugin`). `plugin`).
## 1. Quick start ## 1. Quick start
@@ -418,9 +418,20 @@ are always available. Calling a gated function without its capability returns
## 3. Writing code (Rust SDK) ## 3. Writing code (Rust SDK)
### API 1.7
API 1.7.0 is in development on `main`. Use `engines.openidea = "^1.7"` and the
matching SDK. Released 1.6 plugins keep working. New in 1.7:
- `host::open_diff(&ContentDiff { .. }, file_name)` (`views.open-diff`) opens
two texts in the invoking window's diff viewer, for example a merge request's
file before and after; `file_name` picks the syntax highlighting. Web views
send `{ op: "open-diff", left, right, leftLabel?, rightLabel?, title?, fileName? }`.
Commands and events only; each side at most 1 MiB.
### API 1.5 ### API 1.5
API 1.5.0 is planned for the next OpenIDEA release. Use API 1.5.0 shipped with OpenIDEA 0.1.41. Use
`engines.openidea = "^1.5"` and the matching SDK. Released 1.4 plugins keep `engines.openidea = "^1.5"` and the matching SDK. Released 1.4 plugins keep
working. New in 1.5: working. New in 1.5:
@@ -638,6 +649,7 @@ then run `openidea-plugin check`.
| `host::write_terminal(key, text)` | `views.write-terminal` | API 1.4: write only to this plugin's still-running terminal in this window; trusted project, commands/events only. | | `host::write_terminal(key, text)` | `views.write-terminal` | API 1.4: write only to this plugin's still-running terminal in this window; trusted project, commands/events only. |
| `host::open_content_tab(tab)` | `views.open-content-tab` | API 1.4: the shared content editor protocol, without a web view; actions arrive as `content-tab-action`. | | `host::open_content_tab(tab)` | `views.open-content-tab` | API 1.4: the shared content editor protocol, without a web view; actions arrive as `content-tab-action`. |
| `host::reply_content_tab(request_id, reply)` | `views.reply-content-tab` | API 1.4: reply to an owned action in the originating window. No capability; commands/events only. | | `host::reply_content_tab(request_id, reply)` | `views.reply-content-tab` | API 1.4: reply to an owned action in the originating window. No capability; commands/events only. |
| `host::open_diff(diff, file_name)` | `views.open-diff` | API 1.7: two texts in the invoking window's diff viewer; `file_name` (at most 256 characters) picks the highlighting. Commands/events only; each side at most 1 MiB. |
| `RunConfigurations::configurations(root)` | export `run-configurations.configurations` | API 1.4: optional `plugin-run-configurations` world; SDK registration `run_configurations`. Full project list, refreshed on configuration listing. | | `RunConfigurations::configurations(root)` | export `run-configurations.configurations` | API 1.4: optional `plugin-run-configurations` world; SDK registration `run_configurations`. Full project list, refreshed on configuration listing. |
| `TestResults::parse(config, chunk)` | export `test-results.parse` | API 1.4: optional `plugin-test-results` world; SDK registration `test_results`. Bounded output batches for `framework = "plugin"`; failures use built-in parsers. | | `TestResults::parse(config, chunk)` | export `test-results.parse` | API 1.4: optional `plugin-test-results` world; SDK registration `test_results`. Bounded output batches for `framework = "plugin"`; failures use built-in parsers. |
| `TestResults::select_tests(config, tests)` | export `test-results.select-tests` | API 1.4: full replacement argv for test-tree name paths, or `None` when unsupported (the SDK default). Enables rerunning failed tests and running tree selections. | | `TestResults::select_tests(config, tests)` | export `test-results.select-tests` | API 1.4: full replacement argv for test-tree name paths, or `None` when unsupported (the SDK default). Enables rerunning failed tests and running tree selections. |
@@ -2417,7 +2429,7 @@ the API itself follows _Evolving the plugin API_ below.
Released versions are frozen: 1.0.0 shipped with OpenIDEA 0.1.36, 1.1.0 Released versions are frozen: 1.0.0 shipped with OpenIDEA 0.1.36, 1.1.0
with 0.1.37, 1.2.0 with 0.1.38, 1.3.0 with 0.1.39 and 1.4.0 with 0.1.40. with 0.1.37, 1.2.0 with 0.1.38, 1.3.0 with 0.1.39 and 1.4.0 with 0.1.40.
API 1.5.0 is planned with the next release; API 1.6.0 is in development on `main`. wasmtime decides what stays compatible: it resolves interface names API 1.5.0 shipped with 0.1.41 and 1.6.0 with 0.1.43; API 1.7.0 is in development on `main`. wasmtime decides what stays compatible: it resolves interface names
by semver (a component importing `openidea:plugin/[email protected]` links against a by semver (a component importing `openidea:plugin/[email protected]` links against a
host defining `@1.1.0`, and the host finds its exports the same way), but host defining `@1.1.0`, and the host finds its exports the same way), but
function types must match exactly — a record with another field count, or a function types must match exactly — a record with another field count, or a
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
4d1d89c8b3c734f19b97c132a8aad1e042c7e894d695b7f751f2cfbe785c03f0 e8e6dbe6dba09de2fd71a9d84eed8c01b16253f9247bf882361c6f49b8a4d51d
Binary file not shown.
@@ -1 +1 @@
a7e3cf1fce43f673132f8b5a26d8ab549e85d0f3e40c901b2a93eec5280c2a27 784a4e01725063fc2949a88bd209e7fcc8ecb0f721acd5f03d92db39ece091a9
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
dafabda672d2f0921daf246ace54fff7752ad233003c012f95aaca91a413384a 73670a049d8c108511af35b5030d08f1e04a9198cba0da54268e75a06747d953
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
ed15d10fd0c5b68fd31aa95b67ffe7fc752c7897ff7361581dac54f3edeea65a a17332b7d5becc4ddccffdba1f9b009e07f75f171bc2519b6c1038fdda2bfd71
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
3317a89d28772830f177e55eff8b2bfe0039f86417af8a82ed3f09965ae53b84 3db5b81c6562e2532c9408d749cf65164247c0ef6d51e4195a44ebdc9a697924
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
e34f77ace31e645473c977184242800d0862f0caf20405a17680df2c8c7e0671 2c31b614b8c942fdfc075aa58da2000c85598f0c5031d565ffafeb60c75eeac5
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
0bc52221ab5f8ab79b5bb7997a8129959717ffe34cc35a1ecc996a615f946308 08ab43e65c6904d48a969cb0c4247ece1257b51600962fbc64e67d9a1a78e96a
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
9ec2820fd0f048b69781684a037513cb61562efdebce53e1e6997fa35846e582 c7aa8a41a0b142fac374470597316500e2f1b0dfb2c2e58c8e4bcbe05dd87c1f
Binary file not shown.
+1 -1
View File
@@ -1 +1 @@
0a1b73b75e646cc0a006157630e313c2f67fe62142523867d08480124db47212 e8469311f7ccf2ed4ced5bfea4987cd3ff13aede56ee4b18652d3ab466316392
Binary file not shown.
Loaded 100 of 174 files, more files were not shown because too many files have changed in this diff. Show more