LspStore: move language_server_ids to local state too (#21786)
Attempt to further clarify what state is present in which mode Release Notes: - N/A
This commit is contained in:
parent
48eed7499f
commit
3c053c7bc4
5 changed files with 280 additions and 238 deletions
|
@ -11879,7 +11879,10 @@ impl Editor {
|
||||||
let buffer = buffer.read(cx);
|
let buffer = buffer.read(cx);
|
||||||
let language = buffer.language()?;
|
let language = buffer.language()?;
|
||||||
if project.is_local()
|
if project.is_local()
|
||||||
&& project.language_servers_for_buffer(buffer, cx).count() == 0
|
&& project
|
||||||
|
.language_servers_for_local_buffer(buffer, cx)
|
||||||
|
.count()
|
||||||
|
== 0
|
||||||
{
|
{
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
|
@ -13393,7 +13396,7 @@ impl SemanticsProvider for Model<Project> {
|
||||||
fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool {
|
fn supports_inlay_hints(&self, buffer: &Model<Buffer>, cx: &AppContext) -> bool {
|
||||||
// TODO: make this work for remote projects
|
// TODO: make this work for remote projects
|
||||||
self.read(cx)
|
self.read(cx)
|
||||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
.language_servers_for_local_buffer(buffer.read(cx), cx)
|
||||||
.any(
|
.any(
|
||||||
|(_, server)| match server.capabilities().inlay_hint_provider {
|
|(_, server)| match server.capabilities().inlay_hint_provider {
|
||||||
Some(lsp::OneOf::Left(enabled)) => enabled,
|
Some(lsp::OneOf::Left(enabled)) => enabled,
|
||||||
|
|
|
@ -37,7 +37,7 @@ where
|
||||||
.find_map(|(trigger_anchor, language, buffer)| {
|
.find_map(|(trigger_anchor, language, buffer)| {
|
||||||
project
|
project
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
.language_servers_for_local_buffer(buffer.read(cx), cx)
|
||||||
.find_map(|(adapter, server)| {
|
.find_map(|(adapter, server)| {
|
||||||
if adapter.name.0.as_ref() == language_server_name {
|
if adapter.name.0.as_ref() == language_server_name {
|
||||||
Some((
|
Some((
|
||||||
|
|
|
@ -838,7 +838,7 @@ fn language_server_for_buffer(
|
||||||
lsp_store
|
lsp_store
|
||||||
.update(cx, |lsp_store, cx| {
|
.update(cx, |lsp_store, cx| {
|
||||||
lsp_store
|
lsp_store
|
||||||
.language_server_for_buffer(buffer.read(cx), server_id, cx)
|
.language_server_for_local_buffer(buffer.read(cx), server_id, cx)
|
||||||
.map(|(adapter, server)| (adapter.clone(), server.clone()))
|
.map(|(adapter, server)| (adapter.clone(), server.clone()))
|
||||||
})?
|
})?
|
||||||
.ok_or_else(|| anyhow!("no language server found for buffer"))
|
.ok_or_else(|| anyhow!("no language server found for buffer"))
|
||||||
|
|
|
@ -136,6 +136,8 @@ pub struct LocalLspStore {
|
||||||
http_client: Arc<dyn HttpClient>,
|
http_client: Arc<dyn HttpClient>,
|
||||||
environment: Model<ProjectEnvironment>,
|
environment: Model<ProjectEnvironment>,
|
||||||
fs: Arc<dyn Fs>,
|
fs: Arc<dyn Fs>,
|
||||||
|
languages: Arc<LanguageRegistry>,
|
||||||
|
language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
|
||||||
yarn: Model<YarnPathStore>,
|
yarn: Model<YarnPathStore>,
|
||||||
pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
|
pub language_servers: HashMap<LanguageServerId, LanguageServerState>,
|
||||||
buffers_being_formatted: HashSet<BufferId>,
|
buffers_being_formatted: HashSet<BufferId>,
|
||||||
|
@ -186,6 +188,70 @@ impl LocalLspStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn language_servers_for_worktree(
|
||||||
|
&self,
|
||||||
|
worktree_id: WorktreeId,
|
||||||
|
) -> impl Iterator<Item = &Arc<LanguageServer>> {
|
||||||
|
self.language_server_ids
|
||||||
|
.iter()
|
||||||
|
.filter_map(move |((language_server_worktree_id, _), id)| {
|
||||||
|
if *language_server_worktree_id == worktree_id {
|
||||||
|
if let Some(LanguageServerState::Running { server, .. }) =
|
||||||
|
self.language_servers.get(id)
|
||||||
|
{
|
||||||
|
return Some(server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn language_server_ids_for_buffer(
|
||||||
|
&self,
|
||||||
|
buffer: &Buffer,
|
||||||
|
cx: &AppContext,
|
||||||
|
) -> Vec<LanguageServerId> {
|
||||||
|
if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
|
||||||
|
let worktree_id = file.worktree_id(cx);
|
||||||
|
self.languages
|
||||||
|
.lsp_adapters(&language.name())
|
||||||
|
.iter()
|
||||||
|
.flat_map(|adapter| {
|
||||||
|
let key = (worktree_id, adapter.name.clone());
|
||||||
|
self.language_server_ids.get(&key).copied()
|
||||||
|
})
|
||||||
|
.collect()
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub(crate) fn language_servers_for_buffer<'a>(
|
||||||
|
&'a self,
|
||||||
|
buffer: &'a Buffer,
|
||||||
|
cx: &'a AppContext,
|
||||||
|
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
|
self.language_server_ids_for_buffer(buffer, cx)
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|server_id| match self.language_servers.get(&server_id)? {
|
||||||
|
LanguageServerState::Running {
|
||||||
|
adapter, server, ..
|
||||||
|
} => Some((adapter, server)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
fn primary_language_server_for_buffer<'a>(
|
||||||
|
&'a self,
|
||||||
|
buffer: &'a Buffer,
|
||||||
|
cx: &'a AppContext,
|
||||||
|
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
|
// The list of language servers is ordered based on the `language_servers` setting
|
||||||
|
// for each language, thus we can consider the first one in the list to be the
|
||||||
|
// primary one.
|
||||||
|
self.language_servers_for_buffer(buffer, cx).next()
|
||||||
|
}
|
||||||
|
|
||||||
async fn format_locally(
|
async fn format_locally(
|
||||||
lsp_store: WeakModel<LspStore>,
|
lsp_store: WeakModel<LspStore>,
|
||||||
mut buffers: Vec<FormattableBuffer>,
|
mut buffers: Vec<FormattableBuffer>,
|
||||||
|
@ -227,11 +293,15 @@ impl LocalLspStore {
|
||||||
let buffer = buffer.handle.read(cx);
|
let buffer = buffer.handle.read(cx);
|
||||||
|
|
||||||
let adapters_and_servers = lsp_store
|
let adapters_and_servers = lsp_store
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
.language_servers_for_buffer(buffer, cx)
|
.language_servers_for_buffer(buffer, cx)
|
||||||
.map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
|
.map(|(adapter, lsp)| (adapter.clone(), lsp.clone()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
let primary_adapter = lsp_store
|
let primary_adapter = lsp_store
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
.primary_language_server_for_buffer(buffer, cx)
|
.primary_language_server_for_buffer(buffer, cx)
|
||||||
.map(|(adapter, lsp)| (adapter.clone(), lsp.clone()));
|
.map(|(adapter, lsp)| (adapter.clone(), lsp.clone()));
|
||||||
|
|
||||||
|
@ -820,7 +890,6 @@ impl LocalLspStore {
|
||||||
fn register_buffer_with_language_servers(
|
fn register_buffer_with_language_servers(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer_handle: &Model<Buffer>,
|
buffer_handle: &Model<Buffer>,
|
||||||
language_server_ids: &HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
|
|
||||||
cx: &mut ModelContext<LspStore>,
|
cx: &mut ModelContext<LspStore>,
|
||||||
) {
|
) {
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
|
@ -837,9 +906,6 @@ impl LocalLspStore {
|
||||||
};
|
};
|
||||||
let initial_snapshot = buffer.text_snapshot();
|
let initial_snapshot = buffer.text_snapshot();
|
||||||
let worktree_id = file.worktree_id(cx);
|
let worktree_id = file.worktree_id(cx);
|
||||||
let Some(languages) = buffer.language_registry() else {
|
|
||||||
return;
|
|
||||||
};
|
|
||||||
let language = buffer.language().cloned();
|
let language = buffer.language().cloned();
|
||||||
|
|
||||||
if let Some(diagnostics) = self.diagnostics.get(&worktree_id) {
|
if let Some(diagnostics) = self.diagnostics.get(&worktree_id) {
|
||||||
|
@ -852,8 +918,9 @@ impl LocalLspStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(language) = language {
|
if let Some(language) = language {
|
||||||
for adapter in languages.lsp_adapters(&language.name()) {
|
for adapter in self.languages.lsp_adapters(&language.name()) {
|
||||||
let server = language_server_ids
|
let server = self
|
||||||
|
.language_server_ids
|
||||||
.get(&(worktree_id, adapter.name.clone()))
|
.get(&(worktree_id, adapter.name.clone()))
|
||||||
.and_then(|id| self.language_servers.get(id))
|
.and_then(|id| self.language_servers.get(id))
|
||||||
.and_then(|server_state| {
|
.and_then(|server_state| {
|
||||||
|
@ -1534,7 +1601,6 @@ pub struct LspStore {
|
||||||
worktree_store: Model<WorktreeStore>,
|
worktree_store: Model<WorktreeStore>,
|
||||||
toolchain_store: Option<Model<ToolchainStore>>,
|
toolchain_store: Option<Model<ToolchainStore>>,
|
||||||
pub languages: Arc<LanguageRegistry>,
|
pub languages: Arc<LanguageRegistry>,
|
||||||
language_server_ids: HashMap<(WorktreeId, LanguageServerName), LanguageServerId>,
|
|
||||||
pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
|
pub language_server_statuses: BTreeMap<LanguageServerId, LanguageServerStatus>,
|
||||||
active_entry: Option<ProjectEntryId>,
|
active_entry: Option<ProjectEntryId>,
|
||||||
_maintain_workspace_config: (Task<Result<()>>, watch::Sender<()>),
|
_maintain_workspace_config: (Task<Result<()>>, watch::Sender<()>),
|
||||||
|
@ -1712,6 +1778,8 @@ impl LspStore {
|
||||||
Self {
|
Self {
|
||||||
mode: LspStoreMode::Local(LocalLspStore {
|
mode: LspStoreMode::Local(LocalLspStore {
|
||||||
supplementary_language_servers: Default::default(),
|
supplementary_language_servers: Default::default(),
|
||||||
|
languages: languages.clone(),
|
||||||
|
language_server_ids: Default::default(),
|
||||||
language_servers: Default::default(),
|
language_servers: Default::default(),
|
||||||
last_workspace_edits_by_language_server: Default::default(),
|
last_workspace_edits_by_language_server: Default::default(),
|
||||||
language_server_watched_paths: Default::default(),
|
language_server_watched_paths: Default::default(),
|
||||||
|
@ -1737,7 +1805,6 @@ impl LspStore {
|
||||||
worktree_store,
|
worktree_store,
|
||||||
toolchain_store: Some(toolchain_store),
|
toolchain_store: Some(toolchain_store),
|
||||||
languages: languages.clone(),
|
languages: languages.clone(),
|
||||||
language_server_ids: Default::default(),
|
|
||||||
language_server_statuses: Default::default(),
|
language_server_statuses: Default::default(),
|
||||||
nonce: StdRng::from_entropy().gen(),
|
nonce: StdRng::from_entropy().gen(),
|
||||||
diagnostic_summaries: Default::default(),
|
diagnostic_summaries: Default::default(),
|
||||||
|
@ -1793,7 +1860,6 @@ impl LspStore {
|
||||||
buffer_store,
|
buffer_store,
|
||||||
worktree_store,
|
worktree_store,
|
||||||
languages: languages.clone(),
|
languages: languages.clone(),
|
||||||
language_server_ids: Default::default(),
|
|
||||||
language_server_statuses: Default::default(),
|
language_server_statuses: Default::default(),
|
||||||
nonce: StdRng::from_entropy().gen(),
|
nonce: StdRng::from_entropy().gen(),
|
||||||
diagnostic_summaries: Default::default(),
|
diagnostic_summaries: Default::default(),
|
||||||
|
@ -1830,6 +1896,7 @@ impl LspStore {
|
||||||
self.unregister_buffer_from_language_servers(buffer, old_file, cx);
|
self.unregister_buffer_from_language_servers(buffer, old_file, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
self.detect_language_for_buffer(buffer, cx);
|
||||||
self.register_buffer_with_language_servers(buffer, cx);
|
self.register_buffer_with_language_servers(buffer, cx);
|
||||||
}
|
}
|
||||||
BufferStoreEvent::BufferDropped(_) => {}
|
BufferStoreEvent::BufferDropped(_) => {}
|
||||||
|
@ -1944,23 +2011,28 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
|
self.detect_language_for_buffer(buffer, cx);
|
||||||
self.register_buffer_with_language_servers(buffer, cx);
|
self.register_buffer_with_language_servers(buffer, cx);
|
||||||
cx.observe_release(buffer, |this, buffer, cx| {
|
cx.observe_release(buffer, |this, buffer, cx| {
|
||||||
if let Some(file) = File::from_dyn(buffer.file()) {
|
if let Some(file) = File::from_dyn(buffer.file()) {
|
||||||
if file.is_local() {
|
if file.is_local() {
|
||||||
|
if let Some(local) = this.as_local() {
|
||||||
let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
|
let uri = lsp::Url::from_file_path(file.abs_path(cx)).unwrap();
|
||||||
for server in this.language_servers_for_buffer(buffer, cx) {
|
for server in local.language_servers_for_buffer(buffer, cx) {
|
||||||
server
|
server
|
||||||
.1
|
.1
|
||||||
.notify::<lsp::notification::DidCloseTextDocument>(
|
.notify::<lsp::notification::DidCloseTextDocument>(
|
||||||
lsp::DidCloseTextDocumentParams {
|
lsp::DidCloseTextDocumentParams {
|
||||||
text_document: lsp::TextDocumentIdentifier::new(uri.clone()),
|
text_document: lsp::TextDocumentIdentifier::new(
|
||||||
|
uri.clone(),
|
||||||
|
),
|
||||||
},
|
},
|
||||||
)
|
)
|
||||||
.log_err();
|
.log_err();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
})
|
})
|
||||||
.detach();
|
.detach();
|
||||||
|
|
||||||
|
@ -2012,6 +2084,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for buffer in plain_text_buffers {
|
for buffer in plain_text_buffers {
|
||||||
|
this.detect_language_for_buffer(&buffer, cx);
|
||||||
this.register_buffer_with_language_servers(&buffer, cx);
|
this.register_buffer_with_language_servers(&buffer, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2155,13 +2228,16 @@ impl LspStore {
|
||||||
|
|
||||||
let language_server = match server {
|
let language_server = match server {
|
||||||
LanguageServerToQuery::Primary => {
|
LanguageServerToQuery::Primary => {
|
||||||
match self.primary_language_server_for_buffer(buffer, cx) {
|
match self
|
||||||
|
.as_local()
|
||||||
|
.and_then(|local| local.primary_language_server_for_buffer(buffer, cx))
|
||||||
|
{
|
||||||
Some((_, server)) => Some(Arc::clone(server)),
|
Some((_, server)) => Some(Arc::clone(server)),
|
||||||
None => return Task::ready(Ok(Default::default())),
|
None => return Task::ready(Ok(Default::default())),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
LanguageServerToQuery::Other(id) => self
|
LanguageServerToQuery::Other(id) => self
|
||||||
.language_server_for_buffer(buffer, id, cx)
|
.language_server_for_local_buffer(buffer, id, cx)
|
||||||
.map(|(_, server)| Arc::clone(server)),
|
.map(|(_, server)| Arc::clone(server)),
|
||||||
};
|
};
|
||||||
let file = File::from_dyn(buffer.file()).and_then(File::as_local);
|
let file = File::from_dyn(buffer.file()).and_then(File::as_local);
|
||||||
|
@ -2268,7 +2344,9 @@ impl LspStore {
|
||||||
else {
|
else {
|
||||||
return;
|
return;
|
||||||
};
|
};
|
||||||
for (worktree_id, started_lsp_name) in self.started_language_servers() {
|
for (worktree_id, started_lsp_name) in
|
||||||
|
self.as_local().unwrap().language_server_ids.keys().cloned()
|
||||||
|
{
|
||||||
let language = languages.iter().find_map(|l| {
|
let language = languages.iter().find_map(|l| {
|
||||||
let adapter = self
|
let adapter = self
|
||||||
.languages
|
.languages
|
||||||
|
@ -2359,10 +2437,10 @@ impl LspStore {
|
||||||
})?
|
})?
|
||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
} else {
|
} else if self.mode.is_local() {
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
let (lsp_adapter, lang_server) = if let Some((adapter, server)) =
|
let (lsp_adapter, lang_server) = if let Some((adapter, server)) =
|
||||||
self.language_server_for_buffer(buffer, action.server_id, cx)
|
self.language_server_for_local_buffer(buffer, action.server_id, cx)
|
||||||
{
|
{
|
||||||
(adapter.clone(), server.clone())
|
(adapter.clone(), server.clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -2415,6 +2493,8 @@ impl LspStore {
|
||||||
|
|
||||||
Ok(ProjectTransaction::default())
|
Ok(ProjectTransaction::default())
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Task::ready(Err(anyhow!("no upstream client and not local")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2446,7 +2526,7 @@ impl LspStore {
|
||||||
} else {
|
} else {
|
||||||
let buffer = buffer_handle.read(cx);
|
let buffer = buffer_handle.read(cx);
|
||||||
let (_, lang_server) = if let Some((adapter, server)) =
|
let (_, lang_server) = if let Some((adapter, server)) =
|
||||||
self.language_server_for_buffer(buffer, server_id, cx)
|
self.language_server_for_local_buffer(buffer, server_id, cx)
|
||||||
{
|
{
|
||||||
(adapter.clone(), server.clone())
|
(adapter.clone(), server.clone())
|
||||||
} else {
|
} else {
|
||||||
|
@ -2487,6 +2567,9 @@ impl LspStore {
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let scope = snapshot.language_scope_at(position);
|
let scope = snapshot.language_scope_at(position);
|
||||||
let Some(server_id) = self
|
let Some(server_id) = self
|
||||||
|
.as_local()
|
||||||
|
.and_then(|local| {
|
||||||
|
local
|
||||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
.language_servers_for_buffer(buffer.read(cx), cx)
|
||||||
.filter(|(_, server)| {
|
.filter(|(_, server)| {
|
||||||
server
|
server
|
||||||
|
@ -2502,6 +2585,7 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
.map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
|
.map(|(_, server)| LanguageServerToQuery::Other(server.server_id()))
|
||||||
.next()
|
.next()
|
||||||
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.upstream_client()
|
self.upstream_client()
|
||||||
.is_some()
|
.is_some()
|
||||||
|
@ -2748,13 +2832,13 @@ impl LspStore {
|
||||||
.await;
|
.await;
|
||||||
Ok(result)
|
Ok(result)
|
||||||
})
|
})
|
||||||
} else {
|
} else if let Some(local) = self.as_local() {
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let offset = position.to_offset(&snapshot);
|
let offset = position.to_offset(&snapshot);
|
||||||
let scope = snapshot.language_scope_at(offset);
|
let scope = snapshot.language_scope_at(offset);
|
||||||
let language = snapshot.language().cloned();
|
let language = snapshot.language().cloned();
|
||||||
|
|
||||||
let server_ids: Vec<_> = self
|
let server_ids: Vec<_> = local
|
||||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
.language_servers_for_buffer(buffer.read(cx), cx)
|
||||||
.filter(|(_, server)| server.capabilities().completion_provider.is_some())
|
.filter(|(_, server)| server.capabilities().completion_provider.is_some())
|
||||||
.filter(|(adapter, _)| {
|
.filter(|(adapter, _)| {
|
||||||
|
@ -2803,6 +2887,8 @@ impl LspStore {
|
||||||
|
|
||||||
Ok(completions)
|
Ok(completions)
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Task::ready(Err(anyhow!("No upstream client or local language server")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3083,7 +3169,7 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
} else {
|
} else {
|
||||||
let server_id = completion.server_id;
|
let server_id = completion.server_id;
|
||||||
let lang_server = match self.language_server_for_buffer(buffer, server_id, cx) {
|
let lang_server = match self.language_server_for_local_buffer(buffer, server_id, cx) {
|
||||||
Some((_, server)) => server.clone(),
|
Some((_, server)) => server.clone(),
|
||||||
_ => return Task::ready(Ok(Default::default())),
|
_ => return Task::ready(Ok(Default::default())),
|
||||||
};
|
};
|
||||||
|
@ -3383,7 +3469,7 @@ impl LspStore {
|
||||||
.await;
|
.await;
|
||||||
Ok(symbols)
|
Ok(symbols)
|
||||||
})
|
})
|
||||||
} else {
|
} else if let Some(local) = self.as_local() {
|
||||||
struct WorkspaceSymbolsResult {
|
struct WorkspaceSymbolsResult {
|
||||||
lsp_adapter: Arc<CachedLspAdapter>,
|
lsp_adapter: Arc<CachedLspAdapter>,
|
||||||
language: LanguageName,
|
language: LanguageName,
|
||||||
|
@ -3393,7 +3479,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut requests = Vec::new();
|
let mut requests = Vec::new();
|
||||||
for ((worktree_id, _), server_id) in self.language_server_ids.iter() {
|
for ((worktree_id, _), server_id) in local.language_server_ids.iter() {
|
||||||
let Some(worktree_handle) = self
|
let Some(worktree_handle) = self
|
||||||
.worktree_store
|
.worktree_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
|
@ -3407,8 +3493,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
let worktree_abs_path = worktree.abs_path().clone();
|
let worktree_abs_path = worktree.abs_path().clone();
|
||||||
|
|
||||||
let (lsp_adapter, language, server) =
|
let (lsp_adapter, language, server) = match local.language_servers.get(server_id) {
|
||||||
match self.as_local().unwrap().language_servers.get(server_id) {
|
|
||||||
Some(LanguageServerState::Running {
|
Some(LanguageServerState::Running {
|
||||||
adapter,
|
adapter,
|
||||||
language,
|
language,
|
||||||
|
@ -3521,6 +3606,8 @@ impl LspStore {
|
||||||
|
|
||||||
Ok(symbols)
|
Ok(symbols)
|
||||||
})
|
})
|
||||||
|
} else {
|
||||||
|
Task::ready(Err(anyhow!("No upstream client or local language server")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3570,10 +3657,6 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn started_language_servers(&self) -> Vec<(WorktreeId, LanguageServerName)> {
|
|
||||||
self.language_server_ids.keys().cloned().collect()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn on_buffer_edited(
|
pub fn on_buffer_edited(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffer: Model<Buffer>,
|
buffer: Model<Buffer>,
|
||||||
|
@ -3586,6 +3669,8 @@ impl LspStore {
|
||||||
let next_snapshot = buffer.text_snapshot();
|
let next_snapshot = buffer.text_snapshot();
|
||||||
|
|
||||||
let language_servers: Vec<_> = self
|
let language_servers: Vec<_> = self
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
.language_servers_for_buffer(buffer, cx)
|
.language_servers_for_buffer(buffer, cx)
|
||||||
.map(|i| i.1.clone())
|
.map(|i| i.1.clone())
|
||||||
.collect();
|
.collect();
|
||||||
|
@ -3686,8 +3771,9 @@ impl LspStore {
|
||||||
let text_document = lsp::TextDocumentIdentifier {
|
let text_document = lsp::TextDocumentIdentifier {
|
||||||
uri: lsp::Url::from_file_path(abs_path).log_err()?,
|
uri: lsp::Url::from_file_path(abs_path).log_err()?,
|
||||||
};
|
};
|
||||||
|
let local = self.as_local()?;
|
||||||
|
|
||||||
for server in self.language_servers_for_worktree(worktree_id) {
|
for server in local.language_servers_for_worktree(worktree_id) {
|
||||||
if let Some(include_text) = include_text(server.as_ref()) {
|
if let Some(include_text) = include_text(server.as_ref()) {
|
||||||
let text = if include_text {
|
let text = if include_text {
|
||||||
Some(buffer.read(cx).text())
|
Some(buffer.read(cx).text())
|
||||||
|
@ -3705,7 +3791,7 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for language_server_id in self.language_server_ids_for_buffer(buffer.read(cx), cx) {
|
for language_server_id in local.language_server_ids_for_buffer(buffer.read(cx), cx) {
|
||||||
self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
|
self.simulate_disk_based_diagnostics_events_if_needed(language_server_id, cx);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3719,14 +3805,18 @@ impl LspStore {
|
||||||
maybe!(async move {
|
maybe!(async move {
|
||||||
let servers = this
|
let servers = this
|
||||||
.update(&mut cx, |this, cx| {
|
.update(&mut cx, |this, cx| {
|
||||||
this.language_server_ids
|
let Some(local) = this.as_local() else {
|
||||||
|
return Vec::default();
|
||||||
|
};
|
||||||
|
local
|
||||||
|
.language_server_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|((worktree_id, _), server_id)| {
|
.filter_map(|((worktree_id, _), server_id)| {
|
||||||
let worktree = this
|
let worktree = this
|
||||||
.worktree_store
|
.worktree_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.worktree_for_id(*worktree_id, cx)?;
|
.worktree_for_id(*worktree_id, cx)?;
|
||||||
let state = this.as_local()?.language_servers.get(server_id)?;
|
let state = local.language_servers.get(server_id)?;
|
||||||
let delegate = LocalLspAdapterDelegate::for_local(this, &worktree, cx);
|
let delegate = LocalLspAdapterDelegate::for_local(this, &worktree, cx);
|
||||||
match state {
|
match state {
|
||||||
LanguageServerState::Starting(_) => None,
|
LanguageServerState::Starting(_) => None,
|
||||||
|
@ -3793,58 +3883,47 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
fn primary_language_server_for_buffer<'a>(
|
pub(crate) fn language_servers_for_local_buffer<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
buffer: &'a Buffer,
|
buffer: &'a Buffer,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
// The list of language servers is ordered based on the `language_servers` setting
|
self.as_local().into_iter().flat_map(|local| {
|
||||||
// for each language, thus we can consider the first one in the list to be the
|
local
|
||||||
// primary one.
|
.language_server_ids_for_buffer(buffer, cx)
|
||||||
self.language_servers_for_buffer(buffer, cx).next()
|
.into_iter()
|
||||||
|
.filter_map(|server_id| match local.language_servers.get(&server_id)? {
|
||||||
|
LanguageServerState::Running {
|
||||||
|
adapter, server, ..
|
||||||
|
} => Some((adapter, server)),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_server_for_buffer<'a>(
|
pub fn language_server_for_local_buffer<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
buffer: &'a Buffer,
|
buffer: &'a Buffer,
|
||||||
server_id: LanguageServerId,
|
server_id: LanguageServerId,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
) -> Option<(&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
self.language_servers_for_buffer(buffer, cx)
|
self.as_local()?
|
||||||
|
.language_servers_for_buffer(buffer, cx)
|
||||||
.find(|(_, s)| s.server_id() == server_id)
|
.find(|(_, s)| s.server_id() == server_id)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn language_servers_for_worktree(
|
|
||||||
&self,
|
|
||||||
worktree_id: WorktreeId,
|
|
||||||
) -> impl Iterator<Item = &Arc<LanguageServer>> {
|
|
||||||
self.language_server_ids
|
|
||||||
.iter()
|
|
||||||
.filter_map(move |((language_server_worktree_id, _), id)| {
|
|
||||||
if *language_server_worktree_id == worktree_id {
|
|
||||||
if let Some(LanguageServerState::Running { server, .. }) =
|
|
||||||
self.as_local()?.language_servers.get(id)
|
|
||||||
{
|
|
||||||
return Some(server);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
None
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
|
fn remove_worktree(&mut self, id_to_remove: WorktreeId, cx: &mut ModelContext<Self>) {
|
||||||
|
self.diagnostic_summaries.remove(&id_to_remove);
|
||||||
|
let to_remove = Vec::new();
|
||||||
if let Some(local) = self.as_local_mut() {
|
if let Some(local) = self.as_local_mut() {
|
||||||
local.diagnostics.remove(&id_to_remove);
|
local.diagnostics.remove(&id_to_remove);
|
||||||
local.prettier_store.update(cx, |prettier_store, cx| {
|
local.prettier_store.update(cx, |prettier_store, cx| {
|
||||||
prettier_store.remove_worktree(id_to_remove, cx);
|
prettier_store.remove_worktree(id_to_remove, cx);
|
||||||
})
|
});
|
||||||
}
|
|
||||||
|
|
||||||
self.diagnostic_summaries.remove(&id_to_remove);
|
|
||||||
|
|
||||||
let mut servers_to_remove = HashMap::default();
|
let mut servers_to_remove = HashMap::default();
|
||||||
let mut servers_to_preserve = HashSet::default();
|
let mut servers_to_preserve = HashSet::default();
|
||||||
for ((worktree_id, server_name), &server_id) in &self.language_server_ids {
|
for ((worktree_id, server_name), &server_id) in &local.language_server_ids {
|
||||||
if worktree_id == &id_to_remove {
|
if worktree_id == &id_to_remove {
|
||||||
servers_to_remove.insert(server_id, server_name.clone());
|
servers_to_remove.insert(server_id, server_name.clone());
|
||||||
} else {
|
} else {
|
||||||
|
@ -3853,23 +3932,23 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
servers_to_remove.retain(|server_id, _| !servers_to_preserve.contains(server_id));
|
servers_to_remove.retain(|server_id, _| !servers_to_preserve.contains(server_id));
|
||||||
for (server_id_to_remove, server_name) in servers_to_remove {
|
for (server_id_to_remove, server_name) in servers_to_remove {
|
||||||
self.language_server_ids
|
local
|
||||||
|
.language_server_ids
|
||||||
.remove(&(id_to_remove, server_name));
|
.remove(&(id_to_remove, server_name));
|
||||||
self.language_server_statuses.remove(&server_id_to_remove);
|
local
|
||||||
if let Some(local_lsp_store) = self.as_local_mut() {
|
|
||||||
local_lsp_store
|
|
||||||
.language_server_watched_paths
|
.language_server_watched_paths
|
||||||
.remove(&server_id_to_remove);
|
.remove(&server_id_to_remove);
|
||||||
local_lsp_store
|
local
|
||||||
.last_workspace_edits_by_language_server
|
.last_workspace_edits_by_language_server
|
||||||
.remove(&server_id_to_remove);
|
.remove(&server_id_to_remove);
|
||||||
local_lsp_store
|
local.language_servers.remove(&server_id_to_remove);
|
||||||
.language_servers
|
|
||||||
.remove(&server_id_to_remove);
|
|
||||||
}
|
|
||||||
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
|
cx.emit(LspStoreEvent::LanguageServerRemoved(server_id_to_remove));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for server in to_remove {
|
||||||
|
self.language_server_statuses.remove(&server);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn shared(
|
pub fn shared(
|
||||||
&mut self,
|
&mut self,
|
||||||
|
@ -3926,13 +4005,15 @@ impl LspStore {
|
||||||
.collect();
|
.collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn register_language_server(
|
fn register_local_language_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
worktree_id: WorktreeId,
|
worktree_id: WorktreeId,
|
||||||
language_server_name: LanguageServerName,
|
language_server_name: LanguageServerName,
|
||||||
language_server_id: LanguageServerId,
|
language_server_id: LanguageServerId,
|
||||||
) {
|
) {
|
||||||
self.language_server_ids
|
self.as_local_mut()
|
||||||
|
.unwrap()
|
||||||
|
.language_server_ids
|
||||||
.insert((worktree_id, language_server_name), language_server_id);
|
.insert((worktree_id, language_server_name), language_server_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3941,16 +4022,8 @@ impl LspStore {
|
||||||
buffer_handle: &Model<Buffer>,
|
buffer_handle: &Model<Buffer>,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
self.detect_language_for_buffer(buffer_handle, cx);
|
if let Some(local) = self.as_local_mut() {
|
||||||
match &mut self.mode {
|
local.register_buffer_with_language_servers(buffer_handle, cx);
|
||||||
LspStoreMode::Local(local) => {
|
|
||||||
local.register_buffer_with_language_servers(
|
|
||||||
buffer_handle,
|
|
||||||
&self.language_server_ids,
|
|
||||||
cx,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
_ => {}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3968,7 +4041,7 @@ impl LspStore {
|
||||||
buffer.update(cx, |buffer, cx| {
|
buffer.update(cx, |buffer, cx| {
|
||||||
let worktree_id = old_file.worktree_id(cx);
|
let worktree_id = old_file.worktree_id(cx);
|
||||||
|
|
||||||
let ids = &self.language_server_ids;
|
let ids = &self.as_local().unwrap().language_server_ids;
|
||||||
|
|
||||||
if let Some(language) = buffer.language().cloned() {
|
if let Some(language) = buffer.language().cloned() {
|
||||||
for adapter in self.languages.lsp_adapters(&language.name()) {
|
for adapter in self.languages.lsp_adapters(&language.name()) {
|
||||||
|
@ -3984,7 +4057,11 @@ impl LspStore {
|
||||||
.buffer_snapshots
|
.buffer_snapshots
|
||||||
.remove(&buffer.remote_id());
|
.remove(&buffer.remote_id());
|
||||||
let file_url = lsp::Url::from_file_path(old_path).unwrap();
|
let file_url = lsp::Url::from_file_path(old_path).unwrap();
|
||||||
for (_, language_server) in self.language_servers_for_buffer(buffer, cx) {
|
for (_, language_server) in self
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
|
.language_servers_for_buffer(buffer, cx)
|
||||||
|
{
|
||||||
language_server
|
language_server
|
||||||
.notify::<lsp::notification::DidCloseTextDocument>(
|
.notify::<lsp::notification::DidCloseTextDocument>(
|
||||||
lsp::DidCloseTextDocumentParams {
|
lsp::DidCloseTextDocumentParams {
|
||||||
|
@ -4128,8 +4205,8 @@ impl LspStore {
|
||||||
})?
|
})?
|
||||||
.await
|
.await
|
||||||
})
|
})
|
||||||
} else {
|
} else if let Some(local) = self.as_local() {
|
||||||
let Some(&language_server_id) = self.language_server_ids.get(&(
|
let Some(&language_server_id) = local.language_server_ids.get(&(
|
||||||
symbol.source_worktree_id,
|
symbol.source_worktree_id,
|
||||||
symbol.language_server_name.clone(),
|
symbol.language_server_name.clone(),
|
||||||
)) else {
|
)) else {
|
||||||
|
@ -4162,6 +4239,8 @@ impl LspStore {
|
||||||
symbol.language_server_name.clone(),
|
symbol.language_server_name.clone(),
|
||||||
cx,
|
cx,
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
Task::ready(Err(anyhow!("no upstream client or local store")))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4222,7 +4301,7 @@ impl LspStore {
|
||||||
if worktree.update(&mut cx, |worktree, _| worktree.is_local())? {
|
if worktree.update(&mut cx, |worktree, _| worktree.is_local())? {
|
||||||
lsp_store
|
lsp_store
|
||||||
.update(&mut cx, |lsp_store, cx| {
|
.update(&mut cx, |lsp_store, cx| {
|
||||||
lsp_store.register_language_server(
|
lsp_store.register_local_language_server(
|
||||||
worktree.read(cx).id(),
|
worktree.read(cx).id(),
|
||||||
language_server_name,
|
language_server_name,
|
||||||
language_server_id,
|
language_server_id,
|
||||||
|
@ -4270,6 +4349,8 @@ impl LspStore {
|
||||||
let snapshot = buffer.read(cx).snapshot();
|
let snapshot = buffer.read(cx).snapshot();
|
||||||
let scope = position.and_then(|position| snapshot.language_scope_at(position));
|
let scope = position.and_then(|position| snapshot.language_scope_at(position));
|
||||||
let server_ids = self
|
let server_ids = self
|
||||||
|
.as_local()
|
||||||
|
.unwrap()
|
||||||
.language_servers_for_buffer(buffer.read(cx), cx)
|
.language_servers_for_buffer(buffer.read(cx), cx)
|
||||||
.filter(|(adapter, _)| {
|
.filter(|(adapter, _)| {
|
||||||
scope
|
scope
|
||||||
|
@ -4821,7 +4902,7 @@ impl LspStore {
|
||||||
let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from)?;
|
let old_uri = lsp::Url::from_file_path(old_path).ok().map(String::from)?;
|
||||||
let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from)?;
|
let new_uri = lsp::Url::from_file_path(new_path).ok().map(String::from)?;
|
||||||
|
|
||||||
for language_server in self.language_servers_for_worktree(worktree_id) {
|
for language_server in local_store.language_servers_for_worktree(worktree_id) {
|
||||||
let Some(filter) = local_store
|
let Some(filter) = local_store
|
||||||
.language_server_paths_watched_for_rename
|
.language_server_paths_watched_for_rename
|
||||||
.get(&language_server.server_id())
|
.get(&language_server.server_id())
|
||||||
|
@ -4860,7 +4941,7 @@ impl LspStore {
|
||||||
let local_store = this.as_local()?;
|
let local_store = this.as_local()?;
|
||||||
let old_uri = old_uri?;
|
let old_uri = old_uri?;
|
||||||
let new_uri = new_uri?;
|
let new_uri = new_uri?;
|
||||||
for language_server in this.language_servers_for_worktree(worktree_id) {
|
for language_server in local_store.language_servers_for_worktree(worktree_id) {
|
||||||
let Some(filter) = local_store
|
let Some(filter) = local_store
|
||||||
.language_server_paths_watched_for_rename
|
.language_server_paths_watched_for_rename
|
||||||
.get(&language_server.server_id())
|
.get(&language_server.server_id())
|
||||||
|
@ -4982,7 +5063,8 @@ impl LspStore {
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.worktrees()
|
.worktrees()
|
||||||
.filter_map(|worktree| {
|
.filter_map(|worktree| {
|
||||||
self.language_servers_for_worktree(worktree.read(cx).id())
|
self.as_local()?
|
||||||
|
.language_servers_for_worktree(worktree.read(cx).id())
|
||||||
.find(|server| server.server_id() == language_server_id)
|
.find(|server| server.server_id() == language_server_id)
|
||||||
.map(|_| worktree)
|
.map(|_| worktree)
|
||||||
})
|
})
|
||||||
|
@ -6049,16 +6131,16 @@ impl LspStore {
|
||||||
language: LanguageName,
|
language: LanguageName,
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
if self.mode.is_remote() {
|
let Some(local) = self.as_local() else {
|
||||||
return;
|
return;
|
||||||
}
|
};
|
||||||
|
|
||||||
let worktree = worktree_handle.read(cx);
|
let worktree = worktree_handle.read(cx);
|
||||||
let worktree_id = worktree.id();
|
let worktree_id = worktree.id();
|
||||||
let root_path = worktree.abs_path();
|
let root_path = worktree.abs_path();
|
||||||
let key = (worktree_id, adapter.name.clone());
|
let key = (worktree_id, adapter.name.clone());
|
||||||
|
|
||||||
if self.language_server_ids.contains_key(&key) {
|
if local.language_server_ids.contains_key(&key) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -6227,11 +6309,10 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
});
|
});
|
||||||
|
|
||||||
self.as_local_mut()
|
let local = self.as_local_mut().unwrap();
|
||||||
.unwrap()
|
|
||||||
.language_servers
|
local.language_servers.insert(server_id, state);
|
||||||
.insert(server_id, state);
|
local.language_server_ids.insert(key, server_id);
|
||||||
self.language_server_ids.insert(key, server_id);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn shutdown_language_server(
|
async fn shutdown_language_server(
|
||||||
|
@ -6279,10 +6360,13 @@ impl LspStore {
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) -> Task<Vec<WorktreeId>> {
|
) -> Task<Vec<WorktreeId>> {
|
||||||
let key = (worktree_id, adapter_name);
|
let key = (worktree_id, adapter_name);
|
||||||
if !self.mode.is_local() {
|
let local = match &mut self.mode {
|
||||||
|
LspStoreMode::Local(local) => local,
|
||||||
|
_ => {
|
||||||
return Task::ready(Vec::new());
|
return Task::ready(Vec::new());
|
||||||
|
}
|
||||||
};
|
};
|
||||||
let Some(server_id) = self.language_server_ids.remove(&key) else {
|
let Some(server_id) = local.language_server_ids.remove(&key) else {
|
||||||
return Task::ready(Vec::new());
|
return Task::ready(Vec::new());
|
||||||
};
|
};
|
||||||
let name = key.1;
|
let name = key.1;
|
||||||
|
@ -6290,10 +6374,14 @@ impl LspStore {
|
||||||
|
|
||||||
// Remove other entries for this language server as well
|
// Remove other entries for this language server as well
|
||||||
let mut orphaned_worktrees = vec![worktree_id];
|
let mut orphaned_worktrees = vec![worktree_id];
|
||||||
let other_keys = self.language_server_ids.keys().cloned().collect::<Vec<_>>();
|
let other_keys = local
|
||||||
|
.language_server_ids
|
||||||
|
.keys()
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
for other_key in other_keys {
|
for other_key in other_keys {
|
||||||
if self.language_server_ids.get(&other_key) == Some(&server_id) {
|
if local.language_server_ids.get(&other_key) == Some(&server_id) {
|
||||||
self.language_server_ids.remove(&other_key);
|
local.language_server_ids.remove(&other_key);
|
||||||
orphaned_worktrees.push(other_key.0);
|
orphaned_worktrees.push(other_key.0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6427,14 +6515,17 @@ impl LspStore {
|
||||||
// Restart the language server for the given worktree.
|
// Restart the language server for the given worktree.
|
||||||
this.start_language_servers(&worktree, language.clone(), cx);
|
this.start_language_servers(&worktree, language.clone(), cx);
|
||||||
|
|
||||||
|
let local = this.as_local_mut().unwrap();
|
||||||
|
|
||||||
// Lookup new server ids and set them for each of the orphaned worktrees
|
// Lookup new server ids and set them for each of the orphaned worktrees
|
||||||
for (affected_worktree_id, language_server_name) in affected_worktrees {
|
for (affected_worktree_id, language_server_name) in affected_worktrees {
|
||||||
if let Some(new_server_id) = this
|
if let Some(new_server_id) = local
|
||||||
.language_server_ids
|
.language_server_ids
|
||||||
.get(&(worktree_id, language_server_name.clone()))
|
.get(&(worktree_id, language_server_name.clone()))
|
||||||
.cloned()
|
.cloned()
|
||||||
{
|
{
|
||||||
this.language_server_ids
|
local
|
||||||
|
.language_server_ids
|
||||||
.insert((affected_worktree_id, language_server_name), new_server_id);
|
.insert((affected_worktree_id, language_server_name), new_server_id);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7065,9 +7156,12 @@ impl LspStore {
|
||||||
key: (WorktreeId, LanguageServerName),
|
key: (WorktreeId, LanguageServerName),
|
||||||
cx: &mut ModelContext<Self>,
|
cx: &mut ModelContext<Self>,
|
||||||
) {
|
) {
|
||||||
|
let Some(local) = self.as_local_mut() else {
|
||||||
|
return;
|
||||||
|
};
|
||||||
// If the language server for this key doesn't match the server id, don't store the
|
// If the language server for this key doesn't match the server id, don't store the
|
||||||
// server. Which will cause it to be dropped, killing the process
|
// server. Which will cause it to be dropped, killing the process
|
||||||
if self
|
if local
|
||||||
.language_server_ids
|
.language_server_ids
|
||||||
.get(&key)
|
.get(&key)
|
||||||
.map(|id| id != &server_id)
|
.map(|id| id != &server_id)
|
||||||
|
@ -7078,7 +7172,6 @@ impl LspStore {
|
||||||
|
|
||||||
// Update language_servers collection with Running variant of LanguageServerState
|
// Update language_servers collection with Running variant of LanguageServerState
|
||||||
// indicating that the server is up and running and ready
|
// indicating that the server is up and running and ready
|
||||||
if let Some(local) = self.as_local_mut() {
|
|
||||||
local.language_servers.insert(
|
local.language_servers.insert(
|
||||||
server_id,
|
server_id,
|
||||||
LanguageServerState::Running {
|
LanguageServerState::Running {
|
||||||
|
@ -7105,7 +7198,6 @@ impl LspStore {
|
||||||
.insert(server_id, watcher);
|
.insert(server_id, watcher);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
self.language_server_statuses.insert(
|
self.language_server_statuses.insert(
|
||||||
server_id,
|
server_id,
|
||||||
|
@ -7232,23 +7324,6 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn language_servers_for_buffer<'a>(
|
|
||||||
&'a self,
|
|
||||||
buffer: &'a Buffer,
|
|
||||||
cx: &'a AppContext,
|
|
||||||
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
|
||||||
self.language_server_ids_for_buffer(buffer, cx)
|
|
||||||
.into_iter()
|
|
||||||
.filter_map(
|
|
||||||
|server_id| match self.as_local()?.language_servers.get(&server_id)? {
|
|
||||||
LanguageServerState::Running {
|
|
||||||
adapter, server, ..
|
|
||||||
} => Some((adapter, server)),
|
|
||||||
_ => None,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
pub(crate) fn cancel_language_server_work_for_buffers(
|
pub(crate) fn cancel_language_server_work_for_buffers(
|
||||||
&mut self,
|
&mut self,
|
||||||
buffers: impl IntoIterator<Item = Model<Buffer>>,
|
buffers: impl IntoIterator<Item = Model<Buffer>>,
|
||||||
|
@ -7269,11 +7344,12 @@ impl LspStore {
|
||||||
cx.background_executor()
|
cx.background_executor()
|
||||||
.spawn(request)
|
.spawn(request)
|
||||||
.detach_and_log_err(cx);
|
.detach_and_log_err(cx);
|
||||||
} else {
|
} else if let Some(local) = self.as_local() {
|
||||||
let servers = buffers
|
let servers = buffers
|
||||||
.into_iter()
|
.into_iter()
|
||||||
.flat_map(|buffer| {
|
.flat_map(|buffer| {
|
||||||
self.language_server_ids_for_buffer(buffer.read(cx), cx)
|
local
|
||||||
|
.language_server_ids_for_buffer(buffer.read(cx), cx)
|
||||||
.into_iter()
|
.into_iter()
|
||||||
})
|
})
|
||||||
.collect::<HashSet<_>>();
|
.collect::<HashSet<_>>();
|
||||||
|
@ -7340,16 +7416,6 @@ impl LspStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_servers(
|
|
||||||
&self,
|
|
||||||
) -> impl '_ + Iterator<Item = (LanguageServerId, LanguageServerName, WorktreeId)> {
|
|
||||||
self.language_server_ids
|
|
||||||
.iter()
|
|
||||||
.map(|((worktree_id, server_name), server_id)| {
|
|
||||||
(*server_id, server_name.clone(), *worktree_id)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn register_supplementary_language_server(
|
fn register_supplementary_language_server(
|
||||||
&mut self,
|
&mut self,
|
||||||
id: LanguageServerId,
|
id: LanguageServerId,
|
||||||
|
@ -7416,7 +7482,7 @@ impl LspStore {
|
||||||
});
|
});
|
||||||
|
|
||||||
let worktree_id = worktree_handle.read(cx).id();
|
let worktree_id = worktree_handle.read(cx).id();
|
||||||
let mut language_server_ids = self
|
let mut language_server_ids = local
|
||||||
.language_server_ids
|
.language_server_ids
|
||||||
.iter()
|
.iter()
|
||||||
.filter_map(|((server_worktree_id, _), server_id)| {
|
.filter_map(|((server_worktree_id, _), server_id)| {
|
||||||
|
@ -7477,26 +7543,6 @@ impl LspStore {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) fn language_server_ids_for_buffer(
|
|
||||||
&self,
|
|
||||||
buffer: &Buffer,
|
|
||||||
cx: &AppContext,
|
|
||||||
) -> Vec<LanguageServerId> {
|
|
||||||
if let Some((file, language)) = File::from_dyn(buffer.file()).zip(buffer.language()) {
|
|
||||||
let worktree_id = file.worktree_id(cx);
|
|
||||||
self.languages
|
|
||||||
.lsp_adapters(&language.name())
|
|
||||||
.iter()
|
|
||||||
.flat_map(|adapter| {
|
|
||||||
let key = (worktree_id, adapter.name.clone());
|
|
||||||
self.language_server_ids.get(&key).copied()
|
|
||||||
})
|
|
||||||
.collect()
|
|
||||||
} else {
|
|
||||||
Vec::new()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
|
fn serialize_symbol(symbol: &Symbol) -> proto::Symbol {
|
||||||
proto::Symbol {
|
proto::Symbol {
|
||||||
language_server_name: symbol.language_server_name.0.to_string(),
|
language_server_name: symbol.language_server_name.0.to_string(),
|
||||||
|
|
|
@ -4135,13 +4135,6 @@ impl Project {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_servers<'a>(
|
|
||||||
&'a self,
|
|
||||||
cx: &'a AppContext,
|
|
||||||
) -> impl 'a + Iterator<Item = (LanguageServerId, LanguageServerName, WorktreeId)> {
|
|
||||||
self.lsp_store.read(cx).language_servers()
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn supplementary_language_servers<'a>(
|
pub fn supplementary_language_servers<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
|
@ -4157,14 +4150,14 @@ impl Project {
|
||||||
self.lsp_store.read(cx).language_server_for_id(id)
|
self.lsp_store.read(cx).language_server_for_id(id)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn language_servers_for_buffer<'a>(
|
pub fn language_servers_for_local_buffer<'a>(
|
||||||
&'a self,
|
&'a self,
|
||||||
buffer: &'a Buffer,
|
buffer: &'a Buffer,
|
||||||
cx: &'a AppContext,
|
cx: &'a AppContext,
|
||||||
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
) -> impl Iterator<Item = (&'a Arc<CachedLspAdapter>, &'a Arc<LanguageServer>)> {
|
||||||
self.lsp_store
|
self.lsp_store
|
||||||
.read(cx)
|
.read(cx)
|
||||||
.language_servers_for_buffer(buffer, cx)
|
.language_servers_for_local_buffer(buffer, cx)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn buffer_store(&self) -> &Model<BufferStore> {
|
pub fn buffer_store(&self) -> &Model<BufferStore> {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue