shuck_server/session/
options.rs1use lsp_types::Url;
2use rustc_hash::FxHashMap;
3use serde::Deserialize;
4use shuck_config::{FormatConfig, LintConfig, ShuckConfig};
5
6use crate::session::settings::GlobalClientSettings;
7use crate::{Client, logging};
8
9pub(crate) type WorkspaceOptionsMap = FxHashMap<Url, ClientOptions>;
10
11#[derive(Debug, Deserialize, Default)]
12#[serde(rename_all = "camelCase")]
13pub struct GlobalOptions {
14 #[serde(flatten)]
15 client: ClientOptions,
16 #[serde(default)]
17 pub(crate) tracing: TracingOptions,
18}
19
20impl GlobalOptions {
21 pub fn into_settings(self, client: Client) -> GlobalClientSettings {
22 GlobalClientSettings::new(self.client, client)
23 }
24}
25
26#[derive(Clone, Debug, Default, Deserialize)]
27#[serde(rename_all = "camelCase")]
28pub struct ClientOptions {
29 #[serde(default)]
30 pub lint: Option<LintConfig>,
31 #[serde(default)]
32 pub format: Option<FormatConfig>,
33 #[serde(default)]
34 pub fix_all: Option<bool>,
35 #[serde(default)]
36 pub unsafe_fixes: Option<bool>,
37 #[serde(default)]
38 pub show_syntax_errors: Option<bool>,
39}
40
41impl ClientOptions {
42 pub(crate) fn to_config_overrides(&self) -> ShuckConfig {
43 ShuckConfig {
44 lint: self.lint.clone().unwrap_or_default(),
45 format: self.format.clone().unwrap_or_default(),
46 ..ShuckConfig::default()
47 }
48 }
49}
50
51#[derive(Debug, Deserialize, Default)]
52#[serde(rename_all = "camelCase")]
53pub(crate) struct TracingOptions {
54 pub(crate) log_file: Option<std::path::PathBuf>,
55 pub(crate) log_level: Option<logging::LogLevel>,
56}
57
58#[derive(Debug, Default)]
59pub(crate) struct AllOptions {
60 pub(crate) global: GlobalOptions,
61 pub(crate) workspace: Option<WorkspaceOptionsMap>,
62}
63
64#[derive(Debug, Deserialize, Default)]
65#[serde(rename_all = "camelCase")]
66struct InitializationOptions {
67 #[serde(default)]
68 shuck: GlobalOptions,
69 #[serde(default)]
70 workspace: Option<WorkspaceOptionsMap>,
71}
72
73impl AllOptions {
74 pub(crate) fn from_value(value: serde_json::Value, _client: &Client) -> Self {
75 if value
76 .as_object()
77 .is_some_and(|object| object.contains_key("shuck"))
78 {
79 let options =
80 serde_json::from_value::<InitializationOptions>(value).unwrap_or_default();
81 return Self {
82 global: options.shuck,
83 workspace: options.workspace,
84 };
85 }
86
87 let global = serde_json::from_value::<GlobalOptions>(value).unwrap_or_default();
88 Self {
89 global,
90 workspace: None,
91 }
92 }
93}