1use std::sync::Arc;
2
3use ::serde::{Deserialize, Serialize};
4use gpui::WeakEntity;
5use language::CachedLspAdapter;
6use lsp::LanguageServer;
7use util::ResultExt as _;
8
9use crate::LspStore;
10
11pub const CLANGD_SERVER_NAME: &str = "clangd";
12
13#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
14#[serde(rename_all = "camelCase")]
15pub struct InactiveRegionsParams {
16 pub text_document: lsp::OptionalVersionedTextDocumentIdentifier,
17 pub regions: Vec<lsp::Range>,
18}
19
20/// InactiveRegions is a clangd extension that marks regions of inactive code.
21pub struct InactiveRegions;
22
23impl lsp::notification::Notification for InactiveRegions {
24 type Params = InactiveRegionsParams;
25 const METHOD: &'static str = "textDocument/inactiveRegions";
26}
27
28pub fn register_notifications(
29 lsp_store: WeakEntity<LspStore>,
30 language_server: &LanguageServer,
31 adapter: Arc<CachedLspAdapter>,
32) {
33 if language_server.name().0 != CLANGD_SERVER_NAME {
34 return;
35 }
36 let server_id = language_server.server_id();
37
38 language_server
39 .on_notification::<InactiveRegions, _>({
40 let adapter = adapter.clone();
41 let this = lsp_store;
42
43 move |params: InactiveRegionsParams, mut cx| {
44 let adapter = adapter.clone();
45 this.update(&mut cx, |this, cx| {
46 let diagnostics = params
47 .regions
48 .into_iter()
49 .map(|range| lsp::Diagnostic {
50 range,
51 severity: Some(lsp::DiagnosticSeverity::INFORMATION),
52 source: Some(CLANGD_SERVER_NAME.to_string()),
53 message: "inactive region".to_string(),
54 tags: Some(vec![lsp::DiagnosticTag::UNNECESSARY]),
55 ..Default::default()
56 })
57 .collect();
58 let mapped_diagnostics = lsp::PublishDiagnosticsParams {
59 uri: params.text_document.uri,
60 version: params.text_document.version,
61 diagnostics,
62 };
63 this.update_diagnostics(
64 server_id,
65 mapped_diagnostics,
66 &adapter.disk_based_diagnostic_sources,
67 cx,
68 )
69 .log_err();
70 })
71 .ok();
72 }
73 })
74 .detach();
75}