mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-06 00:07:50 +00:00
test(plugins): freeze plugin API 1.0.0
v0.1.36 shipped API 1.0.0, so its WIT is now the snapshot api_frozen checks every later version against. World items are compared without their @version, since a later minor renames them and wasmtime resolves the release's names to it.
This commit is contained in:
@@ -0,0 +1,54 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Workbench events, delivered in batches to `event-handler.handle`.
|
||||
interface events {
|
||||
use types.{error, extension};
|
||||
|
||||
record action-performed {
|
||||
/// Action id (`editor.duplicate-line`).
|
||||
action: string,
|
||||
title: string,
|
||||
/// How the user started it: `keyboard`, `menu`, `toolbar`,
|
||||
/// `context-menu`, `search` or `other` (more may be added).
|
||||
source: string,
|
||||
/// Its keyboard shortcut, when it has one (`Ctrl+D`).
|
||||
shortcut: option<string>,
|
||||
}
|
||||
|
||||
variant event {
|
||||
file-opened(string),
|
||||
file-saved(string),
|
||||
editor-focused(option<string>),
|
||||
action-performed(action-performed),
|
||||
vcs-changed(string),
|
||||
scheduled,
|
||||
/// A kind added after 1.0 (subscribed to by its name).
|
||||
other(extension),
|
||||
}
|
||||
|
||||
/// Delivers `kind` events from now on, for the rest of the session (also
|
||||
/// across idle reclaim: an event activates the plugin again). Declare
|
||||
/// `activation = ["on-event:<kind>"]` to get them before first use.
|
||||
/// Kinds: `file-opened`, `file-saved`, `editor-focused` (the focused editor
|
||||
/// changed), `vcs-changed` (a repository's state changed: commit,
|
||||
/// checkout, fetch…), `action-performed` (an IDE action ran) and
|
||||
/// `scheduled` (the `on-schedule` period elapsed); later IDEs add more,
|
||||
/// and an IDE that doesn't know one fails with `invalid`.
|
||||
/// Requires `events` (`events.input` for `action-performed`).
|
||||
subscribe: func(kind: string) -> result<_, error>;
|
||||
unsubscribe: func(kind: string);
|
||||
}
|
||||
|
||||
/// Long-running work with a progress indicator. While a task is open, the
|
||||
/// call that began it may run for the background budget (60 s) instead of 5 s.
|
||||
interface tasks {
|
||||
resource task {
|
||||
/// `done` of `total` units (`none`: indeterminate), with a short status.
|
||||
report: func(done: u32, total: option<u32>, message: option<string>);
|
||||
/// The user cancelled it: stop soon and return.
|
||||
is-cancelled: func() -> bool;
|
||||
}
|
||||
|
||||
/// Starts a task shown in the status bar; dropping it ends it.
|
||||
begin: func(title: string, cancellable: bool) -> task;
|
||||
}
|
||||
@@ -0,0 +1,75 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
interface lifecycle {
|
||||
use types.{context, error};
|
||||
|
||||
/// Called once after the instance is created: subscribe to events and
|
||||
/// restore state from `storage`. Contributions (commands, languages,
|
||||
/// themes, …) are declared in plugin.toml, not registered here.
|
||||
/// An error fails the activation (shown on the plugin's page).
|
||||
activate: func(ctx: context) -> result<_, error>;
|
||||
/// Called before the instance is dropped (disable, uninstall, idle reclaim).
|
||||
deactivate: func();
|
||||
}
|
||||
|
||||
interface commands {
|
||||
use types.{error};
|
||||
use invocation.{invocation};
|
||||
|
||||
/// Runs one of the plugin's commands. Returns an optional message.
|
||||
/// `cancelled` (the user gave up) and `denied` (a capability is missing)
|
||||
/// are not counted as the plugin failing.
|
||||
run: func(id: string, ctx: borrow<invocation>, arg: option<string>) -> result<option<string>, error>;
|
||||
}
|
||||
|
||||
interface event-handler {
|
||||
use events.{event};
|
||||
use invocation.{invocation};
|
||||
|
||||
/// A batch of subscribed events, oldest first, from one window (`ctx`).
|
||||
handle: func(events: list<event>, ctx: borrow<invocation>);
|
||||
}
|
||||
|
||||
/// Optional export (world `plugin-syntax`): syntax of the plugin's own
|
||||
/// languages, for languages the IDE has no grammar for. The IDE calls it
|
||||
/// with the whole document; results are flat. Offsets are UTF-8 byte offsets
|
||||
/// into `text` (the IDE converts them); lines are 0-based.
|
||||
interface syntax-provider {
|
||||
/// One highlighted range. `kind` is a highlight category: keyword, string,
|
||||
/// string-special, escape, regexp, atom, number, constant, comment,
|
||||
/// doc-comment, function, function-call, builtin, type, namespace,
|
||||
/// variable, self-variable, property, attribute, macro, label, tag,
|
||||
/// operator, punctuation. Unknown kinds are ignored; ranges must be
|
||||
/// sorted and not overlap.
|
||||
record token {
|
||||
start: u32,
|
||||
end: u32,
|
||||
kind: string,
|
||||
}
|
||||
|
||||
/// A symbol of the structure view. `parent` is the index of the enclosing
|
||||
/// symbol in the same list (which must come first).
|
||||
record symbol {
|
||||
name: string,
|
||||
detail: option<string>,
|
||||
/// class, interface, struct, enum, function, method, constructor,
|
||||
/// field, property, variable, constant, module, namespace, event, …
|
||||
kind: string,
|
||||
start: u32,
|
||||
end: u32,
|
||||
name-start: u32,
|
||||
name-end: u32,
|
||||
parent: option<u32>,
|
||||
}
|
||||
|
||||
/// A foldable line range. `kind`: region, comment or imports.
|
||||
record fold {
|
||||
start-line: u32,
|
||||
end-line: u32,
|
||||
kind: string,
|
||||
}
|
||||
|
||||
highlights: func(language: string, text: string) -> list<token>;
|
||||
outline: func(language: string, text: string) -> list<symbol>;
|
||||
folding: func(language: string, text: string) -> list<fold>;
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Writes to the IDE log, tagged with the plugin id.
|
||||
interface log {
|
||||
use types.{log-level};
|
||||
|
||||
log: func(level: log-level, message: string);
|
||||
}
|
||||
|
||||
interface ui {
|
||||
use types.{notification-level};
|
||||
|
||||
record status-item {
|
||||
text: string,
|
||||
tooltip: option<string>,
|
||||
/// One of the plugin's commands, run when the item is clicked.
|
||||
command: option<string>,
|
||||
}
|
||||
|
||||
/// Shows a notification balloon in the window the current command or
|
||||
/// event came from (every window when there is none).
|
||||
show-notification: func(level: notification-level, title: string, body: string);
|
||||
/// Shows or updates the plugin's status bar item `id` in every window.
|
||||
set-status-item: func(id: string, item: status-item);
|
||||
remove-status-item: func(id: string);
|
||||
}
|
||||
|
||||
/// Persistent key-value storage of the plugin (survives restarts and idle
|
||||
/// reclaim; instance memory does not). Requires `storage`. At most 1 MiB.
|
||||
interface storage {
|
||||
use types.{error};
|
||||
|
||||
get: func(key: string) -> result<option<string>, error>;
|
||||
set: func(key: string, value: string) -> result<_, error>;
|
||||
delete: func(key: string) -> result<_, error>;
|
||||
/// Keys starting with `prefix`, sorted.
|
||||
keys: func(prefix: string) -> result<list<string>, error>;
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Problems in files, shown in the editor and the Problems view.
|
||||
interface diagnostics {
|
||||
use types.{error, range, location};
|
||||
|
||||
enum severity {
|
||||
error,
|
||||
warning,
|
||||
info,
|
||||
hint,
|
||||
}
|
||||
|
||||
/// Another place that explains a diagnostic (the earlier declaration, say).
|
||||
record related-information {
|
||||
location: location,
|
||||
message: string,
|
||||
}
|
||||
|
||||
record diagnostic {
|
||||
range: range,
|
||||
severity: severity,
|
||||
message: string,
|
||||
/// Rule or check id (`LineLength`).
|
||||
code: option<string>,
|
||||
/// The tool that found it, when not the plugin itself (`checkstyle`).
|
||||
source: option<string>,
|
||||
/// `unnecessary` (shown faded) and `deprecated` (struck through); unknown ones are ignored.
|
||||
tags: list<string>,
|
||||
related: list<related-information>,
|
||||
}
|
||||
|
||||
/// Replaces the plugin's diagnostics for the file at `path` (absolute, in
|
||||
/// an open project); an empty list clears them. Requires `project.read`.
|
||||
publish: func(path: string, diagnostics: list<diagnostic>) -> result<_, error>;
|
||||
}
|
||||
|
||||
/// HTTP(S) to the hosts granted with `net:<host>`.
|
||||
interface net {
|
||||
use types.{error};
|
||||
|
||||
record header {
|
||||
name: string,
|
||||
value: string,
|
||||
}
|
||||
|
||||
record request {
|
||||
method: string,
|
||||
/// `https://…`; plain `http://` only to `localhost` / `127.0.0.1`.
|
||||
url: string,
|
||||
/// `{{secret:<name>}}` in a value is replaced by the plugin's secret
|
||||
/// `name` on the way out (requires `secrets`); the plugin never sees it.
|
||||
headers: list<header>,
|
||||
body: option<list<u8>>,
|
||||
/// Default 30 s; the call's own budget applies too.
|
||||
timeout-ms: option<u32>,
|
||||
}
|
||||
|
||||
record response {
|
||||
status: u16,
|
||||
headers: list<header>,
|
||||
/// At most 8 MiB.
|
||||
body: list<u8>,
|
||||
}
|
||||
|
||||
/// Fails with `denied` for a host the plugin may not reach, `cancelled`
|
||||
/// when a newer request replaced the call or the user cancelled.
|
||||
fetch: func(req: request) -> result<response, error>;
|
||||
}
|
||||
|
||||
/// Secrets the user stored for the plugin (Settings › Plugins, kept in the
|
||||
/// OS keychain). Plugins only use them through `{{secret:<name>}}` in
|
||||
/// `net` requests. Requires `secrets`.
|
||||
interface secrets {
|
||||
is-set: func(name: string) -> bool;
|
||||
}
|
||||
|
||||
/// One-off runs of programs granted with `process:<program>` (the file the
|
||||
/// user approved, checked before every run).
|
||||
interface process {
|
||||
use types.{error};
|
||||
use workspace.{project};
|
||||
|
||||
record output {
|
||||
/// `none` when killed by a signal.
|
||||
status: option<s32>,
|
||||
/// At most 4 MiB each (the rest is dropped).
|
||||
stdout: string,
|
||||
stderr: string,
|
||||
}
|
||||
|
||||
/// Runs `program` with `args` in `cwd`'s root (else the plugin's data
|
||||
/// directory) and waits; cancelled with the task or call. Call it inside
|
||||
/// a task for anything slow.
|
||||
run: func(program: string, args: list<string>, cwd: option<borrow<project>>, stdin: option<string>) -> result<output, error>;
|
||||
}
|
||||
@@ -0,0 +1,67 @@
|
||||
/// OpenIDEA plugin API, version 1.0. Once released, 1.x only adds (new
|
||||
/// interfaces, new optional exports; plugins/README.md, "Evolving the plugin
|
||||
/// API"); a 2.0 keeps 1.0 running through an adapter in the host.
|
||||
///
|
||||
/// A plugin is a WebAssembly component targeting the `plugin` world (or
|
||||
/// `plugin-syntax`). It runs sandboxed: no filesystem, network, environment
|
||||
/// or processes beyond WASI's clocks and randomness; everything else goes
|
||||
/// through the imports below, gated by the capabilities granted in
|
||||
/// `plugin.toml` (a missing one returns `error::denied`).
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
world plugin {
|
||||
import log;
|
||||
import ui;
|
||||
import storage;
|
||||
import workspace;
|
||||
import editor;
|
||||
import invocation;
|
||||
import vcs;
|
||||
import events;
|
||||
import tasks;
|
||||
import diagnostics;
|
||||
import net;
|
||||
import secrets;
|
||||
import process;
|
||||
import views;
|
||||
import settings;
|
||||
|
||||
export lifecycle;
|
||||
export commands;
|
||||
export event-handler;
|
||||
}
|
||||
|
||||
/// A plugin that also provides syntax for its languages.
|
||||
world plugin-syntax {
|
||||
include plugin;
|
||||
export syntax-provider;
|
||||
}
|
||||
|
||||
/// A plugin with editor providers (`[[contributes.providers]]`).
|
||||
world plugin-providers {
|
||||
include plugin;
|
||||
export providers;
|
||||
}
|
||||
|
||||
/// A plugin with views or custom editors (`[[contributes.views]]`,
|
||||
/// `[[contributes.custom-editors]]`).
|
||||
world plugin-views {
|
||||
include plugin;
|
||||
export view-provider;
|
||||
}
|
||||
|
||||
/// Only the `syntax-provider` export: guests generate it next to `plugin`
|
||||
/// (the component tools merge both into one component).
|
||||
world syntax {
|
||||
export syntax-provider;
|
||||
}
|
||||
|
||||
/// Only the `providers` export, generated next to `plugin` like `syntax`.
|
||||
world editor-providers {
|
||||
export providers;
|
||||
}
|
||||
|
||||
/// Only the `view-provider` export, generated next to `plugin` like `syntax`.
|
||||
world views-provider {
|
||||
export view-provider;
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Editor features a plugin provides for the languages it declares under
|
||||
/// `[[contributes.providers]]` (the host calls only declared kinds). They run
|
||||
/// on the editing path: a result later than ~50 ms is dropped, a call still
|
||||
/// running at 500 ms is interrupted.
|
||||
interface providers {
|
||||
use types.{error, position, range, text-edit, location};
|
||||
|
||||
/// The document a request is about.
|
||||
record document {
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
record completion-item {
|
||||
label: string,
|
||||
detail: option<string>,
|
||||
/// Icon and sort group: text, method, function, constructor, field,
|
||||
/// variable, class, interface, module, property, unit, value, enum,
|
||||
/// keyword, snippet, color, file, reference, folder, enum-member,
|
||||
/// constant, struct, event, operator or type-parameter. Unknown kinds
|
||||
/// show no icon.
|
||||
kind: option<string>,
|
||||
/// With `snippet`, tab stops and placeholders (`$1`, `${1:name}`, `$0`).
|
||||
insert-text: string,
|
||||
snippet: bool,
|
||||
/// Replaced on accept; `none`: the word at the caret.
|
||||
replace: option<range>,
|
||||
sort-text: option<string>,
|
||||
/// Matched against what was typed instead of `label`.
|
||||
filter-text: option<string>,
|
||||
documentation: option<string>,
|
||||
/// Applied with the item elsewhere in the document (an import).
|
||||
additional-edits: list<text-edit>,
|
||||
}
|
||||
|
||||
record inline-suggestion {
|
||||
insert-text: string,
|
||||
/// Replaced range; `none` inserts at the caret.
|
||||
replace: option<range>,
|
||||
}
|
||||
|
||||
record file-edit {
|
||||
path: string,
|
||||
edits: list<text-edit>,
|
||||
}
|
||||
|
||||
record code-action {
|
||||
title: string,
|
||||
/// `quickfix`, `refactor`, …
|
||||
kind: option<string>,
|
||||
preferred: bool,
|
||||
edits: list<file-edit>,
|
||||
/// The plugin's own reference: with it and no `edits`, the edits are
|
||||
/// computed by `resolve-code-action` once the user picks the action.
|
||||
data: option<string>,
|
||||
}
|
||||
|
||||
record line-marker {
|
||||
line: u32,
|
||||
/// Gutter icon: `navigate` (default), `implemented`, `implementing`, `run`.
|
||||
icon: option<string>,
|
||||
tooltip: string,
|
||||
/// Opened on click.
|
||||
target: option<location>,
|
||||
}
|
||||
|
||||
completion: func(doc: document, at: position, trigger: option<string>) -> list<completion-item>;
|
||||
/// Ghost text at the caret (typing replaces an older request: it is cancelled).
|
||||
inline-completion: func(doc: document, at: position) -> option<inline-suggestion>;
|
||||
/// Actions for `selection` (quick fixes for the plugin's own diagnostics).
|
||||
code-actions: func(doc: document, selection: range) -> list<code-action>;
|
||||
/// The edits of an action `code-actions` returned with `data`, when the
|
||||
/// user picks it (the command budget applies, not the editor's 50 ms).
|
||||
resolve-code-action: func(doc: document, action: code-action) -> result<code-action, error>;
|
||||
definition: func(doc: document, at: position) -> list<location>;
|
||||
line-markers: func(doc: document) -> list<line-marker>;
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Shared types. Positions are 0-based lines and UTF-16 code unit columns,
|
||||
/// as in the editor and LSP.
|
||||
interface types {
|
||||
/// Why a host call failed. A capability that is not granted is reported
|
||||
/// as `denied`, so the plugin can degrade (0.1 trapped instead).
|
||||
variant error {
|
||||
/// Not granted; the payload names the capability (`editor.write`).
|
||||
denied(string),
|
||||
/// The document changed since the version the edit was made for.
|
||||
stale,
|
||||
not-found(string),
|
||||
invalid(string),
|
||||
/// Cancelled by the user, or the plugin is being stopped.
|
||||
cancelled,
|
||||
failed(string),
|
||||
}
|
||||
|
||||
enum log-level {
|
||||
trace,
|
||||
debug,
|
||||
info,
|
||||
warn,
|
||||
error,
|
||||
}
|
||||
|
||||
enum notification-level {
|
||||
info,
|
||||
warning,
|
||||
error,
|
||||
}
|
||||
|
||||
record position {
|
||||
line: u32,
|
||||
character: u32,
|
||||
}
|
||||
|
||||
record range {
|
||||
start: position,
|
||||
end: position,
|
||||
}
|
||||
|
||||
record text-edit {
|
||||
range: range,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// A range in a file (absolute path).
|
||||
record location {
|
||||
path: string,
|
||||
range: range,
|
||||
}
|
||||
|
||||
/// A case added after 1.0, carried by the `other` case of a variant that
|
||||
/// grows (events, view bodies, view events, form fields): its kind and its
|
||||
/// data as JSON. Whoever doesn't know the kind ignores it or shows a
|
||||
/// fallback; the SDKs decode the kinds they know.
|
||||
record extension {
|
||||
kind: string,
|
||||
data: string,
|
||||
}
|
||||
|
||||
/// Passed to `lifecycle.activate`.
|
||||
record context {
|
||||
plugin-id: string,
|
||||
plugin-version: string,
|
||||
/// Version of this API the host implements, e.g. "1.0".
|
||||
api-version: string,
|
||||
/// Capabilities granted to the plugin (`editor.write`, `process:git`, …).
|
||||
capabilities: list<string>,
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,154 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
/// Declarative views: tool windows declared
|
||||
/// under `[[contributes.views]]` and custom editors under
|
||||
/// `[[contributes.customEditors]]`. The plugin describes what to show; the
|
||||
/// IDE renders it with its own components (theme, keyboard, accessibility)
|
||||
/// and sends the user's actions back as `view-event`s. Nothing of the plugin
|
||||
/// runs in the WebView, except a `html` body, which is shown in a sandboxed
|
||||
/// frame that can only exchange messages with the plugin.
|
||||
interface view-types {
|
||||
use types.{extension};
|
||||
|
||||
record button {
|
||||
id: string,
|
||||
label: string,
|
||||
/// An IDE icon name (`refresh`, `add`, `remove`, `run`, …).
|
||||
icon: option<string>,
|
||||
enabled: bool,
|
||||
}
|
||||
|
||||
/// A tree node; `parent` is the key of an earlier item (none: a root).
|
||||
record tree-item {
|
||||
key: string,
|
||||
parent: option<string>,
|
||||
label: string,
|
||||
icon: option<string>,
|
||||
/// Grey text after the label.
|
||||
detail: option<string>,
|
||||
/// Shows an expander even before its children are known
|
||||
/// (`expand` asks for them).
|
||||
expandable: bool,
|
||||
expanded: bool,
|
||||
}
|
||||
|
||||
record list-item {
|
||||
key: string,
|
||||
label: string,
|
||||
icon: option<string>,
|
||||
detail: option<string>,
|
||||
}
|
||||
|
||||
variant field-value {
|
||||
text(string),
|
||||
multiline(string),
|
||||
checkbox(bool),
|
||||
/// The options and the chosen one.
|
||||
choice(tuple<list<string>, string>),
|
||||
/// A field type added after 1.0 (an IDE that doesn't know it leaves it out).
|
||||
other(extension),
|
||||
}
|
||||
|
||||
record field {
|
||||
key: string,
|
||||
label: string,
|
||||
value: field-value,
|
||||
}
|
||||
|
||||
/// Rows `first-row`..`first-row + len(rows)` of `total-rows`: the IDE
|
||||
/// asks for the rows it shows (`viewport`), so large tables stay cheap.
|
||||
record table {
|
||||
columns: list<string>,
|
||||
total-rows: u32,
|
||||
first-row: u32,
|
||||
rows: list<list<string>>,
|
||||
editable: bool,
|
||||
}
|
||||
|
||||
variant body {
|
||||
/// A centred message (empty state, errors).
|
||||
message(string),
|
||||
tree(list<tree-item>),
|
||||
%list(list<list-item>),
|
||||
form(list<field>),
|
||||
table(table),
|
||||
/// HTML shown in a sandboxed frame: no scripts from elsewhere, no
|
||||
/// network, no IDE API. Its script talks to the plugin with
|
||||
/// `openidea.postMessage(text)` / `openidea.onMessage(fn)`.
|
||||
html(string),
|
||||
/// A body added after 1.0; an IDE that doesn't know it says it needs updating.
|
||||
other(extension),
|
||||
}
|
||||
|
||||
record view {
|
||||
toolbar: list<button>,
|
||||
body: body,
|
||||
/// A line below the body (counts, last refresh…).
|
||||
status: option<string>,
|
||||
}
|
||||
|
||||
/// The table rows the IDE shows.
|
||||
record viewport {
|
||||
first-row: u32,
|
||||
rows: u32,
|
||||
}
|
||||
|
||||
record cell-edit {
|
||||
row: u32,
|
||||
column: u32,
|
||||
value: string,
|
||||
}
|
||||
|
||||
variant view-event {
|
||||
/// A toolbar button.
|
||||
button(string),
|
||||
/// Double click / Enter on a tree or list item.
|
||||
activate(string),
|
||||
select(string),
|
||||
expand(string),
|
||||
collapse(string),
|
||||
/// A form field changed: key and new value (`true`/`false` for checkboxes).
|
||||
field(tuple<string, string>),
|
||||
cell(cell-edit),
|
||||
/// Insert an empty row before this one (the row count: append).
|
||||
insert-row(u32),
|
||||
delete-rows(list<u32>),
|
||||
/// From the `html` body's script.
|
||||
message(string),
|
||||
/// An event added after 1.0, from a body or field added after 1.0.
|
||||
other(extension),
|
||||
}
|
||||
}
|
||||
|
||||
/// What a plugin's code can ask of its views.
|
||||
interface views {
|
||||
use types.{error};
|
||||
|
||||
/// The view (or every custom editor of that id) shows outdated content:
|
||||
/// the IDE renders it again.
|
||||
refresh: func(view: string);
|
||||
/// Sends a message to the script of a view's `html` body.
|
||||
post-message: func(view: string, message: string) -> result<_, error>;
|
||||
/// Opens a terminal tab in the window the call came from, running
|
||||
/// `program` (pinned by a `process:<program>` grant) with `args` in the
|
||||
/// project root: long-running output (logs) and interactive sessions.
|
||||
open-terminal: func(title: string, program: string, args: list<string>) -> result<_, error>;
|
||||
}
|
||||
|
||||
/// The plugin's own settings (`[contributes.settings]`), as the user set them
|
||||
/// (project over global) or the schema's default.
|
||||
interface settings {
|
||||
/// The value of `key` as JSON (`true`, `3`, `"text"`), none if unknown.
|
||||
get: func(key: string) -> option<string>;
|
||||
}
|
||||
|
||||
/// Optional export (world `plugin-views`): content of declared views and
|
||||
/// custom editors. For a custom editor, `ctx.editor()` is its document.
|
||||
interface view-provider {
|
||||
use view-types.{view, viewport, view-event};
|
||||
use invocation.{invocation};
|
||||
use types.{error};
|
||||
|
||||
render: func(view: string, viewport: option<viewport>, ctx: borrow<invocation>) -> result<view, error>;
|
||||
handle: func(view: string, event: view-event, ctx: borrow<invocation>) -> result<_, error>;
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
package openidea:plugin@1.0.0;
|
||||
|
||||
interface workspace {
|
||||
use types.{error};
|
||||
|
||||
/// A project open in the IDE.
|
||||
resource project {
|
||||
/// Absolute path of the project root. Requires `project.read`.
|
||||
root: func() -> result<string, error>;
|
||||
/// Reads a UTF-8 text file inside the project (absolute, or relative
|
||||
/// to the root); paths leaving the root are refused. Unsaved editor
|
||||
/// contents win over the disk. Requires `project.read`.
|
||||
read-file: func(path: string) -> result<string, error>;
|
||||
/// Project files whose root-relative path matches `glob` (`**/*Mapper.xml`),
|
||||
/// at most `limit`, as absolute paths. Ignored and excluded files are
|
||||
/// skipped. Requires `project.read`.
|
||||
find-files: func(glob: string, limit: u32) -> result<list<string>, error>;
|
||||
}
|
||||
|
||||
/// Projects open in any window. Requires `project.read`.
|
||||
projects: func() -> result<list<project>, error>;
|
||||
}
|
||||
|
||||
interface editor {
|
||||
use types.{error, range, text-edit};
|
||||
|
||||
record document {
|
||||
/// Grows with every change; edits name the version they were made for.
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// A file open in an editor.
|
||||
resource text-editor {
|
||||
/// Absolute path of the file.
|
||||
path: func() -> string;
|
||||
/// Language id (`rust`, `solidity`, …).
|
||||
language: func() -> string;
|
||||
/// Current version and text. Requires `editor.read`.
|
||||
document: func() -> result<document, error>;
|
||||
/// Selections when the command was invoked (a cursor is an empty
|
||||
/// range). Requires `editor.read`.
|
||||
selections: func() -> result<list<range>, error>;
|
||||
/// Applies `edits` as one undoable change, only if the document is
|
||||
/// still at `version` (else `stale`, and nothing changes). Ranges are
|
||||
/// in that version and must not overlap. Returns the new version.
|
||||
/// Requires `editor.write`.
|
||||
apply-edits: func(version: u64, edits: list<text-edit>) -> result<u64, error>;
|
||||
}
|
||||
}
|
||||
|
||||
/// Where a command or event comes from.
|
||||
interface invocation {
|
||||
use workspace.{project};
|
||||
use editor.{text-editor};
|
||||
|
||||
resource invocation {
|
||||
/// The window's project.
|
||||
project: func() -> option<project>;
|
||||
/// The window's focused editor.
|
||||
editor: func() -> option<text-editor>;
|
||||
}
|
||||
}
|
||||
|
||||
/// Git, for the repository containing a project.
|
||||
interface vcs {
|
||||
use types.{error};
|
||||
use workspace.{project};
|
||||
|
||||
record repository-status {
|
||||
/// Absolute path of the working tree root.
|
||||
root: string,
|
||||
/// `none` when HEAD is detached.
|
||||
branch: option<string>,
|
||||
commit: option<string>,
|
||||
upstream: option<string>,
|
||||
ahead: u32,
|
||||
behind: u32,
|
||||
/// Merge / rebase / cherry-pick in progress.
|
||||
operation: option<string>,
|
||||
/// Files with staged or unstaged changes.
|
||||
changed-files: u32,
|
||||
}
|
||||
|
||||
/// `none` when the project is not in a repository. Requires `vcs.read`.
|
||||
status: func(project: borrow<project>) -> result<option<repository-status>, error>;
|
||||
/// Fetches all remotes (pruning deleted branches). Requires `vcs.write`.
|
||||
/// Long-running: call it inside a task.
|
||||
fetch: func(project: borrow<project>) -> result<_, error>;
|
||||
}
|
||||
@@ -140,12 +140,18 @@ fn released_apis_are_unchanged() {
|
||||
for (key, was) in &release {
|
||||
match current.get(key) {
|
||||
None => broken.push(format!("{key}: removed (was {was})")),
|
||||
// A world may gain imports and exports; everything else stays as it was.
|
||||
// A world may gain imports and exports; everything else stays as it was. Items are
|
||||
// compared without their `@version`: a later minor names them `@1.1.0`, and wasmtime
|
||||
// resolves the release's `@1.0.0` to it.
|
||||
Some(now) if key.starts_with("world ") => {
|
||||
let had = |s: &str, part: &str| -> Vec<String> {
|
||||
let start = s.find(part).unwrap() + part.len();
|
||||
let end = s[start..].find(']').unwrap() + start;
|
||||
s[start..end].split(", ").filter(|x| !x.is_empty()).map(str::to_owned).collect()
|
||||
s[start..end]
|
||||
.split(", ")
|
||||
.filter(|x| !x.is_empty())
|
||||
.map(|x| x.split('@').next().unwrap_or(x).to_owned())
|
||||
.collect()
|
||||
};
|
||||
for part in ["imports [", "exports ["] {
|
||||
let now = had(now, part);
|
||||
|
||||
Reference in New Issue
Block a user