]> git.lizzy.rs Git - rust.git/blobdiff - crates/rust-analyzer/src/config.rs
More maintainable caps config
[rust.git] / crates / rust-analyzer / src / config.rs
index a5b1d90b1dc5e1ded204c525e787a2e969a9f836..a80652e8399778b6efa8eb22626a6c0cf40c7a69 100644 (file)
@@ -175,7 +175,7 @@ struct ConfigData {
 
 #[derive(Debug, Clone)]
 pub struct Config {
-    pub client_caps: ClientCapsConfig,
+    pub caps: lsp_types::ClientCapabilities,
 
     pub publish_diagnostics: bool,
     pub diagnostics: DiagnosticsConfig,
@@ -286,26 +286,12 @@ pub struct RunnablesConfig {
     pub cargo_extra_args: Vec<String>,
 }
 
-#[derive(Debug, Clone, Default)]
-pub struct ClientCapsConfig {
-    pub location_link: bool,
-    pub line_folding_only: bool,
-    pub hierarchical_symbols: bool,
-    pub code_action_literals: bool,
-    pub work_done_progress: bool,
-    pub code_action_group: bool,
-    pub code_action_resolve: bool,
-    pub hover_actions: bool,
-    pub status_notification: bool,
-    pub signature_help_label_offsets: bool,
-}
-
 impl Config {
     pub fn new(root_path: AbsPathBuf) -> Self {
         // Defaults here don't matter, we'll immediately re-write them with
         // ConfigData.
         let mut res = Config {
-            client_caps: ClientCapsConfig::default(),
+            caps: lsp_types::ClientCapabilities::default(),
 
             publish_diagnostics: false,
             diagnostics: DiagnosticsConfig::default(),
@@ -505,38 +491,11 @@ fn do_update(&mut self, json: serde_json::Value) {
     }
 
     pub fn update_caps(&mut self, caps: &ClientCapabilities) {
+        self.caps = caps.clone();
         if let Some(doc_caps) = caps.text_document.as_ref() {
             if let Some(value) = doc_caps.hover.as_ref().and_then(|it| it.content_format.as_ref()) {
                 self.hover.markdown = value.contains(&MarkupKind::Markdown)
             }
-            if let Some(value) = doc_caps.definition.as_ref().and_then(|it| it.link_support) {
-                self.client_caps.location_link = value;
-            }
-            if let Some(value) = doc_caps.folding_range.as_ref().and_then(|it| it.line_folding_only)
-            {
-                self.client_caps.line_folding_only = value
-            }
-            if let Some(value) = doc_caps
-                .document_symbol
-                .as_ref()
-                .and_then(|it| it.hierarchical_document_symbol_support)
-            {
-                self.client_caps.hierarchical_symbols = value
-            }
-            if let Some(value) =
-                doc_caps.code_action.as_ref().map(|it| it.code_action_literal_support.is_some())
-            {
-                self.client_caps.code_action_literals = value;
-            }
-            if let Some(value) = doc_caps
-                .signature_help
-                .as_ref()
-                .and_then(|it| it.signature_information.as_ref())
-                .and_then(|it| it.parameter_information.as_ref())
-                .and_then(|it| it.label_offset_support)
-            {
-                self.client_caps.signature_help_label_offsets = value;
-            }
 
             self.completion.allow_snippets(false);
             self.completion.active_resolve_capabilities =
@@ -548,20 +507,6 @@ pub fn update_caps(&mut self, caps: &ClientCapabilities) {
                     }
                 }
             }
-
-            if let Some(code_action) = &doc_caps.code_action {
-                if let Some(resolve_support) = &code_action.resolve_support {
-                    if resolve_support.properties.iter().any(|it| it == "edit") {
-                        self.client_caps.code_action_resolve = true;
-                    }
-                }
-            }
-        }
-
-        if let Some(window_caps) = caps.window.as_ref() {
-            if let Some(value) = window_caps.work_done_progress {
-                self.client_caps.work_done_progress = value;
-            }
         }
 
         self.assist.allow_snippets(false);
@@ -571,10 +516,6 @@ pub fn update_caps(&mut self, caps: &ClientCapabilities) {
 
             let snippet_text_edit = get_bool("snippetTextEdit");
             self.assist.allow_snippets(snippet_text_edit);
-
-            self.client_caps.code_action_group = get_bool("codeActionGroup");
-            self.client_caps.hover_actions = get_bool("hoverActions");
-            self.client_caps.status_notification = get_bool("statusNotification");
         }
 
         if let Some(workspace_caps) = caps.workspace.as_ref() {
@@ -597,6 +538,95 @@ pub fn json_schema() -> serde_json::Value {
     }
 }
 
+macro_rules! try_ {
+    ($expr:expr) => {
+        || -> _ { Some($expr) }()
+    };
+}
+macro_rules! try_or {
+    ($expr:expr, $or:expr) => {
+        try_!($expr).unwrap_or($or)
+    };
+}
+
+impl Config {
+    pub fn location_link(&self) -> bool {
+        try_or!(self.caps.text_document.as_ref()?.definition?.link_support?, false)
+    }
+    pub fn line_folding_only(&self) -> bool {
+        try_or!(self.caps.text_document.as_ref()?.folding_range.as_ref()?.line_folding_only?, false)
+    }
+    pub fn hierarchical_symbols(&self) -> bool {
+        try_or!(
+            self.caps
+                .text_document
+                .as_ref()?
+                .document_symbol
+                .as_ref()?
+                .hierarchical_document_symbol_support?,
+            false
+        )
+    }
+    pub fn code_action_literals(&self) -> bool {
+        try_!(self
+            .caps
+            .text_document
+            .as_ref()?
+            .code_action
+            .as_ref()?
+            .code_action_literal_support
+            .as_ref()?)
+        .is_some()
+    }
+    pub fn work_done_progress(&self) -> bool {
+        try_or!(self.caps.window.as_ref()?.work_done_progress?, false)
+    }
+    pub fn code_action_resolve(&self) -> bool {
+        try_or!(
+            self.caps
+                .text_document
+                .as_ref()?
+                .code_action
+                .as_ref()?
+                .resolve_support
+                .as_ref()?
+                .properties
+                .as_slice(),
+            &[]
+        )
+        .iter()
+        .any(|it| it == "edit")
+    }
+    pub fn signature_help_label_offsets(&self) -> bool {
+        try_or!(
+            self.caps
+                .text_document
+                .as_ref()?
+                .signature_help
+                .as_ref()?
+                .signature_information
+                .as_ref()?
+                .parameter_information
+                .as_ref()?
+                .label_offset_support?,
+            false
+        )
+    }
+
+    fn experimental(&self, index: &'static str) -> bool {
+        try_or!(self.caps.experimental.as_ref()?.get(index)?.as_bool()?, false)
+    }
+    pub fn code_action_group(&self) -> bool {
+        self.experimental("codeActionGroup")
+    }
+    pub fn hover_actions(&self) -> bool {
+        self.experimental("hoverActions")
+    }
+    pub fn status_notification(&self) -> bool {
+        self.experimental("statusNotification")
+    }
+}
+
 #[derive(Deserialize)]
 #[serde(untagged)]
 enum ManifestOrProjectJson {