ssh remoting: Do not double-register LspAdapters (#18132)
This fixes the bug with hover tooltips appearing multiple times. Turns out everytime we receive the `CreateLanguageServer` message we'd add a new adapter but only have a single server running for all of them. And we send a `CreateLanguageServer` message everytime you open a buffer. What this does is to only add a new adapter if it hasn't already been registered, which is also what we do locally. Release Notes: - N/A
This commit is contained in:
parent
ca033e6475
commit
90a12f5564
2 changed files with 54 additions and 24 deletions
|
@ -326,13 +326,43 @@ impl LanguageRegistry {
|
||||||
Some(load_lsp_adapter())
|
Some(load_lsp_adapter())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn register_lsp_adapter(&self, language_name: LanguageName, adapter: Arc<dyn LspAdapter>) {
|
pub fn register_lsp_adapter(
|
||||||
|
&self,
|
||||||
|
language_name: LanguageName,
|
||||||
|
adapter: Arc<dyn LspAdapter>,
|
||||||
|
) -> Arc<CachedLspAdapter> {
|
||||||
|
let cached = CachedLspAdapter::new(adapter);
|
||||||
self.state
|
self.state
|
||||||
.write()
|
.write()
|
||||||
.lsp_adapters
|
.lsp_adapters
|
||||||
.entry(language_name)
|
.entry(language_name)
|
||||||
.or_default()
|
.or_default()
|
||||||
.push(CachedLspAdapter::new(adapter));
|
.push(cached.clone());
|
||||||
|
cached
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_or_register_lsp_adapter(
|
||||||
|
&self,
|
||||||
|
language_name: LanguageName,
|
||||||
|
server_name: LanguageServerName,
|
||||||
|
build_adapter: impl FnOnce() -> Arc<dyn LspAdapter> + 'static,
|
||||||
|
) -> Arc<CachedLspAdapter> {
|
||||||
|
let registered = self
|
||||||
|
.state
|
||||||
|
.write()
|
||||||
|
.lsp_adapters
|
||||||
|
.entry(language_name.clone())
|
||||||
|
.or_default()
|
||||||
|
.iter()
|
||||||
|
.find(|cached_adapter| cached_adapter.name == server_name)
|
||||||
|
.cloned();
|
||||||
|
|
||||||
|
if let Some(found) = registered {
|
||||||
|
found
|
||||||
|
} else {
|
||||||
|
let adapter = build_adapter();
|
||||||
|
self.register_lsp_adapter(language_name, adapter)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Register a fake language server and adapter
|
/// Register a fake language server and adapter
|
||||||
|
|
|
@ -4475,7 +4475,7 @@ impl LspStore {
|
||||||
mut cx: AsyncAppContext,
|
mut cx: AsyncAppContext,
|
||||||
) -> Result<proto::Ack> {
|
) -> Result<proto::Ack> {
|
||||||
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
let worktree_id = WorktreeId::from_proto(envelope.payload.worktree_id);
|
||||||
let name = LanguageServerName::from_proto(envelope.payload.name);
|
let server_name = LanguageServerName::from_proto(envelope.payload.name);
|
||||||
|
|
||||||
let binary = envelope
|
let binary = envelope
|
||||||
.payload
|
.payload
|
||||||
|
@ -4494,6 +4494,14 @@ impl LspStore {
|
||||||
let matcher: LanguageMatcher = serde_json::from_str(&language.matcher)?;
|
let matcher: LanguageMatcher = serde_json::from_str(&language.matcher)?;
|
||||||
|
|
||||||
this.update(&mut cx, |this, cx| {
|
this.update(&mut cx, |this, cx| {
|
||||||
|
let Some(worktree) = this
|
||||||
|
.worktree_store
|
||||||
|
.read(cx)
|
||||||
|
.worktree_for_id(worktree_id, cx)
|
||||||
|
else {
|
||||||
|
return Err(anyhow!("worktree not found"));
|
||||||
|
};
|
||||||
|
|
||||||
this.languages
|
this.languages
|
||||||
.register_language(language_name.clone(), None, matcher.clone(), {
|
.register_language(language_name.clone(), None, matcher.clone(), {
|
||||||
let language_name = language_name.clone();
|
let language_name = language_name.clone();
|
||||||
|
@ -4513,28 +4521,20 @@ impl LspStore {
|
||||||
.spawn(this.languages.language_for_name(language_name.0.as_ref()))
|
.spawn(this.languages.language_for_name(language_name.0.as_ref()))
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
let adapter = Arc::new(SshLspAdapter::new(
|
let adapter = this.languages.get_or_register_lsp_adapter(
|
||||||
name,
|
language_name.clone(),
|
||||||
binary,
|
server_name.clone(),
|
||||||
envelope.payload.initialization_options,
|
|| {
|
||||||
envelope.payload.code_action_kinds,
|
Arc::new(SshLspAdapter::new(
|
||||||
));
|
server_name,
|
||||||
|
binary,
|
||||||
this.languages
|
envelope.payload.initialization_options,
|
||||||
.register_lsp_adapter(language_name.clone(), adapter.clone());
|
envelope.payload.code_action_kinds,
|
||||||
let Some(worktree) = this
|
))
|
||||||
.worktree_store
|
},
|
||||||
.read(cx)
|
|
||||||
.worktree_for_id(worktree_id, cx)
|
|
||||||
else {
|
|
||||||
return Err(anyhow!("worktree not found"));
|
|
||||||
};
|
|
||||||
this.start_language_server(
|
|
||||||
&worktree,
|
|
||||||
CachedLspAdapter::new(adapter),
|
|
||||||
language_name,
|
|
||||||
cx,
|
|
||||||
);
|
);
|
||||||
|
|
||||||
|
this.start_language_server(&worktree, adapter, language_name, cx);
|
||||||
Ok(())
|
Ok(())
|
||||||
})??;
|
})??;
|
||||||
Ok(proto::Ack {})
|
Ok(proto::Ack {})
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue