Expose context server settings to extensions (#20555)

This PR exposes context server settings to extensions.

Extensions can use `ContextServerSettings::for_project` to get the
context server settings for the current project.

The `experimental.context_servers` setting has been removed and replaced
with the `context_servers` setting (which is now an object instead of an
array).

Release Notes:

- N/A

---------

Co-authored-by: Max Brunsfeld <maxbrunsfeld@gmail.com>
This commit is contained in:
Marshall Bowers 2024-11-12 17:21:58 -05:00 committed by GitHub
parent 0a9c78a58d
commit 3ebb64ea1d
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
17 changed files with 243 additions and 126 deletions

View file

@ -22,6 +22,7 @@ async-tar.workspace = true
async-trait.workspace = true
client.workspace = true
collections.workspace = true
context_servers.workspace = true
extension.workspace = true
fs.workspace = true
futures.workspace = true

View file

@ -27,7 +27,7 @@ use wasmtime::{
};
use wasmtime_wasi as wasi;
use wit::Extension;
pub use wit::SlashCommand;
pub use wit::{ExtensionProject, SlashCommand};
pub struct WasmHost {
engine: Engine,

View file

@ -4,7 +4,6 @@ mod since_v0_0_6;
mod since_v0_1_0;
mod since_v0_2_0;
use lsp::LanguageServerName;
// use indexed_docs::IndexedDocsDatabase;
use release_channel::ReleaseChannel;
use since_v0_2_0 as latest;
@ -27,7 +26,7 @@ pub use latest::{
Completion, CompletionKind, CompletionLabelDetails, InsertTextFormat, Symbol, SymbolKind,
},
zed::extension::slash_command::{SlashCommandArgumentCompletion, SlashCommandOutput},
CodeLabel, CodeLabelSpan, Command, Range, SlashCommand,
CodeLabel, CodeLabelSpan, Command, ExtensionProject, Range, SlashCommand,
};
pub use since_v0_0_4::LanguageServerConfig;
@ -389,10 +388,11 @@ impl Extension {
&self,
store: &mut Store<WasmState>,
context_server_id: Arc<str>,
project: Resource<ExtensionProject>,
) -> Result<Result<Command, String>> {
match self {
Extension::V020(ext) => {
ext.call_context_server_command(store, &context_server_id)
ext.call_context_server_command(store, &context_server_id, project)
.await
}
Extension::V001(_) | Extension::V004(_) | Extension::V006(_) | Extension::V010(_) => {

View file

@ -6,6 +6,7 @@ use anyhow::{anyhow, bail, Context, Result};
use async_compression::futures::bufread::GzipDecoder;
use async_tar::Archive;
use async_trait::async_trait;
use context_servers::manager::ContextServerSettings;
use futures::{io::BufReader, FutureExt as _};
use futures::{lock::Mutex, AsyncReadExt};
use language::{
@ -31,6 +32,7 @@ wasmtime::component::bindgen!({
path: "../extension_api/wit/since_v0.2.0",
with: {
"worktree": ExtensionWorktree,
"project": ExtensionProject,
"key-value-store": ExtensionKeyValueStore,
"zed:extension/http-client/http-response-stream": ExtensionHttpResponseStream
},
@ -46,6 +48,10 @@ pub type ExtensionWorktree = Arc<dyn LspAdapterDelegate>;
pub type ExtensionKeyValueStore = Arc<dyn DocsDatabase>;
pub type ExtensionHttpResponseStream = Arc<Mutex<::http_client::Response<AsyncBody>>>;
pub struct ExtensionProject {
pub worktree_ids: Vec<u64>,
}
pub fn linker() -> &'static Linker<WasmState> {
static LINKER: OnceLock<Linker<WasmState>> = OnceLock::new();
LINKER.get_or_init(|| super::new_linker(Extension::add_to_linker))
@ -69,6 +75,22 @@ impl HostKeyValueStore for WasmState {
}
}
#[async_trait]
impl HostProject for WasmState {
async fn worktree_ids(
&mut self,
project: Resource<ExtensionProject>,
) -> wasmtime::Result<Vec<u64>> {
let project = self.table.get(&project)?;
Ok(project.worktree_ids.clone())
}
fn drop(&mut self, _project: Resource<Project>) -> Result<()> {
// We only ever hand out borrows of projects.
Ok(())
}
}
#[async_trait]
impl HostWorktree for WasmState {
async fn id(
@ -421,14 +443,33 @@ impl ExtensionImports for WasmState {
.cloned()
.unwrap_or_default();
Ok(serde_json::to_string(&settings::LspSettings {
binary: settings.binary.map(|binary| settings::BinarySettings {
binary: settings.binary.map(|binary| settings::CommandSettings {
path: binary.path,
arguments: binary.arguments,
env: None,
}),
settings: settings.settings,
initialization_options: settings.initialization_options,
})?)
}
"context_servers" => {
let settings = key
.and_then(|key| {
ContextServerSettings::get(location, cx)
.context_servers
.get(key.as_str())
})
.cloned()
.unwrap_or_default();
Ok(serde_json::to_string(&settings::ContextServerSettings {
command: settings.command.map(|command| settings::CommandSettings {
path: Some(command.path),
arguments: Some(command.args),
env: command.env.map(|env| env.into_iter().collect()),
}),
settings: settings.settings,
})?)
}
_ => {
bail!("Unknown settings category: {}", category);
}