Fix renames over language server for SSH remoting (#17897)

Release Notes:

- ssh remoting: Fix rename over language server

---------

Co-authored-by: Mikayla <mikayla@zed.dev>
Co-authored-by: Max <max@zed.dev>
This commit is contained in:
Conrad Irwin 2024-09-16 16:20:17 -06:00 committed by GitHub
parent 01bb10f518
commit e66ea9e5d4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
34 changed files with 505 additions and 329 deletions

View file

@ -99,10 +99,15 @@ struct LanguageRegistryState {
reload_count: usize,
#[cfg(any(test, feature = "test-support"))]
fake_server_txs: HashMap<
LanguageName,
Vec<futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>>,
>,
fake_server_entries: HashMap<LanguageServerName, FakeLanguageServerEntry>,
}
#[cfg(any(test, feature = "test-support"))]
pub struct FakeLanguageServerEntry {
pub capabilities: lsp::ServerCapabilities,
pub initializer: Option<Box<dyn 'static + Send + Sync + Fn(&mut lsp::FakeLanguageServer)>>,
pub tx: futures::channel::mpsc::UnboundedSender<lsp::FakeLanguageServer>,
pub _server: Option<lsp::FakeLanguageServer>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
@ -220,7 +225,7 @@ impl LanguageRegistry {
reload_count: 0,
#[cfg(any(test, feature = "test-support"))]
fake_server_txs: Default::default(),
fake_server_entries: Default::default(),
}),
language_server_download_dir: None,
lsp_binary_status_tx: Default::default(),
@ -330,12 +335,35 @@ impl LanguageRegistry {
.push(CachedLspAdapter::new(adapter));
}
/// Register a fake language server and adapter
/// The returned channel receives a new instance of the language server every time it is started
#[cfg(any(feature = "test-support", test))]
pub fn register_fake_lsp(
&self,
language_name: impl Into<LanguageName>,
mut adapter: crate::FakeLspAdapter,
) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
let language_name = language_name.into();
let adapter_name = LanguageServerName(adapter.name.into());
let capabilities = adapter.capabilities.clone();
let initializer = adapter.initializer.take();
self.state
.write()
.lsp_adapters
.entry(language_name.clone())
.or_default()
.push(CachedLspAdapter::new(Arc::new(adapter)));
self.register_fake_language_server(adapter_name, capabilities, initializer)
}
/// Register a fake lsp adapter (without the language server)
/// The returned channel receives a new instance of the language server every time it is started
#[cfg(any(feature = "test-support", test))]
pub fn register_fake_lsp_adapter(
&self,
language_name: impl Into<LanguageName>,
adapter: crate::FakeLspAdapter,
) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
) {
let language_name = language_name.into();
self.state
.write()
@ -343,21 +371,27 @@ impl LanguageRegistry {
.entry(language_name.clone())
.or_default()
.push(CachedLspAdapter::new(Arc::new(adapter)));
self.fake_language_servers(language_name)
}
/// Register a fake language server (without the adapter)
/// The returned channel receives a new instance of the language server every time it is started
#[cfg(any(feature = "test-support", test))]
pub fn fake_language_servers(
pub fn register_fake_language_server(
&self,
language_name: LanguageName,
lsp_name: LanguageServerName,
capabilities: lsp::ServerCapabilities,
initializer: Option<Box<dyn Fn(&mut lsp::FakeLanguageServer) + Send + Sync>>,
) -> futures::channel::mpsc::UnboundedReceiver<lsp::FakeLanguageServer> {
let (servers_tx, servers_rx) = futures::channel::mpsc::unbounded();
self.state
.write()
.fake_server_txs
.entry(language_name)
.or_default()
.push(servers_tx);
self.state.write().fake_server_entries.insert(
lsp_name,
FakeLanguageServerEntry {
tx: servers_tx,
capabilities,
initializer,
_server: None,
},
);
servers_rx
}
@ -835,8 +869,8 @@ impl LanguageRegistry {
adapter.name.0
);
let download_dir = self
.language_server_download_dir
let download_dir = &self
.language_server_download_dir
.clone()
.ok_or_else(|| anyhow!("language server download directory has not been assigned before starting server"))
.log_err()?;
@ -877,52 +911,43 @@ impl LanguageRegistry {
#[cfg(any(test, feature = "test-support"))]
if true {
let capabilities = adapter
.as_fake()
.map(|fake_adapter| fake_adapter.capabilities.clone())
.unwrap_or_else(|| lsp::ServerCapabilities {
completion_provider: Some(Default::default()),
..Default::default()
});
if let Some(this) = this.upgrade() {
if let Some(fake_entry) = this
.state
.write()
.fake_server_entries
.get_mut(&adapter.name)
{
let (server, mut fake_server) = lsp::FakeLanguageServer::new(
server_id,
binary,
adapter.name.0.to_string(),
fake_entry.capabilities.clone(),
cx.clone(),
);
fake_entry._server = Some(fake_server.clone());
let (server, mut fake_server) = lsp::FakeLanguageServer::new(
server_id,
binary,
adapter.name.0.to_string(),
capabilities,
cx.clone(),
);
if let Some(initializer) = &fake_entry.initializer {
initializer(&mut fake_server);
}
if let Some(fake_adapter) = adapter.as_fake() {
if let Some(initializer) = &fake_adapter.initializer {
initializer(&mut fake_server);
let tx = fake_entry.tx.clone();
cx.background_executor()
.spawn(async move {
if fake_server
.try_receive_notification::<lsp::notification::Initialized>(
)
.await
.is_some()
{
tx.unbounded_send(fake_server.clone()).ok();
}
})
.detach();
return Ok((server, options));
}
}
cx.background_executor()
.spawn(async move {
if fake_server
.try_receive_notification::<lsp::notification::Initialized>()
.await
.is_some()
{
if let Some(this) = this.upgrade() {
if let Some(txs) = this
.state
.write()
.fake_server_txs
.get_mut(&_language_name_for_tests)
{
for tx in txs {
tx.unbounded_send(fake_server.clone()).ok();
}
}
}
}
})
.detach();
return Ok((server, options));
}
drop(this);