diff --git a/crates/ra_lsp_server/src/init.rs b/crates/ra_lsp_server/src/init.rs index 0b7a47a0b9..1b77e03125 100644 --- a/crates/ra_lsp_server/src/init.rs +++ b/crates/ra_lsp_server/src/init.rs @@ -1,39 +1,61 @@ -use serde::{Deserialize, Deserializer}; - -/// Client provided initialization options -#[derive(Deserialize, Clone, Copy, Debug)] -#[serde(rename_all = "camelCase")] -pub struct InitializationOptions { - /// Whether the client supports our custom highlighting publishing decorations. - /// This is different to the highlightingOn setting, which is whether the user - /// wants our custom highlighting to be used. - /// - /// Defaults to `true` - #[serde(default = "bool_true", deserialize_with = "nullable_bool_true")] - pub publish_decorations: bool, - - /// Whether or not the workspace loaded notification should be sent - /// - /// Defaults to `true` - #[serde(default = "bool_true", deserialize_with = "nullable_bool_true")] - pub show_workspace_loaded: bool, -} - -impl Default for InitializationOptions { - fn default() -> InitializationOptions { - InitializationOptions { publish_decorations: true, show_workspace_loaded: true } - } -} - -fn bool_true() -> bool { - true -} - -/// Deserializes a null value to a bool true by default -fn nullable_bool_true<'de, D>(deserializer: D) -> Result -where - D: Deserializer<'de>, -{ - let opt = Option::deserialize(deserializer)?; - Ok(opt.unwrap_or(true)) -} +use serde::{Deserialize, Deserializer}; + +/// Client provided initialization options +#[derive(Deserialize, Clone, Copy, Debug, PartialEq, Eq)] +#[serde(rename_all = "camelCase", default)] +pub struct InitializationOptions { + /// Whether the client supports our custom highlighting publishing decorations. + /// This is different to the highlightingOn setting, which is whether the user + /// wants our custom highlighting to be used. + /// + /// Defaults to `false` + #[serde(deserialize_with = "nullable_bool_false")] + pub publish_decorations: bool, + + /// Whether or not the workspace loaded notification should be sent + /// + /// Defaults to `true` + #[serde(deserialize_with = "nullable_bool_true")] + pub show_workspace_loaded: bool, +} + +impl Default for InitializationOptions { + fn default() -> InitializationOptions { + InitializationOptions { publish_decorations: false, show_workspace_loaded: true } + } +} + +/// Deserializes a null value to a bool false by default +fn nullable_bool_false<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let opt = Option::deserialize(deserializer)?; + Ok(opt.unwrap_or(false)) +} + +/// Deserializes a null value to a bool true by default +fn nullable_bool_true<'de, D>(deserializer: D) -> Result +where + D: Deserializer<'de>, +{ + let opt = Option::deserialize(deserializer)?; + Ok(opt.unwrap_or(true)) +} + +#[cfg(test)] +mod test { + use super::*; + + #[test] + fn deserialize_init_options_defaults() { + // check that null == default for both fields + let default = InitializationOptions::default(); + assert_eq!(default, serde_json::from_str(r#"{}"#).unwrap()); + assert_eq!( + default, + serde_json::from_str(r#"{"publishDecorations":null, "showWorkspaceLoaded":null}"#) + .unwrap() + ); + } +}