1use super::DynamicCapabilities;
2use lsp_types::{
3 ServerCapabilities, TextDocumentSyncCapability, TextDocumentSyncKind,
4 TextDocumentSyncSaveOptions,
5};
6
7pub mod cap {
8 pub struct DidChangeTextDocument;
9 pub struct DidSaveTextDocument;
10}
11
12pub trait EffectiveCapability {
13 type Value;
14 fn compute(static_caps: &ServerCapabilities, dynamic_caps: &DynamicCapabilities)
15 -> Self::Value;
16}
17
18impl EffectiveCapability for cap::DidChangeTextDocument {
19 type Value = Option<TextDocumentSyncKind>;
20
21 fn compute(
22 static_caps: &ServerCapabilities,
23 dynamic_caps: &DynamicCapabilities,
24 ) -> Self::Value {
25 dynamic_caps
26 .text_document_sync_did_change
27 .as_ref()
28 .and_then(|id_to_sync_kind_map| {
29 if id_to_sync_kind_map.is_empty() {
30 return None;
31 }
32 let mut has_incremental = false;
33 for &kind in id_to_sync_kind_map.values() {
34 if kind == TextDocumentSyncKind::FULL {
35 return Some(TextDocumentSyncKind::FULL);
36 }
37 if kind == TextDocumentSyncKind::INCREMENTAL {
38 has_incremental = true;
39 }
40 }
41 if has_incremental {
42 Some(TextDocumentSyncKind::INCREMENTAL)
43 } else {
44 None
45 }
46 })
47 .or_else(|| {
48 static_caps
49 .text_document_sync
50 .as_ref()
51 .and_then(|sync| match sync {
52 TextDocumentSyncCapability::Kind(kind) => Some(*kind),
53 TextDocumentSyncCapability::Options(opts) => opts.change,
54 })
55 })
56 }
57}
58
59impl EffectiveCapability for cap::DidSaveTextDocument {
60 type Value = Option<bool>;
61
62 fn compute(
63 static_caps: &ServerCapabilities,
64 dynamic_caps: &DynamicCapabilities,
65 ) -> Self::Value {
66 dynamic_caps
67 .text_document_sync_did_save
68 .as_ref()
69 .and_then(|id_to_save_options_map| {
70 if id_to_save_options_map.is_empty() {
71 None
72 } else {
73 Some(
74 id_to_save_options_map
75 .values()
76 .any(|opts| opts.include_text.unwrap_or(false)),
77 )
78 }
79 })
80 .or_else(|| match static_caps.text_document_sync.as_ref()? {
81 TextDocumentSyncCapability::Options(opts) => match opts.save.as_ref()? {
82 TextDocumentSyncSaveOptions::Supported(true) => Some(false),
83 TextDocumentSyncSaveOptions::Supported(false) => None,
84 TextDocumentSyncSaveOptions::SaveOptions(save_opts) => {
85 Some(save_opts.include_text.unwrap_or(false))
86 }
87 },
88 TextDocumentSyncCapability::Kind(_) => None,
89 })
90 }
91}