mirror of
https://github.com/l0ng-ai/openidea.git
synced 2026-11-08 08:52:12 +00:00
feat(plugins): tidy the unreleased 1.3 API before it freezes (#2079)
- workspace.symbols becomes the project method project.symbols(query, limit), like find-files; the Rust SDK's Project::symbols is unchanged, components built against the previous main need a rebuild. - The open-log-tab web message names its arguments args, as pty-spawn and the services process-log do; baseArgs is refused with log-error rather than ignored. - Document the hover, semantic-tokens and diagnostics provider exports and their worlds.
This commit is contained in:
1 parent
32a778d28d
commit
ec171c3188
86 files changed
+177
-111
No files matched your search
@@ -519,39 +519,6 @@ impl workspace::Host for StoreData {
|
||||
self.host.project_of(Path::new(&path)).map(|root| self.push(ProjectRes { root })).transpose()
|
||||
}
|
||||
|
||||
fn symbols(
|
||||
&mut self,
|
||||
project: Resource<ProjectRes>,
|
||||
query: String,
|
||||
limit: u32,
|
||||
) -> Fallible<Vec<workspace::SymbolInfo>> {
|
||||
if let Err(e) = self.require(Capability::ProjectRead) {
|
||||
return Ok(Err(e));
|
||||
}
|
||||
if query.len() > 256 {
|
||||
return Ok(Err(wit::Error::Invalid("symbol query exceeds 256 UTF-8 bytes".into())));
|
||||
}
|
||||
let root = &self.table.get(&project)?.root;
|
||||
Ok(self
|
||||
.host
|
||||
.symbols(root, &query, limit.min(1000) as usize, &self.cancel.token(), self.deadline)
|
||||
.map(|symbols| {
|
||||
symbols
|
||||
.into_iter()
|
||||
.map(|s| workspace::SymbolInfo {
|
||||
name: s.name,
|
||||
kind: s.kind,
|
||||
container: s.container,
|
||||
location: wit::Location {
|
||||
path: to_ipc(&s.location.path),
|
||||
range: range_to_wit(&s.location.range),
|
||||
},
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.map_err(to_wit))
|
||||
}
|
||||
|
||||
fn projects(&mut self) -> Fallible<Vec<Resource<ProjectRes>>> {
|
||||
if let Err(e) = self.require(Capability::ProjectRead) {
|
||||
return Ok(Err(e));
|
||||
@@ -632,6 +599,39 @@ impl workspace::HostProject for StoreData {
|
||||
Ok(self.host.find_files(&root, &glob, limit.min(MAX_FIND) as usize).map_err(to_wit))
|
||||
}
|
||||
|
||||
fn symbols(
|
||||
&mut self,
|
||||
this: Resource<ProjectRes>,
|
||||
query: String,
|
||||
limit: u32,
|
||||
) -> Fallible<Vec<workspace::SymbolInfo>> {
|
||||
if let Err(e) = self.require(Capability::ProjectRead) {
|
||||
return Ok(Err(e));
|
||||
}
|
||||
if query.len() > 256 {
|
||||
return Ok(Err(wit::Error::Invalid("symbol query exceeds 256 UTF-8 bytes".into())));
|
||||
}
|
||||
let root = &self.table.get(&this)?.root;
|
||||
Ok(self
|
||||
.host
|
||||
.symbols(root, &query, limit.min(1000) as usize, &self.cancel.token(), self.deadline)
|
||||
.map(|symbols| {
|
||||
symbols
|
||||
.into_iter()
|
||||
.map(|s| workspace::SymbolInfo {
|
||||
name: s.name,
|
||||
kind: s.kind,
|
||||
container: s.container,
|
||||
location: wit::Location {
|
||||
path: to_ipc(&s.location.path),
|
||||
range: range_to_wit(&s.location.range),
|
||||
},
|
||||
})
|
||||
.collect()
|
||||
})
|
||||
.map_err(to_wit))
|
||||
}
|
||||
|
||||
fn write_file(&mut self, this: Resource<ProjectRes>, path: String, text: String) -> Fallible<()> {
|
||||
if let Err(e) = self.require(Capability::ProjectWrite) {
|
||||
return Ok(Err(e));
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
da346bd256a61b971c09632465b187c580809cb7f16faa2588d22c6369cba600
|
||||
6efbb6db8442a4dec21e65bb8c4c65e08b0da32082ee26e870c0419ebaf4e7fb
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
002f86e29e9bf4f5f4adeeedd2889d492dbf41b60900c03c25cd84d6f3d226fb
|
||||
21520d2522afaa7212e5c9b765110a334b2a1fe69302f602f05a61dcee08cd0b
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
a2815b273e270d473a80c3d416a41d9d7a44bbc7c87b8aae6668c734e89bac5c
|
||||
9d79e3f45abf0aaba03d30aa482decd3142d879b5964d12298b0aa6cbac581fd
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
88bead9074bf6f2dfa2ceb0756b010b7f3b322e3bd977858f2fac97c840fd56e
|
||||
05442db7ac00e3bcc4670d87d846c46a05c02d101e1651c587245fd5aeb1152f
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
75145b486069cfb44429127ecb11ad863b9c6a88eff3205248c6ce5cf157d516
|
||||
47c2a8deea407ed7bf6a56af8c118295f4ceed394faaff9b535e97cb4ea31115
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
85d822e6ff64e6a5528d0b09d5ad3817ef77ea0f8a4832337c8958a002179755
|
||||
884a42bd59ac64d08e9a0d3a72d4f1d1f25e850ef0b828be01142b61eda8db64
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
badc9dc4fa12739850a5935b3d13e9a223fa7e348af785c5e164a32c5dda2989
|
||||
48d2ab9cc824ed06ae34126d6651a9b7127599626cc00f7aa76d9b3161a2963f
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
52565fa3ed2d76a4f61f7e870bb74124ca901a4efbc12025039c69aaf9a97844
|
||||
5233d7518b685e641fdd48ac2a53e6ca7381c182d36d7920607714703ba37a47
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
dcff32b4f59f5f9ad868fd6cb94a8e8e38e4ff4258b70ed3cb0cfd394ae632a3
|
||||
3a77168e971d60ca4248b9bb2c27516614f74409324125821e74e3a236a67fb9
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
91988c62e885b8792028710a460fc47300de19b96bf9ed23748709e5cdcc5cc1
|
||||
4261434b2dd234426253f07f7e7e3daf8676fcf5680a578ac1b99f503fea2859
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
ebc79bf4f9847003dca269a2870f1ca8d4362102a644ca220dc630c3040fbdf7
|
||||
cc07e85ef5324b4d1d706665b0025b6682a581d1b91196f45a64284e238c7297
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
fb262393a3c0149719b460bc39d8df656a7e8a52f51257c2e1188e0e620bb3eb
|
||||
d0c974dee4010d0e3186bd426e3c53d09c2c56861b04e40f2187515bbb81f8d9
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
78959a803256b5555deadb8952e7410cc661c83dd1046fcf71e2143c2e33d524
|
||||
91ed6b9ee1cf77a0c3bee941aafceb252e7acd241f1d85ecb0366de98ee541d5
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
d16118dd417be01dd23cc2e8693c3d5f5f12b679b72e3c5c5991370fa0b3bccb
|
||||
3eb9c513691e5ad323d4ba6520ccec6305049a39f13e8d74dccb728ab2f0ffca
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
c73610ba50bc540f6719865a4864ec647f1e4b5983fc254e886e7c99d3b552f8
|
||||
6d59a4f37827a64d40cfe34dbcd9fea2b1de40ab39596c364b2cb7f5502de063
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
46d77e5912893a8a70150944b26c9f41f23ffcccaa6666a245a0203fd836f77b
|
||||
5da249c8c78cfcdf8f580099974d2ca654e98debb319f253c42ba18e5082fd0e
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
42848c3b8b0aeaee3e861c8b76b85d13d28374572fc6e17e059b2d2015fbac17
|
||||
961f07c9e1044e3e8c861a85ce4b2020cbbe9ce02b3764d1ec44a83d6c95eba1
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
135f065b9832ba8c86ca0fb5ea4b30ae6a4b38c00f178215ce288fee737acbb6
|
||||
31c61ed0204bd3b2f9152d20f9f275effc305ba7dd095d708c00f34fce023492
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
c6f9b2167494532cc201279f2ac4a9c642ac09571197d7101e773c87b0ab19d5
|
||||
162cde1d53b72a4c88a98cc51a31a2536d0506aeef60e15295b44c682be50fb7
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
b7e055bda20c99de9385a6c90ee1e2ae57fb9288b84b8c71e3eb9cb536869fc6
|
||||
aa7327f38c6277cfd7751b921bd43ac63ab8cb615ea428ccdfe9c4750606c6ad
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
c61cbdcbb2af15cffdd75f8bc5bd411d849b80cb0cd19227a7632b2770e21f58
|
||||
afece2c28e5077507159da59a93a73ede869678d168b3eaa7345962183417744
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
c79eefe6730dc50e4c013b80cc1493c89974d9bbcbc7f4278e6136f20dbbffc3
|
||||
29dd12ef6b9399c3d58b80ca145f6e903b70a9b220be7ca69a2672ee2c3e5582
|
||||
+1
-1
@@ -20,7 +20,7 @@ while true; do
|
||||
done`;
|
||||
const send = (program) => openidea.postMessage(JSON.stringify({
|
||||
op: 'open-log-tab', key: 'probe', title: 'Probe logs', program,
|
||||
baseArgs: ['--noprofile', '--norc', '-c', script, 'log-probe'],
|
||||
args: ['--noprofile', '--norc', '-c', script, 'log-probe'],
|
||||
toggles: [{ id: 'verbose', label: 'Verbose', args: ['--verbose'] }]
|
||||
}));
|
||||
document.querySelector('#open').onclick = () => send('bash');
|
||||
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
0dfe2f704cf0ad9b2ab06cfb92a190a19bcf18fe3d5da473a6f05b16002a76ff
|
||||
ebc3a1213b97addb5abcbbfcf4baaff3f7644d1b60b62e2f215d3a35f36f221b
|
||||
+3
-3
@@ -1119,7 +1119,7 @@ openidea.postMessage(JSON.stringify({
|
||||
key: "server-output",
|
||||
title: "Server logs",
|
||||
program: "my-server",
|
||||
baseArgs: ["logs"],
|
||||
args: ["logs"],
|
||||
toggles: [{ id: "verbose", label: "Verbose", args: ["--verbose"] }],
|
||||
}));
|
||||
```
|
||||
@@ -1130,9 +1130,9 @@ session caps and lifecycle rules are the same as for web frame PTYs. The tab
|
||||
uses the backend PTY API, never a shell fallback. It supplies no environment
|
||||
overrides; the environment is inherited. A shell requires its own explicit grant.
|
||||
|
||||
`program` is required. `baseArgs` and `toggles` default to empty arrays; `title`
|
||||
`program` is required. `args` and `toggles` default to empty arrays; `title`
|
||||
defaults to the program. Each toggle has a unique `id`, a plugin-localized
|
||||
`label`, and `args` appended after `baseArgs` in declaration order. Changing a
|
||||
`label`, and `args` appended after the top-level `args` in declaration order. Changing a
|
||||
toggle terminates the previous process and replaces the stream. `key` defaults
|
||||
to the title and is scoped to the calling plugin and view; reopening the same
|
||||
key focuses its existing tab. Titles are at most 256 characters, keys 128,
|
||||
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
344df18074d7171c42ae2c245e6ea2beeb7119ed6bf74b76503d241513ddcdba
|
||||
b390c7f6acf5d32cbf451faf7a6393f2d4f130d5131ef0857a2b0904c434f598
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
b5f99458a32d54373661e8f61569b1e675e19594275036153b8c52fea74d8f69
|
||||
1eea85130f5feacdcd6aade3548ac8e6ca4c1b316441346a89a7be6c13caaba7
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
b6f765692f944b63cb9ec0749a49c9d3be077b0eab709f148ffb0fb058ff1829
|
||||
d2e1a074d81a4f29935524b6ba11a94d6a9bc301833ea721ed9e7cab461e198e
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
27a37336df957085a73504c5957033f1b178bcc47c190ffcd234ebad2d900817
|
||||
150ed795daab29e3a152e50ebdf5e4ec3ca569d792962b77fce5fac428e7e076
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
99f00d65801c278a6d8a4e4466d0bf71738233c849dfcaf44902d60a557b8757
|
||||
580e19fd349b6be1f2d4c32e572015337ef8f1e73b1b1f24199fc6d4ea73189f
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
0ace6d1b7f9f3cac0d23f92660d97d6eb6c79174203471970f3e4ca9f7d9b531
|
||||
64d1e9a8bf48355f380feba052ea0ffb5f4ae7957b04d0a62a04e1d49d6ed690
|
||||
Binary file not shown.
@@ -1 +1 @@
|
||||
9241c310c638a6a2e5e90e32c0651c76184498d193ad344f762f33a301bcaaab
|
||||
ef76535391c4186a6373ef61197d96cc3ad7c42f47505ec75328ba5385e4df6e
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
e484774db29b214fb7247c6a403a7c9dbfaa030b0315c353826bf44982f82d61
|
||||
246a3ace4e3ccdd9ed4f2499cde275c9ea2402fbb902893cc2d8d3403175bd47
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
ec03327641cc9f32d9205718847939981b3ec5e74e4aa2b800ba1598bccdb70f
|
||||
75b3b93fe5ca2c5a58052c931f4d9cd824c379227d7f4cd8477fa89d045cda06
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
baf14df1362b15a0022456d3ea927b9fe07533dabf1fb717888ea98179152464
|
||||
59f62db0a1c20a1d4fa6b380cd3272ec70ea4789835873d0abe3839ec08c94c3
|
||||
BIN
Binary file not shown.
+1
-1
@@ -1 +1 @@
|
||||
5c96088e3f31ee74669bb4481fee6c95f51a9d875ad9bed9123f3e0de1a6ead5
|
||||
548c6ed16fcd5d3a053bf6d8417d52ebd0fd74138d0665e9205eb8bf32ec497a
|
||||
@@ -311,7 +311,7 @@ mod imp {
|
||||
}
|
||||
|
||||
pub fn project_symbols(p: &ProjectRes, query: &str, limit: u32) -> Result<Vec<SymbolInfo>, Error> {
|
||||
wit::workspace::symbols(p, query, limit)
|
||||
p.symbols(query, limit)
|
||||
.map(|symbols| {
|
||||
symbols
|
||||
.into_iter()
|
||||
|
||||
@@ -1,15 +1,22 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional diagnostics for the current, possibly unsaved document (API 1.3).
|
||||
/// Optional export (world `plugin-diagnostics`): problems in the current,
|
||||
/// possibly unsaved document, for the languages declared with the
|
||||
/// `diagnostics` provider kind. Asked shortly after a document opens or
|
||||
/// changes, under the editor-provider budget; it can't ask the user.
|
||||
interface diagnostics-provider {
|
||||
use diagnostics.{diagnostic};
|
||||
|
||||
/// The document to check (the editor's text, unsaved edits included).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// The document's problems, at most 5,000; they replace what this
|
||||
/// provider reported before, and an empty list removes them.
|
||||
diagnostics: func(doc: document) -> list<diagnostic>;
|
||||
}
|
||||
@@ -1,19 +1,29 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional export (world `plugin-hover`): Markdown added to the hover of
|
||||
/// documents of the languages declared with the `hover` provider kind,
|
||||
/// including languages the plugin doesn't contribute. It shows below the
|
||||
/// language server's hover, under the edit-path budget.
|
||||
interface hover-provider {
|
||||
use types.{position, range};
|
||||
|
||||
/// The document hovered (the editor's text while it is open).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// What the plugin adds to the hover.
|
||||
record hover-content {
|
||||
/// At most 64 KiB.
|
||||
markdown: string,
|
||||
/// The text the hover describes; used when the server names none.
|
||||
range: option<range>,
|
||||
}
|
||||
|
||||
/// The hover at `at`, or `none` to add nothing.
|
||||
hover: func(doc: document, at: position) -> option<hover-content>;
|
||||
}
|
||||
@@ -59,11 +59,13 @@ world plugin-indexing {
|
||||
export document-indexer;
|
||||
}
|
||||
|
||||
/// A plugin with semantic tokens (`semantic-tokens` under `[[contributes.providers]]`).
|
||||
world plugin-semantic-tokens {
|
||||
include plugin;
|
||||
export semantic-tokens-provider;
|
||||
}
|
||||
|
||||
/// A plugin adding to hovers (`hover` under `[[contributes.providers]]`).
|
||||
world plugin-hover {
|
||||
include plugin;
|
||||
export hover-provider;
|
||||
@@ -115,10 +117,12 @@ world indexing {
|
||||
export document-indexer;
|
||||
}
|
||||
|
||||
/// Only the `semantic-tokens-provider` export, generated next to `plugin` like `syntax`.
|
||||
world semantic-tokens {
|
||||
export semantic-tokens-provider;
|
||||
}
|
||||
|
||||
/// Only the `hover-provider` export, generated next to `plugin` like `syntax`.
|
||||
world hover {
|
||||
export hover-provider;
|
||||
}
|
||||
@@ -149,6 +153,7 @@ world plugin-endpoints {
|
||||
export endpoints-provider;
|
||||
}
|
||||
|
||||
/// Only the `endpoints-provider` export, generated next to `plugin` like `syntax`.
|
||||
world endpoints {
|
||||
export endpoints-provider;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional export (world `plugin-semantic-tokens`): semantic colouring of
|
||||
/// documents of the languages declared with the `semantic-tokens` provider
|
||||
/// kind, including languages the plugin doesn't contribute. The tokens join
|
||||
/// the language server's and win where they overlap one.
|
||||
interface semantic-tokens-provider {
|
||||
use types.{range};
|
||||
|
||||
/// The document to colour (the editor's text while it is open).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// A token: part of one line.
|
||||
record semantic-token {
|
||||
range: range,
|
||||
/// An LSP token type in kebab-case (`method`, `property`, `type`, …).
|
||||
kind: string,
|
||||
/// LSP token modifiers in kebab-case (`static`, `deprecated`, …).
|
||||
modifiers: list<string>,
|
||||
}
|
||||
|
||||
/// The document's tokens, at most 65,536; asked again after each edit,
|
||||
/// under the edit-path budget.
|
||||
semantic-tokens: func(doc: document) -> list<semantic-token>;
|
||||
}
|
||||
@@ -39,17 +39,6 @@ interface workspace {
|
||||
location: location,
|
||||
}
|
||||
|
||||
/// Fuzzy symbol search (CamelHump and container-qualified queries) over the
|
||||
/// current index only; never starts or waits for a language server. Results
|
||||
/// may be incomplete while indexing and ranges reflect the indexed text,
|
||||
/// not necessarily unsaved edits. Empty queries return no symbols. Queries
|
||||
/// over 256 UTF-8 bytes are invalid; limit is capped at 1000 (zero is empty).
|
||||
/// Only paths readable under this project's root are returned; external
|
||||
/// content roots are excluded. Cancellation returns cancelled; exceeding the
|
||||
/// current call's deadline fails. A closed project is not-found.
|
||||
/// Requires `project.read`. New in 1.3.
|
||||
symbols: func(project: borrow<project>, query: string, limit: u32) -> result<list<symbol-info>, error>;
|
||||
|
||||
/// A project open in the IDE.
|
||||
resource project {
|
||||
/// Absolute path of the project root. Requires `project.read`.
|
||||
@@ -80,6 +69,16 @@ interface workspace {
|
||||
/// 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>;
|
||||
/// Fuzzy symbol search (CamelHump and container-qualified queries) over the
|
||||
/// current index only; never starts or waits for a language server. Results
|
||||
/// may be incomplete while indexing and ranges reflect the indexed text,
|
||||
/// not necessarily unsaved edits. Empty queries return no symbols. Queries
|
||||
/// over 256 UTF-8 bytes are invalid; limit is capped at 1000 (zero is
|
||||
/// empty). Only paths readable under the root are returned; external
|
||||
/// content roots are excluded. Cancellation returns cancelled; exceeding
|
||||
/// the current call's deadline fails. A closed project is not-found.
|
||||
/// Requires `project.read`.
|
||||
symbols: func(query: string, limit: u32) -> result<list<symbol-info>, error>;
|
||||
}
|
||||
|
||||
/// Projects open in any window. Requires `project.read`.
|
||||
|
||||
@@ -19,7 +19,7 @@ const plugin = { id: "probe", enabled: true, capabilities: [{ id: "process:bash"
|
||||
const spec = {
|
||||
program: "bash",
|
||||
title: "Probe logs",
|
||||
baseArgs: ["--noprofile", "--norc"],
|
||||
args: ["--noprofile", "--norc"],
|
||||
toggles: [{ id: "verbose", label: "Verbose", args: ["-v"] }],
|
||||
};
|
||||
let stopActions: () => void;
|
||||
@@ -76,9 +76,10 @@ describe("plugin streaming log tabs", () => {
|
||||
{ program: "sh" },
|
||||
{ program: "/bin/bash" },
|
||||
{ program: " bash" },
|
||||
{ baseArgs: [123] },
|
||||
{ baseArgs: ["\0"] },
|
||||
{ baseArgs: ["x".repeat(4097)] },
|
||||
{ args: [123] },
|
||||
{ args: ["\0"] },
|
||||
{ args: ["x".repeat(4097)] },
|
||||
{ baseArgs: ["--verbose"] },
|
||||
{ cwd: "/" },
|
||||
{ env: { PATH: "/tmp" } },
|
||||
{ title: "x".repeat(257) },
|
||||
@@ -102,7 +103,7 @@ describe("plugin streaming log tabs", () => {
|
||||
const f = setup();
|
||||
expect(webPtyBackend).toHaveBeenCalledWith("probe", "logs");
|
||||
expect(f.backend.spawn).toHaveBeenCalledWith(
|
||||
expect.objectContaining({ program: "bash", env: {}, args: spec.baseArgs }),
|
||||
expect.objectContaining({ program: "bash", env: {}, args: spec.args }),
|
||||
expect.any(Function),
|
||||
);
|
||||
expect(f.view().state.facet(EditorState.readOnly)).toBe(true);
|
||||
@@ -128,7 +129,7 @@ describe("plugin streaming log tabs", () => {
|
||||
fireEvent.click(screen.getByRole("switch", { name: "Verbose" }));
|
||||
await waitFor(() => expect(f.backend.kill).toHaveBeenCalledWith(42));
|
||||
expect(f.backend.spawn).toHaveBeenLastCalledWith(
|
||||
expect.objectContaining({ args: [...spec.baseArgs, "-v"] }),
|
||||
expect.objectContaining({ args: [...spec.args, "-v"] }),
|
||||
expect.any(Function),
|
||||
);
|
||||
vi.mocked(f.backend.kill).mockClear();
|
||||
|
||||
@@ -277,7 +277,7 @@ describe("WebView", () => {
|
||||
title: "App Logs",
|
||||
key: "shared",
|
||||
program: "tail",
|
||||
baseArgs: ["-f", "app.log"],
|
||||
args: ["-f", "app.log"],
|
||||
toggles: [{ id: "verbose", label: "Verbose", args: ["-v"] }],
|
||||
};
|
||||
|
||||
@@ -308,7 +308,7 @@ describe("WebView", () => {
|
||||
pluginId: "acme.draw",
|
||||
title: "App Logs",
|
||||
program: "tail",
|
||||
baseArgs: ["-f", "app.log"],
|
||||
args: ["-f", "app.log"],
|
||||
toggles: [{ id: "verbose", label: "Verbose", args: ["-v"] }],
|
||||
},
|
||||
});
|
||||
|
||||
@@ -395,7 +395,7 @@ function PluginLogEditorBody({ input, data }: { input: EditorInput; data: Plugin
|
||||
op: "pty-spawn",
|
||||
sessionId: "log",
|
||||
program: data.program,
|
||||
args: [...data.baseArgs, ...data.toggles.filter((t) => on.has(t.id)).flatMap((t) => t.args)],
|
||||
args: [...data.args, ...data.toggles.filter((t) => on.has(t.id)).flatMap((t) => t.args)],
|
||||
cols: 240,
|
||||
rows: 40,
|
||||
}),
|
||||
|
||||
@@ -13,7 +13,7 @@ export interface PluginLogEditorData {
|
||||
key?: string;
|
||||
title: string;
|
||||
program: string;
|
||||
baseArgs: string[];
|
||||
args: string[];
|
||||
toggles: PluginLogToggleSpec[];
|
||||
}
|
||||
|
||||
@@ -25,27 +25,28 @@ const args = (v: unknown): v is string[] =>
|
||||
/** Reject malformed requests instead of silently running a different command. */
|
||||
export function logTabData(pluginId: string, view: string, value: object, length: number): PluginLogEditorData {
|
||||
const m = value as Record<string, unknown>;
|
||||
const { program, baseArgs = [], toggles = [], key, title = program } = m;
|
||||
const { program, args: command = [], toggles = [], key, title = program } = m;
|
||||
if (
|
||||
length > 2 << 20 ||
|
||||
!text(program, 256) ||
|
||||
program.trim() !== program ||
|
||||
!text(title, 256) ||
|
||||
(key !== undefined && !text(key, 128)) ||
|
||||
!args(baseArgs) ||
|
||||
!args(command) ||
|
||||
!Array.isArray(toggles) ||
|
||||
toggles.length > 32 ||
|
||||
toggles.some((t) => !t || !text(t.id, 64) || !text(t.label, 128) || !args(t.args)) ||
|
||||
new Set(toggles.map((t) => t.id)).size !== toggles.length ||
|
||||
baseArgs.length + toggles.reduce((n, t) => n + t.args.length, 0) > 256 ||
|
||||
command.length + toggles.reduce((n, t) => n + t.args.length, 0) > 256 ||
|
||||
"cwd" in m ||
|
||||
"env" in m
|
||||
"env" in m ||
|
||||
"baseArgs" in m
|
||||
)
|
||||
throw new Error(tx("Invalid log stream configuration"));
|
||||
const plugin = usePlugins.getState().plugins.find((p) => p.id === pluginId);
|
||||
if (!plugin?.enabled || !plugin.capabilities.some((c) => c.id === `process:${program}` && c.granted))
|
||||
throw new Error(tx`Cannot start PTY: process:${program} capability not granted.`);
|
||||
return { pluginId, view, key: key as string | undefined, title, program, baseArgs, toggles };
|
||||
return { pluginId, view, key: key as string | undefined, title, program, args: command, toggles };
|
||||
}
|
||||
|
||||
/** Bound both line count and text size, including output with no newlines. */
|
||||
|
||||
+8
-1
@@ -1,15 +1,22 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional diagnostics for the current, possibly unsaved document (API 1.3).
|
||||
/// Optional export (world `plugin-diagnostics`): problems in the current,
|
||||
/// possibly unsaved document, for the languages declared with the
|
||||
/// `diagnostics` provider kind. Asked shortly after a document opens or
|
||||
/// changes, under the editor-provider budget; it can't ask the user.
|
||||
interface diagnostics-provider {
|
||||
use diagnostics.{diagnostic};
|
||||
|
||||
/// The document to check (the editor's text, unsaved edits included).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// The document's problems, at most 5,000; they replace what this
|
||||
/// provider reported before, and an empty list removes them.
|
||||
diagnostics: func(doc: document) -> list<diagnostic>;
|
||||
}
|
||||
@@ -1,19 +1,29 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional export (world `plugin-hover`): Markdown added to the hover of
|
||||
/// documents of the languages declared with the `hover` provider kind,
|
||||
/// including languages the plugin doesn't contribute. It shows below the
|
||||
/// language server's hover, under the edit-path budget.
|
||||
interface hover-provider {
|
||||
use types.{position, range};
|
||||
|
||||
/// The document hovered (the editor's text while it is open).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// What the plugin adds to the hover.
|
||||
record hover-content {
|
||||
/// At most 64 KiB.
|
||||
markdown: string,
|
||||
/// The text the hover describes; used when the server names none.
|
||||
range: option<range>,
|
||||
}
|
||||
|
||||
/// The hover at `at`, or `none` to add nothing.
|
||||
hover: func(doc: document, at: position) -> option<hover-content>;
|
||||
}
|
||||
@@ -59,11 +59,13 @@ world plugin-indexing {
|
||||
export document-indexer;
|
||||
}
|
||||
|
||||
/// A plugin with semantic tokens (`semantic-tokens` under `[[contributes.providers]]`).
|
||||
world plugin-semantic-tokens {
|
||||
include plugin;
|
||||
export semantic-tokens-provider;
|
||||
}
|
||||
|
||||
/// A plugin adding to hovers (`hover` under `[[contributes.providers]]`).
|
||||
world plugin-hover {
|
||||
include plugin;
|
||||
export hover-provider;
|
||||
@@ -115,10 +117,12 @@ world indexing {
|
||||
export document-indexer;
|
||||
}
|
||||
|
||||
/// Only the `semantic-tokens-provider` export, generated next to `plugin` like `syntax`.
|
||||
world semantic-tokens {
|
||||
export semantic-tokens-provider;
|
||||
}
|
||||
|
||||
/// Only the `hover-provider` export, generated next to `plugin` like `syntax`.
|
||||
world hover {
|
||||
export hover-provider;
|
||||
}
|
||||
@@ -149,6 +153,7 @@ world plugin-endpoints {
|
||||
export endpoints-provider;
|
||||
}
|
||||
|
||||
/// Only the `endpoints-provider` export, generated next to `plugin` like `syntax`.
|
||||
world endpoints {
|
||||
export endpoints-provider;
|
||||
}
|
||||
|
||||
@@ -1,20 +1,31 @@
|
||||
package openidea:[email protected];
|
||||
|
||||
/// Optional export (world `plugin-semantic-tokens`): semantic colouring of
|
||||
/// documents of the languages declared with the `semantic-tokens` provider
|
||||
/// kind, including languages the plugin doesn't contribute. The tokens join
|
||||
/// the language server's and win where they overlap one.
|
||||
interface semantic-tokens-provider {
|
||||
use types.{range};
|
||||
|
||||
/// The document to colour (the editor's text while it is open).
|
||||
record document {
|
||||
/// Absolute path.
|
||||
path: string,
|
||||
language: string,
|
||||
version: u64,
|
||||
text: string,
|
||||
}
|
||||
|
||||
/// A token: part of one line.
|
||||
record semantic-token {
|
||||
range: range,
|
||||
/// An LSP token type in kebab-case (`method`, `property`, `type`, …).
|
||||
kind: string,
|
||||
/// LSP token modifiers in kebab-case (`static`, `deprecated`, …).
|
||||
modifiers: list<string>,
|
||||
}
|
||||
|
||||
/// The document's tokens, at most 65,536; asked again after each edit,
|
||||
/// under the edit-path budget.
|
||||
semantic-tokens: func(doc: document) -> list<semantic-token>;
|
||||
}
|
||||
+10
-11
@@ -39,17 +39,6 @@ interface workspace {
|
||||
location: location,
|
||||
}
|
||||
|
||||
/// Fuzzy symbol search (CamelHump and container-qualified queries) over the
|
||||
/// current index only; never starts or waits for a language server. Results
|
||||
/// may be incomplete while indexing and ranges reflect the indexed text,
|
||||
/// not necessarily unsaved edits. Empty queries return no symbols. Queries
|
||||
/// over 256 UTF-8 bytes are invalid; limit is capped at 1000 (zero is empty).
|
||||
/// Only paths readable under this project's root are returned; external
|
||||
/// content roots are excluded. Cancellation returns cancelled; exceeding the
|
||||
/// current call's deadline fails. A closed project is not-found.
|
||||
/// Requires `project.read`. New in 1.3.
|
||||
symbols: func(project: borrow<project>, query: string, limit: u32) -> result<list<symbol-info>, error>;
|
||||
|
||||
/// A project open in the IDE.
|
||||
resource project {
|
||||
/// Absolute path of the project root. Requires `project.read`.
|
||||
@@ -80,6 +69,16 @@ interface workspace {
|
||||
/// 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>;
|
||||
/// Fuzzy symbol search (CamelHump and container-qualified queries) over the
|
||||
/// current index only; never starts or waits for a language server. Results
|
||||
/// may be incomplete while indexing and ranges reflect the indexed text,
|
||||
/// not necessarily unsaved edits. Empty queries return no symbols. Queries
|
||||
/// over 256 UTF-8 bytes are invalid; limit is capped at 1000 (zero is
|
||||
/// empty). Only paths readable under the root are returned; external
|
||||
/// content roots are excluded. Cancellation returns cancelled; exceeding
|
||||
/// the current call's deadline fails. A closed project is not-found.
|
||||
/// Requires `project.read`.
|
||||
symbols: func(query: string, limit: u32) -> result<list<symbol-info>, error>;
|
||||
}
|
||||
|
||||
/// Projects open in any window. Requires `project.read`.
|
||||
|
||||
Reference in new issue
Block a user