@@ -24,7 +24,47 @@ pub enum ConfigTreeError {
24
24
/// Some rust-analyzer.toml files have changed, and/or the LSP client sent a new configuration.
25
25
pub struct ConfigChanges {
26
26
ra_toml_changes : Vec < vfs:: ChangedFile > ,
27
+ xdg_config_change : Option < Arc < ConfigInput > > ,
27
28
client_change : Option < Arc < ConfigInput > > ,
29
+ parent_changes : Vec < ConfigParentChange > ,
30
+ }
31
+
32
+ pub struct ConfigParentChange {
33
+ /// The config node in question
34
+ pub node : FileId ,
35
+ pub parent : ConfigParent ,
36
+ }
37
+
38
+ pub enum ConfigParent {
39
+ /// The node is now a root in its own right, but still inherits from the config in XDG_CONFIG_HOME
40
+ /// etc
41
+ UserDefault ,
42
+ /// The node is now a child of another rust-analyzer.toml. Even if that one is a non-existent
43
+ /// file, it's fine.
44
+ ///
45
+ ///
46
+ /// ```ignore,text
47
+ /// /project_root/
48
+ /// rust-analyzer.toml
49
+ /// crate_a/
50
+ /// crate_b/
51
+ /// rust-analyzer.toml
52
+ ///
53
+ /// ```
54
+ ///
55
+ /// ```ignore
56
+ /// // imagine set_file_contents = vfs.set_file_contents() and then get the vfs.file_id()
57
+ ///
58
+ /// let root = vfs.set_file_contents("/project_root/rust-analyzer.toml", Some("..."));
59
+ /// let crate_a = vfs.set_file_contents("/project_root/crate_a/rust-analyzer.toml", None);
60
+ /// let crate_b = vfs.set_file_contents("/project_root/crate_a/crate_b/rust-analyzer.toml", Some("..."));
61
+ /// let config_parent_changes = [
62
+ /// ConfigParentChange { node: root, parent: ConfigParent::UserDefault },
63
+ /// ConfigParentChange { node: crate_a, parent: ConfigParent::Parent(root) },
64
+ /// ConfigParentChange { node: crate_b, parent: ConfigParent::Parent(crate_a) }
65
+ /// ];
66
+ /// ```
67
+ Parent ( FileId ) ,
28
68
}
29
69
30
70
impl ConcurrentConfigTree {
@@ -56,13 +96,15 @@ slotmap::new_key_type! {
56
96
57
97
struct ConfigNode {
58
98
src : ConfigSource ,
99
+ // TODO: make option
59
100
input : Arc < ConfigInput > ,
60
101
computed : ComputedIdx ,
61
102
}
62
103
63
104
struct ConfigTree {
64
105
tree : indextree:: Arena < ConfigNode > ,
65
- client_config : NodeId ,
106
+ client_config : Arc < ConfigInput > ,
107
+ xdg_config_node_id : NodeId ,
66
108
ra_file_id_map : FxHashMap < FileId , NodeId > ,
67
109
computed : SlotMap < ComputedIdx , Option < Arc < LocalConfigData > > > ,
68
110
}
@@ -98,15 +140,24 @@ fn parse_toml(
98
140
}
99
141
100
142
impl ConfigTree {
101
- fn new ( ) -> Self {
143
+ fn new ( xdg_config_file_id : FileId ) -> Self {
102
144
let mut tree = indextree:: Arena :: new ( ) ;
103
145
let mut computed = SlotMap :: default ( ) ;
104
- let client_config = tree. new_node ( ConfigNode {
105
- src : ConfigSource :: ClientConfig ,
146
+ let mut ra_file_id_map = FxHashMap :: default ( ) ;
147
+ let xdg_config = tree. new_node ( ConfigNode {
148
+ src : ConfigSource :: RaToml ( xdg_config_file_id) ,
106
149
input : Arc :: new ( ConfigInput :: default ( ) ) ,
107
150
computed : computed. insert ( Option :: < Arc < LocalConfigData > > :: None ) ,
108
151
} ) ;
109
- Self { client_config, ra_file_id_map : FxHashMap :: default ( ) , tree, computed }
152
+ ra_file_id_map. insert ( xdg_config_file_id, xdg_config) ;
153
+
154
+ Self {
155
+ client_config : Arc :: new ( Default :: default ( ) ) ,
156
+ xdg_config_node_id : xdg_config,
157
+ ra_file_id_map,
158
+ tree,
159
+ computed,
160
+ }
110
161
}
111
162
112
163
fn read_only ( & self , file_id : FileId ) -> Result < Option < Arc < LocalConfigData > > , ConfigTreeError > {
@@ -205,18 +256,27 @@ impl ConfigTree {
205
256
206
257
fn apply_changes (
207
258
& mut self ,
208
- changes : ConfigChanges ,
259
+ mut changes : ConfigChanges ,
209
260
vfs : & Vfs ,
210
261
errors : & mut Vec < ConfigTreeError > ,
211
262
) {
212
263
let mut scratch_errors = Vec :: new ( ) ;
213
- let ConfigChanges { client_change, ra_toml_changes } = changes;
264
+ let ConfigChanges { client_change, ra_toml_changes, xdg_config_change, parent_changes } =
265
+ changes;
266
+
214
267
if let Some ( change) = client_change {
215
- let node =
216
- self . tree . get_mut ( self . client_config ) . expect ( "client_config node should exist" ) ;
268
+ self . client_config = change;
269
+ }
270
+
271
+ if let Some ( change) = xdg_config_change {
272
+ let node = self
273
+ . tree
274
+ . get_mut ( self . xdg_config_node_id )
275
+ . expect ( "client_config node should exist" ) ;
217
276
node. get_mut ( ) . input = change;
218
- self . invalidate_subtree ( self . client_config ) ;
277
+ self . invalidate_subtree ( self . xdg_config_node_id ) ;
219
278
}
279
+
220
280
for change in ra_toml_changes {
221
281
// turn and face the strain
222
282
match change. change_kind {
0 commit comments