@@ -125,6 +125,7 @@ struct ConfigTree {
125
125
xdg_config_node_id : NodeId ,
126
126
ra_file_id_map : FxHashMap < FileId , NodeId > ,
127
127
computed : SlotMap < ComputedIdx , Option < Arc < LocalConfigData > > > ,
128
+ with_client_config : slotmap:: SecondaryMap < ComputedIdx , Arc < LocalConfigData > > ,
128
129
}
129
130
130
131
fn parse_toml (
@@ -179,19 +180,13 @@ impl ConfigTree {
179
180
ra_file_id_map,
180
181
tree,
181
182
computed,
183
+ with_client_config : Default :: default ( ) ,
182
184
}
183
185
}
184
186
185
187
fn read_only ( & self , file_id : FileId ) -> Result < Option < Arc < LocalConfigData > > , ConfigTreeError > {
186
188
let node_id = * self . ra_file_id_map . get ( & file_id) . ok_or ( ConfigTreeError :: NonExistent ) ?;
187
- let stored = self . read_only_inner ( node_id) ?;
188
- Ok ( stored. map ( |stored| {
189
- if let Some ( client_config) = self . client_config . as_deref ( ) {
190
- stored. clone_with_overrides ( client_config. local . clone ( ) ) . into ( )
191
- } else {
192
- stored
193
- }
194
- } ) )
189
+ self . read_only_inner ( node_id)
195
190
}
196
191
197
192
fn read_only_inner (
@@ -204,7 +199,7 @@ impl ConfigTree {
204
199
return Err ( ConfigTreeError :: Removed ) ;
205
200
}
206
201
let node = self . tree . get ( node_id) . ok_or ( ConfigTreeError :: NonExistent ) ?. get ( ) ;
207
- let stored = self . computed [ node. computed_idx ] . clone ( ) ;
202
+ let stored = self . with_client_config . get ( node. computed_idx ) . cloned ( ) ;
208
203
tracing:: trace!(
209
204
"read_only_inner on {:?} got {:?}" ,
210
205
node. src,
@@ -215,14 +210,19 @@ impl ConfigTree {
215
210
216
211
fn compute ( & mut self , file_id : FileId ) -> Result < Arc < LocalConfigData > , ConfigTreeError > {
217
212
let node_id = * self . ra_file_id_map . get ( & file_id) . ok_or ( ConfigTreeError :: NonExistent ) ?;
218
- let computed = self . compute_inner ( node_id) ?;
219
- Ok ( if let Some ( client_config) = self . client_config . as_deref ( ) {
220
- computed. clone_with_overrides ( client_config. local . clone ( ) ) . into ( )
213
+ let ( computed, idx ) = self . compute_recursive ( node_id) ?;
214
+ let out = if let Some ( client_config) = self . client_config . as_deref ( ) {
215
+ Arc :: new ( computed. clone_with_overrides ( client_config. local . clone ( ) ) )
221
216
} else {
222
217
computed
223
- } )
218
+ } ;
219
+ self . with_client_config . insert ( idx, out. clone ( ) ) ;
220
+ Ok ( out)
224
221
}
225
- fn compute_inner ( & mut self , node_id : NodeId ) -> Result < Arc < LocalConfigData > , ConfigTreeError > {
222
+ fn compute_recursive (
223
+ & mut self ,
224
+ node_id : NodeId ,
225
+ ) -> Result < ( Arc < LocalConfigData > , ComputedIdx ) , ConfigTreeError > {
226
226
if node_id. is_removed ( & self . tree ) {
227
227
return Err ( ConfigTreeError :: Removed ) ;
228
228
}
@@ -231,14 +231,14 @@ impl ConfigTree {
231
231
let idx = node. computed_idx ;
232
232
let slot = & mut self . computed [ idx] ;
233
233
if let Some ( slot) = slot {
234
- Ok ( slot. clone ( ) )
234
+ Ok ( ( slot. clone ( ) , idx ) )
235
235
} else {
236
236
let self_computed = if let Some ( parent) =
237
237
self . tree . get ( node_id) . ok_or ( ConfigTreeError :: NonExistent ) ?. parent ( )
238
238
{
239
239
tracing:: trace!( "looking at parent of {node_id:?} -> {parent:?}" ) ;
240
240
let self_input = node. input . clone ( ) ;
241
- let parent_computed = self . compute_inner ( parent) ?;
241
+ let ( parent_computed, _ ) = self . compute_recursive ( parent) ?;
242
242
if let Some ( input) = self_input. as_deref ( ) {
243
243
Arc :: new ( parent_computed. clone_with_overrides ( input. local . clone ( ) ) )
244
244
} else {
@@ -258,7 +258,7 @@ impl ConfigTree {
258
258
// Get a new &mut slot because self.compute(parent) also gets mut access
259
259
let slot = & mut self . computed [ idx] ;
260
260
slot. replace ( self_computed. clone ( ) ) ;
261
- Ok ( self_computed)
261
+ Ok ( ( self_computed, idx ) )
262
262
}
263
263
}
264
264
@@ -322,6 +322,9 @@ impl ConfigTree {
322
322
} ;
323
323
tracing:: trace!( "invalidating {x:?} / {:?}" , desc. src) ;
324
324
slot. take ( ) ;
325
+
326
+ // Also invalidate the secondary data
327
+ self . with_client_config . remove ( desc. computed_idx ) ;
325
328
} ) ;
326
329
}
327
330
@@ -346,7 +349,16 @@ impl ConfigTree {
346
349
let ConfigChanges { client_change, ra_toml_changes, mut parent_changes } = changes;
347
350
348
351
if let Some ( change) = client_change {
349
- self . client_config = change;
352
+ match ( self . client_config . as_ref ( ) , change. as_ref ( ) ) {
353
+ ( None , None ) => { }
354
+ ( Some ( a) , Some ( b) ) if Arc :: ptr_eq ( a, b) => { }
355
+ _ => {
356
+ // invalidate the output table only, don't immediately need to recompute
357
+ // everything from scratch
358
+ self . with_client_config . clear ( ) ;
359
+ self . client_config = change;
360
+ }
361
+ }
350
362
}
351
363
352
364
for change in ra_toml_changes {
@@ -498,6 +510,9 @@ mod tests {
498
510
499
511
let prev = local;
500
512
let local = config_tree. read_config ( crate_a) . unwrap ( ) ;
513
+ assert ! ( !Arc :: ptr_eq( & prev, & local) ) ;
514
+ let local2 = config_tree. read_config ( crate_a) . unwrap ( ) ;
515
+ assert ! ( Arc :: ptr_eq( & local, & local2) ) ;
501
516
502
517
assert_eq ! (
503
518
local. inlayHints_discriminantHints_enable,
0 commit comments