120 lines · 3.8 KB · Rust
RawDownload
use std::sync::Arc; use anyhow::Result;use context_server::ContextServerCommand;use extension::{    ContextServerConfiguration, Extension, ExtensionContextServerProxy, ExtensionHostProxy,    ProjectDelegate,};use gpui::{App, AsyncApp, Entity, Task}; use crate::worktree_store::WorktreeStore; use super::registry::{self, ContextServerDescriptorRegistry}; pub fn init(cx: &mut App) {    let proxy = ExtensionHostProxy::default_global(cx);    proxy.register_context_server_proxy(ContextServerDescriptorRegistryProxy {        context_server_factory_registry: ContextServerDescriptorRegistry::default_global(cx),    });} struct ExtensionProject {    worktree_ids: Vec<u64>,} impl ProjectDelegate for ExtensionProject {    fn worktree_ids(&self) -> Vec<u64> {        self.worktree_ids.clone()    }} struct ContextServerDescriptor {    id: Arc<str>,    extension: Arc<dyn Extension>,} fn extension_project(    worktree_store: Entity<WorktreeStore>,    cx: &mut AsyncApp,) -> Result<Arc<ExtensionProject>> {    Ok(worktree_store.update(cx, |worktree_store, cx| {        Arc::new(ExtensionProject {            worktree_ids: worktree_store                .visible_worktrees(cx)                .map(|worktree| worktree.read(cx).id().to_proto())                .collect(),        })    }))} impl registry::ContextServerDescriptor for ContextServerDescriptor {    fn command(        &self,        worktree_store: Entity<WorktreeStore>,        cx: &AsyncApp,    ) -> Task<Result<ContextServerCommand>> {        let id = self.id.clone();        let extension = self.extension.clone();        cx.spawn(async move |cx| {            let extension_project = extension_project(worktree_store, cx)?;            let mut command = extension                .context_server_command(id.clone(), extension_project.clone())                .await?;            command.command = extension.path_from_extension(&command.command);             log::debug!("loaded command for context server {id}: {command:?}");             Ok(ContextServerCommand {                path: command.command,                args: command.args,                env: Some(command.env.into_iter().collect()),                timeout: None,            })        })    }     fn configuration(        &self,        worktree_store: Entity<WorktreeStore>,        cx: &AsyncApp,    ) -> Task<Result<Option<ContextServerConfiguration>>> {        let id = self.id.clone();        let extension = self.extension.clone();        cx.spawn(async move |cx| {            let extension_project = extension_project(worktree_store, cx)?;            let configuration = extension                .context_server_configuration(id.clone(), extension_project)                .await?;             log::debug!("loaded configuration for context server {id}: {configuration:?}");             Ok(configuration)        })    }} struct ContextServerDescriptorRegistryProxy {    context_server_factory_registry: Entity<ContextServerDescriptorRegistry>,} impl ExtensionContextServerProxy for ContextServerDescriptorRegistryProxy {    fn register_context_server(&self, extension: Arc<dyn Extension>, id: Arc<str>, cx: &mut App) {        self.context_server_factory_registry            .update(cx, |registry, cx| {                registry.register_context_server_descriptor(                    id.clone(),                    Arc::new(ContextServerDescriptor { id, extension })                        as Arc<dyn registry::ContextServerDescriptor>,                    cx,                )            });    }     fn unregister_context_server(&self, server_id: Arc<str>, cx: &mut App) {        self.context_server_factory_registry            .update(cx, |registry, cx| {                registry.unregister_context_server_descriptor_by_id(&server_id, cx)            });    }}