extension_context_server.rs

 1use std::sync::Arc;
 2
 3use extension::{Extension, ExtensionContextServerProxy, ExtensionHostProxy, ProjectDelegate};
 4use gpui::{App, Entity};
 5
 6use crate::{ContextServerFactoryRegistry, ServerCommand};
 7
 8struct ExtensionProject {
 9    worktree_ids: Vec<u64>,
10}
11
12impl ProjectDelegate for ExtensionProject {
13    fn worktree_ids(&self) -> Vec<u64> {
14        self.worktree_ids.clone()
15    }
16}
17
18pub fn init(cx: &mut App) {
19    let proxy = ExtensionHostProxy::default_global(cx);
20    proxy.register_context_server_proxy(ContextServerFactoryRegistryProxy {
21        context_server_factory_registry: ContextServerFactoryRegistry::global(cx),
22    });
23}
24
25struct ContextServerFactoryRegistryProxy {
26    context_server_factory_registry: Entity<ContextServerFactoryRegistry>,
27}
28
29impl ExtensionContextServerProxy for ContextServerFactoryRegistryProxy {
30    fn register_context_server(&self, extension: Arc<dyn Extension>, id: Arc<str>, cx: &mut App) {
31        self.context_server_factory_registry
32            .update(cx, |registry, _| {
33                registry.register_server_factory(
34                    id.clone(),
35                    Arc::new({
36                        move |project, cx| {
37                            log::info!(
38                                "loading command for context server {id} from extension {}",
39                                extension.manifest().id
40                            );
41
42                            let id = id.clone();
43                            let extension = extension.clone();
44                            cx.spawn(async move |cx| {
45                                let extension_project = project.update(cx, |project, cx| {
46                                    Arc::new(ExtensionProject {
47                                        worktree_ids: project
48                                            .visible_worktrees(cx)
49                                            .map(|worktree| worktree.read(cx).id().to_proto())
50                                            .collect(),
51                                    })
52                                })?;
53
54                                let mut command = extension
55                                    .context_server_command(id.clone(), extension_project)
56                                    .await?;
57                                command.command = extension
58                                    .path_from_extension(command.command.as_ref())
59                                    .to_string_lossy()
60                                    .to_string();
61
62                                log::info!("loaded command for context server {id}: {command:?}");
63
64                                Ok(ServerCommand {
65                                    path: command.command,
66                                    args: command.args,
67                                    env: Some(command.env.into_iter().collect()),
68                                })
69                            })
70                        }
71                    }),
72                )
73            });
74    }
75}