extension: Define capabilities in the extension manifest (#16953)

This PR adds an initial notion of extension capabilities.

Capabilities are used to express the operations an extension is capable
of doing. This will provide further insights into what an extension can
do, as well as provide the ability to grant or deny the set of
capabilities.

Capabilities are defined in the `capabilities` field in the extension
manifest. This field contains an array of capabilities.

Each capability has a `kind` to denote the known capability it
corresponds to. Individual capabilities may have additional fields,
based on the `kind`.

Here's an example of some capabilities:

```toml
capabilities = [
    { kind = "download-file", host = "github.com", path_prefix = "owner/repo" },
    { kind = "npm:install", package = "@vue/language-server" },
]
```

In order to avoid a breaking change, the `capabilities` field is
currently optional and defaults to an empty array. This will allow us to
add support for extensions to define capabilities before we start
enforcing them.

Release Notes:

- N/A
This commit is contained in:
Marshall Bowers 2024-08-27 11:10:58 -04:00 committed by GitHub
parent ad43bbbf5e
commit 8ec36f1e2b
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 32 additions and 0 deletions

View file

@ -64,6 +64,8 @@ pub struct ExtensionManifest {
#[serde(default)]
pub authors: Vec<String>,
#[serde(default)]
pub capabilities: Vec<ExtensionCapability>,
#[serde(default)]
pub lib: LibManifestEntry,
#[serde(default)]
@ -82,6 +84,28 @@ pub struct ExtensionManifest {
pub snippets: Option<PathBuf>,
}
/// A capability for an extension.
#[derive(Debug, PartialEq, Eq, Clone, Serialize, Deserialize)]
#[serde(tag = "kind")]
pub enum ExtensionCapability {
/// The capability to download a file from a server.
#[serde(rename = "download-file")]
DownloadFile {
/// The host name of the server from which the file will be downloaded (e.g., `github.com`).
host: String,
/// The path prefix to the file that will be downloaded.
///
/// Any path that starts with this prefix will be allowed.
path_prefix: String,
},
/// The capability to install a package from npm.
#[serde(rename = "npm:install")]
NpmInstall {
/// The name of the package.
package: String,
},
}
#[derive(Clone, Default, PartialEq, Eq, Debug, Deserialize, Serialize)]
pub struct LibManifestEntry {
pub kind: Option<ExtensionLibraryKind>,
@ -186,6 +210,7 @@ fn manifest_from_old_manifest(
repository: manifest_json.repository,
authors: manifest_json.authors,
schema_version: SchemaVersion::ZERO,
capabilities: Vec::new(),
lib: Default::default(),
themes: {
let mut themes = manifest_json.themes.into_values().collect::<Vec<_>>();

View file

@ -150,6 +150,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
authors: Vec::new(),
repository: None,
themes: Default::default(),
capabilities: Vec::new(),
lib: Default::default(),
languages: vec!["languages/erb".into(), "languages/ruby".into()],
grammars: [
@ -181,6 +182,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
"themes/monokai-pro.json".into(),
"themes/monokai.json".into(),
],
capabilities: Vec::new(),
lib: Default::default(),
languages: Default::default(),
grammars: BTreeMap::default(),
@ -344,6 +346,7 @@ async fn test_extension_store(cx: &mut TestAppContext) {
authors: vec![],
repository: None,
themes: vec!["themes/gruvbox.json".into()],
capabilities: Vec::new(),
lib: Default::default(),
languages: Default::default(),
grammars: BTreeMap::default(),

View file

@ -6,6 +6,10 @@ schema_version = 1
authors = ["Marshall Bowers <elliott.codes@gmail.com>"]
repository = "https://github.com/zed-industries/zed"
capabilities = [
{ kind = "download-file", host = "github.com", path_prefix = "gleam-lang/gleam" },
]
[language_servers.gleam]
name = "Gleam LSP"
language = "Gleam"