Use new language server info on remote servers (#35682)
* Straightens out the `*_ext.rs` workflow for clangd and rust-analyzer: no need to asynchronously query for the language server, as we sync that information already. * Fixes inlay hints editor menu toggle not being shown in the remote sessions Release Notes: - Fixed inlay hints editor menu toggle not being shown in the remote sessions
This commit is contained in:
parent
cc93175256
commit
9caa9d042a
14 changed files with 176 additions and 291 deletions
|
@ -3284,6 +3284,16 @@ impl InlayHints {
|
|||
})
|
||||
.unwrap_or(false)
|
||||
}
|
||||
|
||||
pub fn check_capabilities(capabilities: &ServerCapabilities) -> bool {
|
||||
capabilities
|
||||
.inlay_hint_provider
|
||||
.as_ref()
|
||||
.is_some_and(|inlay_hint_provider| match inlay_hint_provider {
|
||||
lsp::OneOf::Left(enabled) => *enabled,
|
||||
lsp::OneOf::Right(_) => true,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait(?Send)]
|
||||
|
@ -3297,17 +3307,7 @@ impl LspCommand for InlayHints {
|
|||
}
|
||||
|
||||
fn check_capabilities(&self, capabilities: AdapterServerCapabilities) -> bool {
|
||||
let Some(inlay_hint_provider) = &capabilities.server_capabilities.inlay_hint_provider
|
||||
else {
|
||||
return false;
|
||||
};
|
||||
match inlay_hint_provider {
|
||||
lsp::OneOf::Left(enabled) => *enabled,
|
||||
lsp::OneOf::Right(inlay_hint_capabilities) => match inlay_hint_capabilities {
|
||||
lsp::InlayHintServerCapabilities::Options(_) => true,
|
||||
lsp::InlayHintServerCapabilities::RegistrationOptions(_) => false,
|
||||
},
|
||||
}
|
||||
Self::check_capabilities(&capabilities.server_capabilities)
|
||||
}
|
||||
|
||||
fn to_lsp(
|
||||
|
|
|
@ -3671,7 +3671,6 @@ impl LspStore {
|
|||
client.add_entity_request_handler(Self::handle_apply_additional_edits_for_completion);
|
||||
client.add_entity_request_handler(Self::handle_register_buffer_with_language_servers);
|
||||
client.add_entity_request_handler(Self::handle_rename_project_entry);
|
||||
client.add_entity_request_handler(Self::handle_language_server_id_for_name);
|
||||
client.add_entity_request_handler(Self::handle_pull_workspace_diagnostics);
|
||||
client.add_entity_request_handler(Self::handle_lsp_command::<GetCodeActions>);
|
||||
client.add_entity_request_handler(Self::handle_lsp_command::<GetCompletions>);
|
||||
|
@ -8745,34 +8744,6 @@ impl LspStore {
|
|||
Ok(proto::Ack {})
|
||||
}
|
||||
|
||||
async fn handle_language_server_id_for_name(
|
||||
lsp_store: Entity<Self>,
|
||||
envelope: TypedEnvelope<proto::LanguageServerIdForName>,
|
||||
mut cx: AsyncApp,
|
||||
) -> Result<proto::LanguageServerIdForNameResponse> {
|
||||
let name = &envelope.payload.name;
|
||||
let buffer_id = BufferId::new(envelope.payload.buffer_id)?;
|
||||
lsp_store
|
||||
.update(&mut cx, |lsp_store, cx| {
|
||||
let buffer = lsp_store.buffer_store.read(cx).get_existing(buffer_id)?;
|
||||
let server_id = buffer.update(cx, |buffer, cx| {
|
||||
lsp_store
|
||||
.language_servers_for_local_buffer(buffer, cx)
|
||||
.find_map(|(adapter, server)| {
|
||||
if adapter.name.0.as_ref() == name {
|
||||
Some(server.server_id())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
});
|
||||
Ok(server_id)
|
||||
})?
|
||||
.map(|server_id| proto::LanguageServerIdForNameResponse {
|
||||
server_id: server_id.map(|id| id.to_proto()),
|
||||
})
|
||||
}
|
||||
|
||||
async fn handle_rename_project_entry(
|
||||
this: Entity<Self>,
|
||||
envelope: TypedEnvelope<proto::RenameProjectEntry>,
|
||||
|
|
|
@ -3,12 +3,12 @@ use std::sync::Arc;
|
|||
use ::serde::{Deserialize, Serialize};
|
||||
use gpui::WeakEntity;
|
||||
use language::{CachedLspAdapter, Diagnostic, DiagnosticSourceKind};
|
||||
use lsp::LanguageServer;
|
||||
use lsp::{LanguageServer, LanguageServerName};
|
||||
use util::ResultExt as _;
|
||||
|
||||
use crate::LspStore;
|
||||
|
||||
pub const CLANGD_SERVER_NAME: &str = "clangd";
|
||||
pub const CLANGD_SERVER_NAME: LanguageServerName = LanguageServerName::new_static("clangd");
|
||||
const INACTIVE_REGION_MESSAGE: &str = "inactive region";
|
||||
const INACTIVE_DIAGNOSTIC_SEVERITY: lsp::DiagnosticSeverity = lsp::DiagnosticSeverity::INFORMATION;
|
||||
|
||||
|
@ -34,7 +34,7 @@ pub fn is_inactive_region(diag: &Diagnostic) -> bool {
|
|||
&& diag
|
||||
.source
|
||||
.as_ref()
|
||||
.is_some_and(|v| v == CLANGD_SERVER_NAME)
|
||||
.is_some_and(|v| v == &CLANGD_SERVER_NAME.0)
|
||||
}
|
||||
|
||||
pub fn is_lsp_inactive_region(diag: &lsp::Diagnostic) -> bool {
|
||||
|
@ -43,7 +43,7 @@ pub fn is_lsp_inactive_region(diag: &lsp::Diagnostic) -> bool {
|
|||
&& diag
|
||||
.source
|
||||
.as_ref()
|
||||
.is_some_and(|v| v == CLANGD_SERVER_NAME)
|
||||
.is_some_and(|v| v == &CLANGD_SERVER_NAME.0)
|
||||
}
|
||||
|
||||
pub fn register_notifications(
|
||||
|
@ -51,7 +51,7 @@ pub fn register_notifications(
|
|||
language_server: &LanguageServer,
|
||||
adapter: Arc<CachedLspAdapter>,
|
||||
) {
|
||||
if language_server.name().0 != CLANGD_SERVER_NAME {
|
||||
if language_server.name() != CLANGD_SERVER_NAME {
|
||||
return;
|
||||
}
|
||||
let server_id = language_server.server_id();
|
||||
|
|
|
@ -2,12 +2,12 @@ use ::serde::{Deserialize, Serialize};
|
|||
use anyhow::Context as _;
|
||||
use gpui::{App, Entity, Task, WeakEntity};
|
||||
use language::ServerHealth;
|
||||
use lsp::LanguageServer;
|
||||
use lsp::{LanguageServer, LanguageServerName};
|
||||
use rpc::proto;
|
||||
|
||||
use crate::{LspStore, LspStoreEvent, Project, ProjectPath, lsp_store};
|
||||
|
||||
pub const RUST_ANALYZER_NAME: &str = "rust-analyzer";
|
||||
pub const RUST_ANALYZER_NAME: LanguageServerName = LanguageServerName::new_static("rust-analyzer");
|
||||
pub const CARGO_DIAGNOSTICS_SOURCE_NAME: &str = "rustc";
|
||||
|
||||
/// Experimental: Informs the end user about the state of the server
|
||||
|
@ -97,13 +97,9 @@ pub fn cancel_flycheck(
|
|||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
let Some(rust_analyzer_server) = project.read_with(cx, |project, cx| {
|
||||
project.language_server_id_for_name(buffer.read(cx), &RUST_ANALYZER_NAME, cx)
|
||||
})?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -148,13 +144,9 @@ pub fn run_flycheck(
|
|||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
let Some(rust_analyzer_server) = project.read_with(cx, |project, cx| {
|
||||
project.language_server_id_for_name(buffer.read(cx), &RUST_ANALYZER_NAME, cx)
|
||||
})?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
@ -204,13 +196,9 @@ pub fn clear_flycheck(
|
|||
|
||||
cx.spawn(async move |cx| {
|
||||
let buffer = buffer.await?;
|
||||
let Some(rust_analyzer_server) = project
|
||||
.update(cx, |project, cx| {
|
||||
buffer.update(cx, |buffer, cx| {
|
||||
project.language_server_id_for_name(buffer, RUST_ANALYZER_NAME, cx)
|
||||
})
|
||||
})?
|
||||
.await
|
||||
let Some(rust_analyzer_server) = project.read_with(cx, |project, cx| {
|
||||
project.language_server_id_for_name(buffer.read(cx), &RUST_ANALYZER_NAME, cx)
|
||||
})?
|
||||
else {
|
||||
return Ok(());
|
||||
};
|
||||
|
|
|
@ -5002,63 +5002,53 @@ impl Project {
|
|||
}
|
||||
|
||||
pub fn any_language_server_supports_inlay_hints(&self, buffer: &Buffer, cx: &mut App) -> bool {
|
||||
self.lsp_store.update(cx, |this, cx| {
|
||||
this.language_servers_for_local_buffer(buffer, cx)
|
||||
.any(
|
||||
|(_, server)| match server.capabilities().inlay_hint_provider {
|
||||
Some(lsp::OneOf::Left(enabled)) => enabled,
|
||||
Some(lsp::OneOf::Right(_)) => true,
|
||||
None => false,
|
||||
},
|
||||
)
|
||||
let Some(language) = buffer.language().cloned() else {
|
||||
return false;
|
||||
};
|
||||
self.lsp_store.update(cx, |lsp_store, _| {
|
||||
let relevant_language_servers = lsp_store
|
||||
.languages
|
||||
.lsp_adapters(&language.name())
|
||||
.into_iter()
|
||||
.map(|lsp_adapter| lsp_adapter.name())
|
||||
.collect::<HashSet<_>>();
|
||||
lsp_store
|
||||
.language_server_statuses()
|
||||
.filter_map(|(server_id, server_status)| {
|
||||
relevant_language_servers
|
||||
.contains(&server_status.name)
|
||||
.then_some(server_id)
|
||||
})
|
||||
.filter_map(|server_id| lsp_store.lsp_server_capabilities.get(&server_id))
|
||||
.any(InlayHints::check_capabilities)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn language_server_id_for_name(
|
||||
&self,
|
||||
buffer: &Buffer,
|
||||
name: &str,
|
||||
cx: &mut App,
|
||||
) -> Task<Option<LanguageServerId>> {
|
||||
if self.is_local() {
|
||||
Task::ready(self.lsp_store.update(cx, |lsp_store, cx| {
|
||||
lsp_store
|
||||
.language_servers_for_local_buffer(buffer, cx)
|
||||
.find_map(|(adapter, server)| {
|
||||
if adapter.name.0 == name {
|
||||
Some(server.server_id())
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}))
|
||||
} else if let Some(project_id) = self.remote_id() {
|
||||
let request = self.client.request(proto::LanguageServerIdForName {
|
||||
project_id,
|
||||
buffer_id: buffer.remote_id().to_proto(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
cx.background_spawn(async move {
|
||||
let response = request.await.log_err()?;
|
||||
response.server_id.map(LanguageServerId::from_proto)
|
||||
})
|
||||
} else if let Some(ssh_client) = self.ssh_client.as_ref() {
|
||||
let request =
|
||||
ssh_client
|
||||
.read(cx)
|
||||
.proto_client()
|
||||
.request(proto::LanguageServerIdForName {
|
||||
project_id: SSH_PROJECT_ID,
|
||||
buffer_id: buffer.remote_id().to_proto(),
|
||||
name: name.to_string(),
|
||||
});
|
||||
cx.background_spawn(async move {
|
||||
let response = request.await.log_err()?;
|
||||
response.server_id.map(LanguageServerId::from_proto)
|
||||
})
|
||||
} else {
|
||||
Task::ready(None)
|
||||
name: &LanguageServerName,
|
||||
cx: &App,
|
||||
) -> Option<LanguageServerId> {
|
||||
let language = buffer.language()?;
|
||||
let relevant_language_servers = self
|
||||
.languages
|
||||
.lsp_adapters(&language.name())
|
||||
.into_iter()
|
||||
.map(|lsp_adapter| lsp_adapter.name())
|
||||
.collect::<HashSet<_>>();
|
||||
if !relevant_language_servers.contains(name) {
|
||||
return None;
|
||||
}
|
||||
self.language_server_statuses(cx)
|
||||
.filter(|(_, server_status)| relevant_language_servers.contains(&server_status.name))
|
||||
.find_map(|(server_id, server_status)| {
|
||||
if &server_status.name == name {
|
||||
Some(server_id)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn has_language_servers_for(&self, buffer: &Buffer, cx: &mut App) -> bool {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue