@@ -60,7 +60,7 @@ mod patch_old_style;
60
60
// To deprecate an option by replacing it with another name use `new_name | `old_name` so that we keep
61
61
// parsing the old name.
62
62
config_data ! {
63
- global: struct GlobalConfigData <- GlobalConfigInput {
63
+ global: struct GlobalConfigData <- GlobalConfigInput -> RootGlobalConfigData {
64
64
/// Whether to insert #[must_use] when generating `as_` methods
65
65
/// for enum variants.
66
66
assist_emitMustUse: bool = false ,
@@ -366,7 +366,7 @@ config_data! {
366
366
}
367
367
368
368
config_data ! {
369
- local: struct LocalConfigData <- LocalConfigInput {
369
+ local: struct LocalConfigData <- LocalConfigInput -> RootLocalConfigData {
370
370
/// Toggles the additional completions that automatically add imports when completed.
371
371
/// Note that your client must specify the `additionalTextEdits` LSP client capability to truly have this feature enabled.
372
372
completion_autoimport_enable: bool = true ,
@@ -583,44 +583,25 @@ config_data! {
583
583
}
584
584
585
585
config_data ! {
586
- client: struct ClientConfigData <- ClientConfigInput { }
586
+ client: struct ClientConfigData <- ClientConfigInput -> RootClientConfigData { }
587
587
}
588
588
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 ) ]
603
590
struct RootConfigData {
604
591
local : RootLocalConfigData ,
605
592
global : RootGlobalConfigData ,
606
593
client : RootClientConfigData ,
607
594
}
608
595
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) ,
624
605
}
625
606
}
626
607
}
@@ -1188,13 +1169,14 @@ impl Config {
1188
1169
}
1189
1170
let mut errors = Vec :: new ( ) ;
1190
1171
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 ( )
1192
1174
. into_iter ( )
1193
1175
. map ( AbsPathBuf :: assert)
1194
1176
. collect ( ) ;
1195
1177
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 ) ;
1198
1180
tracing:: debug!( "deserialized config data: {:#?}" , self . root_config. global) ;
1199
1181
self . snippets . clear ( ) ;
1200
1182
for ( name, def) in self . root_config . local . 0 . completion_snippets_custom . iter ( ) {
@@ -1244,7 +1226,7 @@ impl Config {
1244
1226
}
1245
1227
1246
1228
pub fn json_schema ( ) -> serde_json:: Value {
1247
- ConfigData :: json_schema ( )
1229
+ ConfigInput :: json_schema ( )
1248
1230
}
1249
1231
1250
1232
pub fn root_path ( & self ) -> & AbsPathBuf {
@@ -2325,43 +2307,83 @@ macro_rules! _default_str {
2325
2307
2326
2308
macro_rules! _config_data {
2327
2309
// modname is for the tests
2328
- ( $modname: ident: struct $name: ident <- $input: ident {
2310
+ ( $modname: ident: struct $name: ident <- $input: ident -> $root : ident {
2329
2311
$(
2330
2312
$( #[ doc=$doc: literal] ) *
2331
2313
$field: ident $( | $alias: ident) * : $ty: ty = $( @$marker: ident: ) ? $default: expr,
2332
2314
) *
2333
2315
} ) => {
2316
+ /// All fields raw `T`, representing either a root config, or a root config + overrides from
2317
+ /// some distal configuration blob(s).
2334
2318
#[ allow( non_snake_case) ]
2335
2319
#[ derive( Debug , Clone , Serialize ) ]
2336
2320
struct $name { $( $field: $ty, ) * }
2337
2321
2322
+ /// All fields `Option<T>`, `None` representing fields not set in a particular JSON/TOML blob.
2338
2323
#[ 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
+ }
2341
2353
2342
2354
impl $name {
2355
+ /// Applies overrides from some more local config blob, to self.
2343
2356
#[ 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 { $(
2346
2370
$field: get_field(
2347
2371
json,
2348
2372
error_sink,
2349
2373
stringify!( $field) ,
2350
2374
None $( . or( Some ( stringify!( $alias) ) ) ) * ,
2351
- default_val!( $( @$marker: ) ? $default, $ty) ,
2352
2375
) ,
2353
2376
) * }
2354
2377
}
2355
2378
2356
2379
#[ 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 { $(
2359
2382
$field: get_field_toml:: <$ty>(
2360
2383
toml,
2361
2384
error_sink,
2362
2385
stringify!( $field) ,
2363
2386
None $( . or( Some ( stringify!( $alias) ) ) ) * ,
2364
- default_val!( $( @$marker: ) ? $default, $ty) ,
2365
2387
) ,
2366
2388
) * }
2367
2389
}
@@ -2377,14 +2399,6 @@ macro_rules! _config_data {
2377
2399
} , ) *
2378
2400
] )
2379
2401
}
2380
-
2381
- fn apply_input( & mut self , input: $input) {
2382
- $(
2383
- if let Some ( value) = input. $field {
2384
- self . $field = value;
2385
- }
2386
- ) *
2387
- }
2388
2402
}
2389
2403
2390
2404
mod $modname {
@@ -2400,7 +2414,8 @@ use _config_data as config_data;
2400
2414
use _default_str as default_str;
2401
2415
use _default_val as default_val;
2402
2416
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 ) ]
2404
2419
struct ConfigData {
2405
2420
#[ serde( flatten) ]
2406
2421
global : GlobalConfigData ,
@@ -2410,34 +2425,47 @@ struct ConfigData {
2410
2425
client : ClientConfigData ,
2411
2426
}
2412
2427
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 {
2414
2442
fn from_json (
2415
2443
mut json : serde_json:: Value ,
2416
2444
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) ,
2422
2450
}
2423
2451
}
2424
2452
2425
2453
fn from_toml (
2426
2454
mut toml : toml:: Table ,
2427
2455
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) ,
2433
2461
}
2434
2462
}
2435
2463
2436
2464
fn schema_fields ( ) -> Vec < SchemaField > {
2437
2465
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) ;
2441
2469
// HACK: sort the fields, so the diffs on the generated docs/schema are smaller
2442
2470
fields. sort_by_key ( |& ( x, ..) | x) ;
2443
2471
fields
@@ -2458,8 +2486,7 @@ fn get_field_toml<T: DeserializeOwned>(
2458
2486
error_sink : & mut Vec < ( String , toml:: de:: Error ) > ,
2459
2487
field : & ' static str ,
2460
2488
alias : Option < & ' static str > ,
2461
- default : T ,
2462
- ) -> T {
2489
+ ) -> Option < T > {
2463
2490
alias
2464
2491
. into_iter ( )
2465
2492
. chain ( iter:: once ( field) )
@@ -2487,16 +2514,14 @@ fn get_field_toml<T: DeserializeOwned>(
2487
2514
None
2488
2515
}
2489
2516
} )
2490
- . unwrap_or ( default)
2491
2517
}
2492
2518
2493
2519
fn get_field < T : DeserializeOwned > (
2494
2520
json : & mut serde_json:: Value ,
2495
2521
error_sink : & mut Vec < ( String , serde_json:: Error ) > ,
2496
2522
field : & ' static str ,
2497
2523
alias : Option < & ' static str > ,
2498
- default : T ,
2499
- ) -> T {
2524
+ ) -> Option < T > {
2500
2525
// XXX: check alias first, to work around the VS Code where it pre-fills the
2501
2526
// defaults instead of sending an empty object.
2502
2527
alias
@@ -2517,7 +2542,6 @@ fn get_field<T: DeserializeOwned>(
2517
2542
None
2518
2543
}
2519
2544
} )
2520
- . unwrap_or ( default)
2521
2545
}
2522
2546
2523
2547
type SchemaField = ( & ' static str , & ' static str , & ' static [ & ' static str ] , String ) ;
@@ -2978,7 +3002,7 @@ mod tests {
2978
3002
#[ test]
2979
3003
fn generate_config_documentation ( ) {
2980
3004
let docs_path = project_root ( ) . join ( "docs/user/generated_config.adoc" ) ;
2981
- let expected = ConfigData :: manual ( ) ;
3005
+ let expected = ConfigInput :: manual ( ) ;
2982
3006
ensure_file_contents ( & docs_path, & expected) ;
2983
3007
}
2984
3008
0 commit comments