@@ -41,7 +41,7 @@ pub struct ConfigChanges {
41
41
/// - `Some(None)` => the client config was removed / reset or something
42
42
/// - `Some(Some(...))` => the client config was updated
43
43
client_change : Option < Option < Arc < ConfigInput > > > ,
44
- parent_changes : Vec < ConfigParentChange > ,
44
+ parent_changes : FxHashMap < FileId , ConfigParent > ,
45
45
}
46
46
47
47
#[ derive( Debug ) ]
@@ -103,7 +103,7 @@ impl ConcurrentConfigTree {
103
103
104
104
#[ derive( Clone , Copy , Debug , PartialEq , Eq , Hash ) ]
105
105
enum ConfigSource {
106
- ClientConfig ,
106
+ XdgConfig ( FileId ) ,
107
107
RaToml ( FileId ) ,
108
108
}
109
109
@@ -115,12 +115,13 @@ slotmap::new_key_type! {
115
115
struct ConfigNode {
116
116
src : ConfigSource ,
117
117
input : Option < Arc < ConfigInput > > ,
118
- computed : ComputedIdx ,
118
+ computed_idx : ComputedIdx ,
119
119
}
120
120
121
121
struct ConfigTree {
122
122
tree : indextree:: Arena < ConfigNode > ,
123
123
client_config : Option < Arc < ConfigInput > > ,
124
+ xdg_config_file_id : FileId ,
124
125
xdg_config_node_id : NodeId ,
125
126
ra_file_id_map : FxHashMap < FileId , NodeId > ,
126
127
computed : SlotMap < ComputedIdx , Option < Arc < LocalConfigData > > > ,
@@ -164,14 +165,21 @@ impl ConfigTree {
164
165
let mut tree = indextree:: Arena :: new ( ) ;
165
166
let mut computed = SlotMap :: default ( ) ;
166
167
let mut ra_file_id_map = FxHashMap :: default ( ) ;
167
- let xdg_config = tree. new_node ( ConfigNode {
168
- src : ConfigSource :: RaToml ( xdg_config_file_id) ,
168
+ let xdg_config_node_id = tree. new_node ( ConfigNode {
169
+ src : ConfigSource :: XdgConfig ( xdg_config_file_id) ,
169
170
input : None ,
170
- computed : computed. insert ( Option :: < Arc < LocalConfigData > > :: None ) ,
171
+ computed_idx : computed. insert ( Option :: < Arc < LocalConfigData > > :: None ) ,
171
172
} ) ;
172
- ra_file_id_map. insert ( xdg_config_file_id, xdg_config ) ;
173
+ ra_file_id_map. insert ( xdg_config_file_id, xdg_config_node_id ) ;
173
174
174
- Self { client_config : None , xdg_config_node_id : xdg_config, ra_file_id_map, tree, computed }
175
+ Self {
176
+ client_config : None ,
177
+ xdg_config_file_id,
178
+ xdg_config_node_id,
179
+ ra_file_id_map,
180
+ tree,
181
+ computed,
182
+ }
175
183
}
176
184
177
185
fn read_only ( & self , file_id : FileId ) -> Result < Option < Arc < LocalConfigData > > , ConfigTreeError > {
@@ -196,7 +204,12 @@ impl ConfigTree {
196
204
return Err ( ConfigTreeError :: Removed ) ;
197
205
}
198
206
let node = self . tree . get ( node_id) . ok_or ( ConfigTreeError :: NonExistent ) ?. get ( ) ;
199
- let stored = self . computed [ node. computed ] . clone ( ) ;
207
+ let stored = self . computed [ node. computed_idx ] . clone ( ) ;
208
+ tracing:: trace!(
209
+ "read_only_inner on {:?} got {:?}" ,
210
+ node. src,
211
+ stored. as_ref( ) . map( |_| "some stored value" )
212
+ ) ;
200
213
Ok ( stored)
201
214
}
202
215
@@ -214,7 +227,8 @@ impl ConfigTree {
214
227
return Err ( ConfigTreeError :: Removed ) ;
215
228
}
216
229
let node = self . tree . get ( node_id) . ok_or ( ConfigTreeError :: NonExistent ) ?. get ( ) ;
217
- let idx = node. computed ;
230
+ tracing:: trace!( "compute_inner on {:?}" , node. src) ;
231
+ let idx = node. computed_idx ;
218
232
let slot = & mut self . computed [ idx] ;
219
233
if let Some ( slot) = slot {
220
234
Ok ( slot. clone ( ) )
@@ -250,12 +264,17 @@ impl ConfigTree {
250
264
251
265
fn insert_toml ( & mut self , file_id : FileId , input : Option < Arc < ConfigInput > > ) -> NodeId {
252
266
let computed = self . computed . insert ( None ) ;
253
- let node =
254
- self . tree . new_node ( ConfigNode { src : ConfigSource :: RaToml ( file_id) , input, computed } ) ;
255
- if let Some ( _removed) = self . ra_file_id_map . insert ( file_id, node) {
267
+ let node_id = self . tree . new_node ( ConfigNode {
268
+ src : ConfigSource :: RaToml ( file_id) ,
269
+ input,
270
+ computed_idx : computed,
271
+ } ) ;
272
+ if let Some ( _removed) = self . ra_file_id_map . insert ( file_id, node_id) {
256
273
panic ! ( "ERROR: node should not have existed for {file_id:?} but it did" ) ;
257
274
}
258
- node
275
+ // By default, everything is under the xdg_config_node_id
276
+ self . xdg_config_node_id . append ( node_id, & mut self . tree ) ;
277
+ node_id
259
278
}
260
279
261
280
fn update_toml (
@@ -274,6 +293,7 @@ impl ConfigTree {
274
293
node. get_mut ( ) . input = input;
275
294
276
295
self . invalidate_subtree ( node_id) ;
296
+ // tracing::trace!("invalidated subtree:\n{:#?}", node_id.debug_pretty_print(&self.tree));
277
297
Ok ( node_id)
278
298
}
279
299
@@ -292,7 +312,16 @@ impl ConfigTree {
292
312
let Some ( desc) = self . tree . get ( x) else {
293
313
return ;
294
314
} ;
295
- self . computed . get_mut ( desc. get ( ) . computed ) . take ( ) ;
315
+ let desc = desc. get ( ) ;
316
+ let Some ( slot) = self . computed . get_mut ( desc. computed_idx ) else {
317
+ tracing:: error!(
318
+ "computed_idx missing from computed local config slotmap: {:?}" ,
319
+ desc. computed_idx
320
+ ) ;
321
+ return ;
322
+ } ;
323
+ tracing:: trace!( "invalidating {x:?} / {:?}" , desc. src) ;
324
+ slot. take ( ) ;
296
325
} ) ;
297
326
}
298
327
@@ -314,32 +343,22 @@ impl ConfigTree {
314
343
errors : & mut Vec < ConfigTreeError > ,
315
344
) {
316
345
let mut scratch_errors = Vec :: new ( ) ;
317
- let ConfigChanges { client_change, ra_toml_changes, parent_changes } = changes;
346
+ let ConfigChanges { client_change, ra_toml_changes, mut parent_changes } = changes;
318
347
319
348
if let Some ( change) = client_change {
320
349
self . client_config = change;
321
350
}
322
351
323
- for ConfigParentChange { file_id, parent } in parent_changes {
324
- let node_id = self . ensure_node ( file_id) ;
325
- let parent_node_id = match parent {
326
- ConfigParent :: UserDefault => self . xdg_config_node_id ,
327
- ConfigParent :: Parent ( parent_file_id) => self . ensure_node ( parent_file_id) ,
328
- } ;
329
- // order of children within the parent node does not matter
330
- tracing:: trace!( "appending child {node_id:?} to {parent_node_id:?}" ) ;
331
- parent_node_id. append ( node_id, & mut self . tree ) ;
332
- }
333
-
334
352
for change in ra_toml_changes {
335
353
// turn and face the strain
336
354
match change. change_kind {
337
- vfs:: ChangeKind :: Create => {
338
- let input = parse_toml ( change. file_id , vfs, & mut scratch_errors, errors) ;
339
- let _new_node = self . update_toml ( change. file_id , input) ;
340
- }
341
- vfs:: ChangeKind :: Modify => {
355
+ vfs:: ChangeKind :: Create | vfs:: ChangeKind :: Modify => {
356
+ if change. change_kind == vfs:: ChangeKind :: Create {
357
+ parent_changes. entry ( change. file_id ) . or_insert ( ConfigParent :: UserDefault ) ;
358
+ }
342
359
let input = parse_toml ( change. file_id , vfs, & mut scratch_errors, errors) ;
360
+ tracing:: trace!( "updating toml for {:?} to {:?}" , change. file_id, input) ;
361
+
343
362
if let Err ( e) = self . update_toml ( change. file_id , input) {
344
363
errors. push ( e) ;
345
364
}
@@ -349,6 +368,18 @@ impl ConfigTree {
349
368
}
350
369
}
351
370
}
371
+
372
+ for ( file_id, parent) in parent_changes {
373
+ let node_id = self . ensure_node ( file_id) ;
374
+ let parent_node_id = match parent {
375
+ ConfigParent :: Parent ( parent_file_id) => self . ensure_node ( parent_file_id) ,
376
+ ConfigParent :: UserDefault if file_id == self . xdg_config_file_id => continue ,
377
+ ConfigParent :: UserDefault => self . xdg_config_node_id ,
378
+ } ;
379
+ // order of children within the parent node does not matter
380
+ tracing:: trace!( "appending child {node_id:?} to {parent_node_id:?}" ) ;
381
+ parent_node_id. append ( node_id, & mut self . tree ) ;
382
+ }
352
383
}
353
384
}
354
385
@@ -365,6 +396,7 @@ mod tests {
365
396
use vfs:: { AbsPathBuf , VfsPath } ;
366
397
367
398
fn alloc_file_id ( vfs : & mut Vfs , s : & str ) -> FileId {
399
+ tracing_subscriber:: fmt ( ) . init ( ) ;
368
400
let abs_path = AbsPathBuf :: try_from ( PathBuf :: new ( ) . join ( s) ) . unwrap ( ) ;
369
401
370
402
let vfs_path = VfsPath :: from ( abs_path) ;
@@ -391,7 +423,7 @@ mod tests {
391
423
fn basic ( ) {
392
424
let mut vfs = Vfs :: default ( ) ;
393
425
let xdg_config_file_id =
394
- alloc_file_id ( & mut vfs, "/home/.config/rust-analyzer/rust-analyzer.toml" ) ;
426
+ alloc_file_id ( & mut vfs, "/home/username/ .config/rust-analyzer/rust-analyzer.toml" ) ;
395
427
let config_tree = ConcurrentConfigTree :: new ( ConfigTree :: new ( xdg_config_file_id) ) ;
396
428
397
429
let root = alloc_config (
@@ -415,8 +447,8 @@ mod tests {
415
447
"# ,
416
448
) ;
417
449
418
- let parent_changes =
419
- vec ! [ ConfigParentChange { file_id : crate_a, parent : ConfigParent :: Parent ( root) } ] ;
450
+ let mut parent_changes = FxHashMap :: default ( ) ;
451
+ parent_changes . insert ( crate_a, ConfigParent :: Parent ( root) ) ;
420
452
421
453
let changes = ConfigChanges {
422
454
// Normally you will filter these!
@@ -432,7 +464,6 @@ mod tests {
432
464
} ;
433
465
434
466
dbg ! ( config_tree. apply_changes( changes, & vfs) ) ;
435
- dbg ! ( & config_tree) ;
436
467
437
468
let local = config_tree. read_config ( crate_a) . unwrap ( ) ;
438
469
// from root
@@ -442,6 +473,9 @@ mod tests {
442
473
// from client
443
474
assert_eq ! ( local. semanticHighlighting_strings_enable, false ) ;
444
475
476
+ // --------------------------------------------------------
477
+
478
+ // Now let's modify the xdg_config_file_id, which should invalidate everything else
445
479
vfs. set_file_id_contents (
446
480
xdg_config_file_id,
447
481
Some (
@@ -456,15 +490,14 @@ mod tests {
456
490
) ;
457
491
458
492
let changes = ConfigChanges {
459
- ra_toml_changes : vfs. take_changes ( ) ,
460
- parent_changes : vec ! [ ] ,
493
+ ra_toml_changes : dbg ! ( vfs. take_changes( ) ) ,
494
+ parent_changes : Default :: default ( ) ,
461
495
client_change : None ,
462
496
} ;
463
497
dbg ! ( config_tree. apply_changes( changes, & vfs) ) ;
464
498
465
- let local2 = config_tree. read_config ( crate_a) . unwrap ( ) ;
466
- // should have recomputed
467
- assert ! ( !Arc :: ptr_eq( & local, & local2) ) ;
499
+ let prev = local;
500
+ let local = config_tree. read_config ( crate_a) . unwrap ( ) ;
468
501
469
502
assert_eq ! (
470
503
local. inlayHints_discriminantHints_enable,
0 commit comments