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:
parent
01bb10f518
commit
e66ea9e5d4
34 changed files with 505 additions and 329 deletions
|
@ -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);
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue