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 None
31 } else {
32 let mut best: Option<TextDocumentSyncKind> = None;
33 for kind in id_to_sync_kind_map.values() {
34 best = Some(match (best, kind) {
35 (None, kind) => *kind,
36 (
37 Some(TextDocumentSyncKind::FULL),
38 &TextDocumentSyncKind::INCREMENTAL,
39 ) => TextDocumentSyncKind::INCREMENTAL,
40 (Some(kind), _) => kind,
41 });
42 }
43 best
44 }
45 })
46 .or_else(|| {
47 static_caps
48 .text_document_sync
49 .as_ref()
50 .and_then(|sync| match sync {
51 TextDocumentSyncCapability::Kind(kind) => Some(*kind),
52 TextDocumentSyncCapability::Options(opts) => opts.change,
53 })
54 })
55 }
56}
57
58impl EffectiveCapability for cap::DidSaveTextDocument {
59 type Value = Option<bool>;
60
61 fn compute(
62 static_caps: &ServerCapabilities,
63 dynamic_caps: &DynamicCapabilities,
64 ) -> Self::Value {
65 dynamic_caps
66 .text_document_sync_did_save
67 .as_ref()
68 .and_then(|id_to_save_options_map| {
69 if id_to_save_options_map.is_empty() {
70 None
71 } else {
72 Some(
73 id_to_save_options_map
74 .values()
75 .any(|opts| opts.include_text.unwrap_or(false)),
76 )
77 }
78 })
79 .or_else(|| match static_caps.text_document_sync.as_ref()? {
80 TextDocumentSyncCapability::Options(opts) => match opts.save.as_ref()? {
81 TextDocumentSyncSaveOptions::Supported(true) => Some(false),
82 TextDocumentSyncSaveOptions::Supported(false) => None,
83 TextDocumentSyncSaveOptions::SaveOptions(save_opts) => {
84 Some(save_opts.include_text.unwrap_or(false))
85 }
86 },
87 TextDocumentSyncCapability::Kind(_) => None,
88 })
89 }
90}