@@ -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 {
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 {
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 { }
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,38 +2307,102 @@ 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 {
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, ) * }
2321
+
2322
+ /// All fields `Option<T>`, `None` representing fields not set in a particular JSON/TOML blob.
2323
+ #[ allow( non_snake_case) ]
2324
+ #[ derive( Clone , Serialize , Default ) ]
2325
+ struct $input { $(
2326
+ #[ serde( skip_serializing_if = "Option::is_none" ) ]
2327
+ $field: Option <$ty>,
2328
+ ) * }
2329
+
2330
+ impl std:: fmt:: Debug for $input {
2331
+ fn fmt( & self , f: & mut std:: fmt:: Formatter <' _>) -> std:: fmt:: Result {
2332
+ let mut s = f. debug_struct( stringify!( $input) ) ;
2333
+ $(
2334
+ if let Some ( val) = self . $field. as_ref( ) {
2335
+ s. field( stringify!( $field) , val) ;
2336
+ }
2337
+ ) *
2338
+ s. finish( )
2339
+ }
2340
+ }
2341
+
2342
+ /// Newtype of
2343
+ #[ doc = stringify!( $name) ]
2344
+ /// expressing that this was read directly from a single, root config blob.
2345
+ #[ derive( Debug , Clone , Default ) ]
2346
+ struct $root( $name) ;
2347
+
2348
+ impl $root {
2349
+ /// Reads a single root config blob. All fields are either set by the config blob, or to the
2350
+ /// default value.
2351
+ fn from_root_input( input: $input) -> Self {
2352
+ let mut data = $name:: default ( ) ;
2353
+ data. apply_input( input) ;
2354
+ Self ( data)
2355
+ }
2356
+ }
2357
+
2358
+ impl Default for $name {
2359
+ fn default ( ) -> Self {
2360
+ $name { $(
2361
+ $field: default_val!( $( @$marker: ) ? $default, $ty) ,
2362
+ ) * }
2363
+ }
2364
+ }
2365
+
2337
2366
impl $name {
2367
+ /// Applies overrides from some more local config blob, to self.
2338
2368
#[ allow( unused) ]
2339
- fn from_json( json: & mut serde_json:: Value , error_sink: & mut Vec <( String , serde_json:: Error ) >) -> $name {
2340
- $name { $(
2369
+ fn apply_input( & mut self , input: $input) {
2370
+ $(
2371
+ if let Some ( value) = input. $field {
2372
+ self . $field = value;
2373
+ }
2374
+ ) *
2375
+ }
2376
+
2377
+ #[ allow( unused) ]
2378
+ fn clone_with_overrides( & self , input: $input) -> Self {
2379
+ Self { $(
2380
+ $field: input. $field. unwrap_or_else( || self . $field. clone( ) ) ,
2381
+ ) * }
2382
+ }
2383
+ }
2384
+
2385
+ impl $input {
2386
+ #[ allow( unused) ]
2387
+ fn from_json( json: & mut serde_json:: Value , error_sink: & mut Vec <( String , serde_json:: Error ) >) -> Self {
2388
+ Self { $(
2341
2389
$field: get_field(
2342
2390
json,
2343
2391
error_sink,
2344
2392
stringify!( $field) ,
2345
2393
None $( . or( Some ( stringify!( $alias) ) ) ) * ,
2346
- default_val!( $( @$marker: ) ? $default, $ty) ,
2347
2394
) ,
2348
2395
) * }
2349
2396
}
2350
2397
2351
2398
#[ allow( unused) ]
2352
- fn from_toml( toml: & mut toml:: Table , error_sink: & mut Vec <( String , toml:: de:: Error ) >) -> $name {
2353
- $name { $(
2399
+ fn from_toml( toml: & mut toml:: Table , error_sink: & mut Vec <( String , toml:: de:: Error ) >) -> Self {
2400
+ Self { $(
2354
2401
$field: get_field_toml:: <$ty>(
2355
2402
toml,
2356
2403
error_sink,
2357
2404
stringify!( $field) ,
2358
2405
None $( . or( Some ( stringify!( $alias) ) ) ) * ,
2359
- default_val!( $( @$marker: ) ? $default, $ty) ,
2360
2406
) ,
2361
2407
) * }
2362
2408
}
@@ -2387,7 +2433,8 @@ use _config_data as config_data;
2387
2433
use _default_str as default_str;
2388
2434
use _default_val as default_val;
2389
2435
2390
- #[ derive( Debug , Clone , Serialize ) ]
2436
+ /// All of the config levels, all fields raw `T`. Represents a root configuration, or a config set
2437
+ #[ derive( Debug , Clone , Serialize , Default ) ]
2391
2438
struct ConfigData {
2392
2439
#[ serde( flatten) ]
2393
2440
global : GlobalConfigData ,
@@ -2397,34 +2444,47 @@ struct ConfigData {
2397
2444
client : ClientConfigData ,
2398
2445
}
2399
2446
2400
- impl ConfigData {
2447
+ /// All of the config levels, all fields `Option<T>`, to describe fields that are actually set by
2448
+ /// some rust-analyzer.toml file or JSON blob. An empty rust-analyzer.toml corresponds to
2449
+ /// all fields being None.
2450
+ #[ derive( Debug , Clone , Serialize , Default ) ]
2451
+ struct ConfigInput {
2452
+ #[ serde( flatten) ]
2453
+ global : GlobalConfigInput ,
2454
+ #[ serde( flatten) ]
2455
+ local : LocalConfigInput ,
2456
+ #[ serde( flatten) ]
2457
+ client : ClientConfigInput ,
2458
+ }
2459
+
2460
+ impl ConfigInput {
2401
2461
fn from_json (
2402
2462
mut json : serde_json:: Value ,
2403
2463
error_sink : & mut Vec < ( String , serde_json:: Error ) > ,
2404
- ) -> ConfigData {
2405
- ConfigData {
2406
- global : GlobalConfigData :: from_json ( & mut json, error_sink) ,
2407
- local : LocalConfigData :: from_json ( & mut json, error_sink) ,
2408
- client : ClientConfigData :: from_json ( & mut json, error_sink) ,
2464
+ ) -> ConfigInput {
2465
+ ConfigInput {
2466
+ global : GlobalConfigInput :: from_json ( & mut json, error_sink) ,
2467
+ local : LocalConfigInput :: from_json ( & mut json, error_sink) ,
2468
+ client : ClientConfigInput :: from_json ( & mut json, error_sink) ,
2409
2469
}
2410
2470
}
2411
2471
2412
2472
fn from_toml (
2413
2473
mut toml : toml:: Table ,
2414
2474
error_sink : & mut Vec < ( String , toml:: de:: Error ) > ,
2415
- ) -> ConfigData {
2416
- ConfigData {
2417
- global : GlobalConfigData :: from_toml ( & mut toml, error_sink) ,
2418
- local : LocalConfigData :: from_toml ( & mut toml, error_sink) ,
2419
- client : ClientConfigData :: from_toml ( & mut toml, error_sink) ,
2475
+ ) -> ConfigInput {
2476
+ ConfigInput {
2477
+ global : GlobalConfigInput :: from_toml ( & mut toml, error_sink) ,
2478
+ local : LocalConfigInput :: from_toml ( & mut toml, error_sink) ,
2479
+ client : ClientConfigInput :: from_toml ( & mut toml, error_sink) ,
2420
2480
}
2421
2481
}
2422
2482
2423
2483
fn schema_fields ( ) -> Vec < SchemaField > {
2424
2484
let mut fields = Vec :: new ( ) ;
2425
- GlobalConfigData :: schema_fields ( & mut fields) ;
2426
- LocalConfigData :: schema_fields ( & mut fields) ;
2427
- ClientConfigData :: schema_fields ( & mut fields) ;
2485
+ GlobalConfigInput :: schema_fields ( & mut fields) ;
2486
+ LocalConfigInput :: schema_fields ( & mut fields) ;
2487
+ ClientConfigInput :: schema_fields ( & mut fields) ;
2428
2488
// HACK: sort the fields, so the diffs on the generated docs/schema are smaller
2429
2489
fields. sort_by_key ( |& ( x, ..) | x) ;
2430
2490
fields
@@ -2445,8 +2505,7 @@ fn get_field_toml<T: DeserializeOwned>(
2445
2505
error_sink : & mut Vec < ( String , toml:: de:: Error ) > ,
2446
2506
field : & ' static str ,
2447
2507
alias : Option < & ' static str > ,
2448
- default : T ,
2449
- ) -> T {
2508
+ ) -> Option < T > {
2450
2509
alias
2451
2510
. into_iter ( )
2452
2511
. chain ( iter:: once ( field) )
@@ -2474,16 +2533,14 @@ fn get_field_toml<T: DeserializeOwned>(
2474
2533
None
2475
2534
}
2476
2535
} )
2477
- . unwrap_or ( default)
2478
2536
}
2479
2537
2480
2538
fn get_field < T : DeserializeOwned > (
2481
2539
json : & mut serde_json:: Value ,
2482
2540
error_sink : & mut Vec < ( String , serde_json:: Error ) > ,
2483
2541
field : & ' static str ,
2484
2542
alias : Option < & ' static str > ,
2485
- default : T ,
2486
- ) -> T {
2543
+ ) -> Option < T > {
2487
2544
// XXX: check alias first, to work around the VS Code where it pre-fills the
2488
2545
// defaults instead of sending an empty object.
2489
2546
alias
@@ -2504,7 +2561,6 @@ fn get_field<T: DeserializeOwned>(
2504
2561
None
2505
2562
}
2506
2563
} )
2507
- . unwrap_or ( default)
2508
2564
}
2509
2565
2510
2566
type SchemaField = ( & ' static str , & ' static str , & ' static [ & ' static str ] , String ) ;
@@ -2965,7 +3021,7 @@ mod tests {
2965
3021
#[ test]
2966
3022
fn generate_config_documentation ( ) {
2967
3023
let docs_path = project_root ( ) . join ( "docs/user/generated_config.adoc" ) ;
2968
- let expected = ConfigData :: manual ( ) ;
3024
+ let expected = ConfigInput :: manual ( ) ;
2969
3025
ensure_file_contents ( & docs_path, & expected) ;
2970
3026
}
2971
3027
0 commit comments