1use std::collections::hash_map::Entry;
2use std::sync::Arc;
3
4use crate::Editor;
5use collections::HashMap;
6use gpui::{App, Entity};
7use language::Buffer;
8use language::Language;
9use lsp::LanguageServerId;
10use multi_buffer::Anchor;
11
12pub(crate) fn find_specific_language_server_in_selection<F>(
13 editor: &Editor,
14 cx: &mut App,
15 filter_language: F,
16 language_server_name: &str,
17) -> Option<(Anchor, Arc<Language>, LanguageServerId, Entity<Buffer>)>
18where
19 F: Fn(&Language) -> bool,
20{
21 let Some(project) = &editor.project else {
22 return None;
23 };
24 let multibuffer = editor.buffer().read(cx);
25 let mut language_servers_for = HashMap::default();
26 editor
27 .selections
28 .disjoint_anchors()
29 .iter()
30 .filter(|selection| selection.start == selection.end)
31 .filter_map(|selection| Some((selection.start.buffer_id?, selection.start)))
32 .filter_map(|(buffer_id, trigger_anchor)| {
33 let buffer = multibuffer.buffer(buffer_id)?;
34 let server_id = *match language_servers_for.entry(buffer_id) {
35 Entry::Occupied(occupied_entry) => occupied_entry.into_mut(),
36 Entry::Vacant(vacant_entry) => {
37 let language_server_id = project
38 .read(cx)
39 .language_servers_for_local_buffer(buffer.read(cx), cx)
40 .find_map(|(adapter, server)| {
41 if adapter.name.0.as_ref() == language_server_name {
42 Some(server.server_id())
43 } else {
44 None
45 }
46 });
47 vacant_entry.insert(language_server_id)
48 }
49 }
50 .as_ref()?;
51
52 Some((buffer, trigger_anchor, server_id))
53 })
54 .find_map(|(buffer, trigger_anchor, server_id)| {
55 let language = buffer.read(cx).language_at(trigger_anchor.text_anchor)?;
56 if !filter_language(&language) {
57 return None;
58 }
59 Some((
60 trigger_anchor,
61 Arc::clone(&language),
62 server_id,
63 buffer.clone(),
64 ))
65 })
66}