lsp_ext.rs

 1use std::sync::Arc;
 2
 3use crate::Editor;
 4use gpui::{App, AppContext as _, Entity, Task};
 5use itertools::Itertools;
 6use language::Buffer;
 7use language::Language;
 8use lsp::LanguageServerId;
 9use multi_buffer::Anchor;
10
11pub(crate) fn find_specific_language_server_in_selection<F>(
12    editor: &Editor,
13    cx: &mut App,
14    filter_language: F,
15    language_server_name: &str,
16) -> Task<Option<(Anchor, Arc<Language>, LanguageServerId, Entity<Buffer>)>>
17where
18    F: Fn(&Language) -> bool,
19{
20    let Some(project) = &editor.project else {
21        return Task::ready(None);
22    };
23
24    let applicable_buffers = editor
25        .selections
26        .disjoint_anchors()
27        .iter()
28        .filter(|selection| selection.start == selection.end)
29        .filter_map(|selection| Some((selection.start, selection.start.buffer_id?)))
30        .filter_map(|(trigger_anchor, buffer_id)| {
31            let buffer = editor.buffer().read(cx).buffer(buffer_id)?;
32            let language = buffer.read(cx).language_at(trigger_anchor.text_anchor)?;
33            if filter_language(&language) {
34                Some((trigger_anchor, buffer, language))
35            } else {
36                None
37            }
38        })
39        .unique_by(|(_, buffer, _)| buffer.read(cx).remote_id())
40        .collect::<Vec<_>>();
41
42    let applicable_buffer_tasks = applicable_buffers
43        .into_iter()
44        .map(|(trigger_anchor, buffer, language)| {
45            let task = buffer.update(cx, |buffer, cx| {
46                project.update(cx, |project, cx| {
47                    project.language_server_id_for_name(buffer, language_server_name, cx)
48                })
49            });
50            (trigger_anchor, buffer, language, task)
51        })
52        .collect::<Vec<_>>();
53    cx.background_spawn(async move {
54        for (trigger_anchor, buffer, language, task) in applicable_buffer_tasks {
55            if let Some(server_id) = task.await {
56                return Some((trigger_anchor, language, server_id, buffer));
57            }
58        }
59
60        None
61    })
62}