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) }); }}
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)
});
}
}