lsp_ext.rs

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