Skip to content

Commit 9b0666e

Browse files
committed
Finish splitting *ConfigData and *ConfigInput
1 parent 0039f6b commit 9b0666e

File tree

1 file changed

+99
-75
lines changed

1 file changed

+99
-75
lines changed

crates/rust-analyzer/src/config.rs

Lines changed: 99 additions & 75 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ mod patch_old_style;
6060
// To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep
6161
// parsing the old name.
6262
config_data! {
63-
global: struct GlobalConfigData <- GlobalConfigInput {
63+
global: struct GlobalConfigData <- GlobalConfigInput -> RootGlobalConfigData {
6464
/// Whether to insert #[must_use] when generating `as_` methods
6565
/// for enum variants.
6666
assist_emitMustUse: bool = false,
@@ -366,7 +366,7 @@ config_data! {
366366
}
367367

368368
config_data! {
369-
local: struct LocalConfigData <- LocalConfigInput {
369+
local: struct LocalConfigData <- LocalConfigInput -> RootLocalConfigData {
370370
/// Toggles the additional completions that automatically add imports when completed.
371371
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
372372
completion_autoimport_enable: bool = true,
@@ -583,44 +583,25 @@ config_data! {
583583
}
584584

585585
config_data! {
586-
client: struct ClientConfigData <- ClientConfigInput {}
586+
client: struct ClientConfigData <- ClientConfigInput -> RootClientConfigData {}
587587
}
588588

589-
impl Default for ConfigData {
590-
fn default() -> Self {
591-
ConfigData::from_json(serde_json::Value::Null, &mut Vec::new())
592-
}
593-
}
594-
595-
#[derive(Debug, Clone)]
596-
struct RootLocalConfigData(LocalConfigData);
597-
#[derive(Debug, Clone)]
598-
struct RootGlobalConfigData(GlobalConfigData);
599-
#[derive(Debug, Clone)]
600-
struct RootClientConfigData(ClientConfigData);
601-
602-
#[derive(Debug, Clone)]
589+
#[derive(Debug, Clone, Default)]
603590
struct RootConfigData {
604591
local: RootLocalConfigData,
605592
global: RootGlobalConfigData,
606593
client: RootClientConfigData,
607594
}
608595

609-
impl Default for RootConfigData {
610-
fn default() -> Self {
611-
RootConfigData {
612-
local: RootLocalConfigData(LocalConfigData::from_json(
613-
&mut serde_json::Value::Null,
614-
&mut Vec::new(),
615-
)),
616-
global: RootGlobalConfigData(GlobalConfigData::from_json(
617-
&mut serde_json::Value::Null,
618-
&mut Vec::new(),
619-
)),
620-
client: RootClientConfigData(ClientConfigData::from_json(
621-
&mut serde_json::Value::Null,
622-
&mut Vec::new(),
623-
)),
596+
impl RootConfigData {
597+
/// Reads a single root config blob. All fields are either set by the config blob, or to the
598+
/// default value.
599+
fn from_root_input(input: ConfigInput) -> Self {
600+
let ConfigInput { global, local, client } = input;
601+
Self {
602+
global: RootGlobalConfigData::from_root_input(global),
603+
local: RootLocalConfigData::from_root_input(local),
604+
client: RootClientConfigData::from_root_input(client),
624605
}
625606
}
626607
}
@@ -1188,13 +1169,14 @@ impl Config {
11881169
}
11891170
let mut errors = Vec::new();
11901171
self.detached_files =
1191-
get_field::<Vec<PathBuf>>(&mut json, &mut errors, "detachedFiles", None, vec![])
1172+
get_field::<Vec<PathBuf>>(&mut json, &mut errors, "detachedFiles", None)
1173+
.unwrap_or_default()
11921174
.into_iter()
11931175
.map(AbsPathBuf::assert)
11941176
.collect();
11951177
patch_old_style::patch_json_for_outdated_configs(&mut json);
1196-
self.root_config.global =
1197-
RootGlobalConfigData(GlobalConfigData::from_json(&mut json, &mut errors));
1178+
let input = ConfigInput::from_json(json, &mut errors);
1179+
self.root_config = RootConfigData::from_root_input(input);
11981180
tracing::debug!("deserialized config data: {:#?}", self.root_config.global);
11991181
self.snippets.clear();
12001182
for (name, def) in self.root_config.local.0.completion_snippets_custom.iter() {
@@ -1244,7 +1226,7 @@ impl Config {
12441226
}
12451227

12461228
pub fn json_schema() -> serde_json::Value {
1247-
ConfigData::json_schema()
1229+
ConfigInput::json_schema()
12481230
}
12491231

12501232
pub fn root_path(&self) -> &AbsPathBuf {
@@ -2325,43 +2307,83 @@ macro_rules! _default_str {
23252307

23262308
macro_rules! _config_data {
23272309
// modname is for the tests
2328-
($modname:ident: struct $name:ident <- $input:ident {
2310+
($modname:ident: struct $name:ident <- $input:ident -> $root:ident {
23292311
$(
23302312
$(#[doc=$doc:literal])*
23312313
$field:ident $(| $alias:ident)*: $ty:ty = $(@$marker:ident: )? $default:expr,
23322314
)*
23332315
}) => {
2316+
/// All fields raw `T`, representing either a root config, or a root config + overrides from
2317+
/// some distal configuration blob(s).
23342318
#[allow(non_snake_case)]
23352319
#[derive(Debug, Clone, Serialize)]
23362320
struct $name { $($field: $ty,)* }
23372321

2322+
/// All fields `Option<T>`, `None` representing fields not set in a particular JSON/TOML blob.
23382323
#[allow(non_snake_case)]
2339-
#[derive(Debug, Clone, Serialize)]
2340-
struct $input { $($field: Option<$ty>,)* }
2324+
#[derive(Debug, Clone, Serialize, Default)]
2325+
struct $input { $(
2326+
#[serde(skip_serializing_if = "Option::is_none")]
2327+
$field: Option<$ty>,
2328+
)* }
2329+
2330+
/// Newtype of
2331+
#[doc = stringify!($name)]
2332+
/// expressing that this was read directly from a single, root config blob.
2333+
#[derive(Debug, Clone, Default)]
2334+
struct $root($name);
2335+
2336+
impl $root {
2337+
/// Reads a single root config blob. All fields are either set by the config blob, or to the
2338+
/// default value.
2339+
fn from_root_input(input: $input) -> Self {
2340+
let mut data = $name::default();
2341+
data.apply_input(input);
2342+
Self(data)
2343+
}
2344+
}
2345+
2346+
impl Default for $name {
2347+
fn default() -> Self {
2348+
$name {$(
2349+
$field: default_val!($(@$marker:)? $default, $ty),
2350+
)*}
2351+
}
2352+
}
23412353

23422354
impl $name {
2355+
/// Applies overrides from some more local config blob, to self.
23432356
#[allow(unused)]
2344-
fn from_json(json: &mut serde_json::Value, error_sink: &mut Vec<(String, serde_json::Error)>) -> $name {
2345-
$name {$(
2357+
fn apply_input(&mut self, input: $input) {
2358+
$(
2359+
if let Some(value) = input.$field {
2360+
self.$field = value;
2361+
}
2362+
)*
2363+
}
2364+
}
2365+
2366+
impl $input {
2367+
#[allow(unused)]
2368+
fn from_json(json: &mut serde_json::Value, error_sink: &mut Vec<(String, serde_json::Error)>) -> Self {
2369+
Self {$(
23462370
$field: get_field(
23472371
json,
23482372
error_sink,
23492373
stringify!($field),
23502374
None$(.or(Some(stringify!($alias))))*,
2351-
default_val!($(@$marker:)? $default, $ty),
23522375
),
23532376
)*}
23542377
}
23552378

23562379
#[allow(unused)]
2357-
fn from_toml(toml: &mut toml::Table , error_sink: &mut Vec<(String, toml::de::Error)>) -> $name {
2358-
$name {$(
2380+
fn from_toml(toml: &mut toml::Table , error_sink: &mut Vec<(String, toml::de::Error)>) -> Self {
2381+
Self {$(
23592382
$field: get_field_toml::<$ty>(
23602383
toml,
23612384
error_sink,
23622385
stringify!($field),
23632386
None$(.or(Some(stringify!($alias))))*,
2364-
default_val!($(@$marker:)? $default, $ty),
23652387
),
23662388
)*}
23672389
}
@@ -2377,14 +2399,6 @@ macro_rules! _config_data {
23772399
},)*
23782400
])
23792401
}
2380-
2381-
fn apply_input(&mut self, input: $input) {
2382-
$(
2383-
if let Some(value) = input.$field {
2384-
self.$field = value;
2385-
}
2386-
)*
2387-
}
23882402
}
23892403

23902404
mod $modname {
@@ -2400,7 +2414,8 @@ use _config_data as config_data;
24002414
use _default_str as default_str;
24012415
use _default_val as default_val;
24022416

2403-
#[derive(Debug, Clone, Serialize)]
2417+
/// All of the config levels, all fields raw `T`. Represents a root configuration, or a config set
2418+
#[derive(Debug, Clone, Serialize, Default)]
24042419
struct ConfigData {
24052420
#[serde(flatten)]
24062421
global: GlobalConfigData,
@@ -2410,34 +2425,47 @@ struct ConfigData {
24102425
client: ClientConfigData,
24112426
}
24122427

2413-
impl ConfigData {
2428+
/// All of the config levels, all fields `Option<T>`, to describe fields that are actually set by
2429+
/// some rust-analyzer.toml file or JSON blob. An empty rust-analyzer.toml corresponds to
2430+
/// all fields being None.
2431+
#[derive(Debug, Clone, Serialize, Default)]
2432+
struct ConfigInput {
2433+
#[serde(flatten)]
2434+
global: GlobalConfigInput,
2435+
#[serde(flatten)]
2436+
local: LocalConfigInput,
2437+
#[serde(flatten)]
2438+
client: ClientConfigInput,
2439+
}
2440+
2441+
impl ConfigInput {
24142442
fn from_json(
24152443
mut json: serde_json::Value,
24162444
error_sink: &mut Vec<(String, serde_json::Error)>,
2417-
) -> ConfigData {
2418-
ConfigData {
2419-
global: GlobalConfigData::from_json(&mut json, error_sink),
2420-
local: LocalConfigData::from_json(&mut json, error_sink),
2421-
client: ClientConfigData::from_json(&mut json, error_sink),
2445+
) -> ConfigInput {
2446+
ConfigInput {
2447+
global: GlobalConfigInput::from_json(&mut json, error_sink),
2448+
local: LocalConfigInput::from_json(&mut json, error_sink),
2449+
client: ClientConfigInput::from_json(&mut json, error_sink),
24222450
}
24232451
}
24242452

24252453
fn from_toml(
24262454
mut toml: toml::Table,
24272455
error_sink: &mut Vec<(String, toml::de::Error)>,
2428-
) -> ConfigData {
2429-
ConfigData {
2430-
global: GlobalConfigData::from_toml(&mut toml, error_sink),
2431-
local: LocalConfigData::from_toml(&mut toml, error_sink),
2432-
client: ClientConfigData::from_toml(&mut toml, error_sink),
2456+
) -> ConfigInput {
2457+
ConfigInput {
2458+
global: GlobalConfigInput::from_toml(&mut toml, error_sink),
2459+
local: LocalConfigInput::from_toml(&mut toml, error_sink),
2460+
client: ClientConfigInput::from_toml(&mut toml, error_sink),
24332461
}
24342462
}
24352463

24362464
fn schema_fields() -> Vec<SchemaField> {
24372465
let mut fields = Vec::new();
2438-
GlobalConfigData::schema_fields(&mut fields);
2439-
LocalConfigData::schema_fields(&mut fields);
2440-
ClientConfigData::schema_fields(&mut fields);
2466+
GlobalConfigInput::schema_fields(&mut fields);
2467+
LocalConfigInput::schema_fields(&mut fields);
2468+
ClientConfigInput::schema_fields(&mut fields);
24412469
// HACK: sort the fields, so the diffs on the generated docs/schema are smaller
24422470
fields.sort_by_key(|&(x, ..)| x);
24432471
fields
@@ -2458,8 +2486,7 @@ fn get_field_toml<T: DeserializeOwned>(
24582486
error_sink: &mut Vec<(String, toml::de::Error)>,
24592487
field: &'static str,
24602488
alias: Option<&'static str>,
2461-
default: T,
2462-
) -> T {
2489+
) -> Option<T> {
24632490
alias
24642491
.into_iter()
24652492
.chain(iter::once(field))
@@ -2487,16 +2514,14 @@ fn get_field_toml<T: DeserializeOwned>(
24872514
None
24882515
}
24892516
})
2490-
.unwrap_or(default)
24912517
}
24922518

24932519
fn get_field<T: DeserializeOwned>(
24942520
json: &mut serde_json::Value,
24952521
error_sink: &mut Vec<(String, serde_json::Error)>,
24962522
field: &'static str,
24972523
alias: Option<&'static str>,
2498-
default: T,
2499-
) -> T {
2524+
) -> Option<T> {
25002525
// XXX: check alias first, to work around the VS Code where it pre-fills the
25012526
// defaults instead of sending an empty object.
25022527
alias
@@ -2517,7 +2542,6 @@ fn get_field<T: DeserializeOwned>(
25172542
None
25182543
}
25192544
})
2520-
.unwrap_or(default)
25212545
}
25222546

25232547
type SchemaField = (&'static str, &'static str, &'static [&'static str], String);
@@ -2978,7 +3002,7 @@ mod tests {
29783002
#[test]
29793003
fn generate_config_documentation() {
29803004
let docs_path = project_root().join("docs/user/generated_config.adoc");
2981-
let expected = ConfigData::manual();
3005+
let expected = ConfigInput::manual();
29823006
ensure_file_contents(&docs_path, &expected);
29833007
}
29843008

0 commit comments

Comments
 (0)