rust_analyzer/config/
patch_old_style.rs1use serde_json::{Value, json};
3
4pub(super) fn patch_json_for_outdated_configs(json: &mut Value) {
11 let copy = json.clone();
12
13 macro_rules! patch {
14 ($(
15 $($src:ident).+ -> $($dst:ident).+ ;
16 )+) => { $(
17 match copy.pointer(concat!($("/", stringify!($src)),+)).cloned() {
18 Some(Value::Object(_)) | None => (),
19 Some(it) => {
20 let mut last = it;
21 for segment in [$(stringify!($dst)),+].into_iter().rev() {
22 last = Value::Object(serde_json::Map::from_iter(std::iter::once((segment.to_owned(), last))));
23 }
24
25 merge(json, last);
26 },
27 }
28 )+ };
29 }
30
31 patch! {
32 assist.allowMergingIntoGlobImports -> imports.merge.glob;
33 assist.exprFillDefault -> assist.expressionFillDefault;
34 assist.importEnforceGranularity -> imports.granularity.enforce;
35 assist.importGranularity -> imports.granularity.group;
36 assist.importMergeBehavior -> imports.granularity.group;
37 assist.importMergeBehaviour -> imports.granularity.group;
38 assist.importGroup -> imports.group.enable;
39 assist.importPrefix -> imports.prefix;
40 primeCaches.enable -> cachePriming.enable;
41 cache.warmup -> cachePriming.enable;
42 cargo.loadOutDirsFromCheck -> cargo.buildScripts.enable;
43 cargo.runBuildScripts -> cargo.buildScripts.enable;
44 cargo.runBuildScriptsCommand -> cargo.buildScripts.overrideCommand;
45 cargo.useRustcWrapperForBuildScripts -> cargo.buildScripts.useRustcWrapper;
46 diagnostics.enableExperimental -> diagnostics.experimental.enable;
47 experimental.procAttrMacros -> procMacro.attributes.enable;
48 highlighting.strings -> semanticHighlighting.strings.enable;
49 highlightRelated.breakPoints -> semanticHighlighting.breakPoints.enable;
50 highlightRelated.exitPoints -> semanticHighlighting.exitPoints.enable;
51 highlightRelated.yieldPoints -> semanticHighlighting.yieldPoints.enable;
52 highlightRelated.references -> semanticHighlighting.references.enable;
53 hover.documentation -> hover.documentation.enable;
54 hover.linksInHover -> hover.links.enable;
55 hoverActions.linksInHover -> hover.links.enable;
56 hoverActions.debug -> hover.actions.debug.enable;
57 hoverActions.enable -> hover.actions.enable;
58 hoverActions.gotoTypeDef -> hover.actions.gotoTypeDef.enable;
59 hoverActions.implementations -> hover.actions.implementations.enable;
60 hoverActions.references -> hover.actions.references.enable;
61 hoverActions.run -> hover.actions.run.enable;
62 inlayHints.chainingHints -> inlayHints.chainingHints.enable;
63 inlayHints.closureReturnTypeHints -> inlayHints.closureReturnTypeHints.enable;
64 inlayHints.hideNamedConstructorHints -> inlayHints.typeHints.hideNamedConstructorHints;
65 inlayHints.parameterHints -> inlayHints.parameterHints.enable;
66 inlayHints.reborrowHints -> inlayHints.reborrowHints.enable;
67 inlayHints.typeHints -> inlayHints.typeHints.enable;
68 lruCapacity -> lru.capacity;
69 runnables.cargoExtraArgs -> runnables.extraArgs ;
70 runnables.overrideCargo -> runnables.command ;
71 rustcSource -> rustc.source;
72 rustfmt.enableRangeFormatting -> rustfmt.rangeFormatting.enable;
73 }
74
75 if let Some(Value::Object(obj)) = copy.pointer("/completion/snippets").cloned()
77 && (obj.len() != 1 || obj.get("custom").is_none())
78 {
79 merge(
80 json,
81 json! {{
82 "completion": {
83 "snippets": {
84 "custom": obj
85 },
86 },
87 }},
88 );
89 }
90
91 if let Some(Value::Bool(b)) = copy.pointer("/callInfo/full") {
93 let sig_info = match b {
94 true => json!({ "signatureInfo": {
95 "documentation": {"enable": true}},
96 "detail": "full"
97 }),
98 false => json!({ "signatureInfo": {
99 "documentation": {"enable": false}},
100 "detail": "parameters"
101 }),
102 };
103 merge(json, sig_info);
104 }
105
106 if let Some(Value::Bool(true)) = copy.pointer("/cargo/allFeatures") {
108 merge(json, json!({ "cargo": { "features": "all" } }));
109 }
110
111 if let Some(Value::Bool(true)) = copy.pointer("/checkOnSave/allFeatures") {
113 merge(json, json!({ "check": { "features": "all" } }));
114 }
115
116 'completion: {
118 let res = match (
119 copy.pointer("/completion/addCallArgumentSnippets"),
120 copy.pointer("/completion/addCallParenthesis"),
121 ) {
122 (Some(Value::Bool(true)), Some(Value::Bool(true))) => json!("fill_arguments"),
123 (_, Some(Value::Bool(true))) => json!("add_parentheses"),
124 (Some(Value::Bool(false)), Some(Value::Bool(false))) => json!("none"),
125 (_, _) => break 'completion,
126 };
127 merge(json, json!({ "completion": { "callable": {"snippets": res }} }));
128 }
129
130 if let Some(Value::Object(obj)) = copy.pointer("/checkOnSave") {
133 if let Some(b @ Value::Bool(_)) = obj.get("enable") {
135 merge(json, json!({ "checkOnSave": b }));
136 }
137 merge(json, json!({ "check": obj }));
138 }
139}
140
141fn merge(dst: &mut Value, src: Value) {
142 match (dst, src) {
143 (Value::Object(dst), Value::Object(src)) => {
144 for (k, v) in src {
145 merge(dst.entry(k).or_insert(v.clone()), v)
146 }
147 }
148 (dst, src) => *dst = src,
149 }
150}
151
152#[test]
153fn check_on_save_patching() {
154 let mut json = json!({ "checkOnSave": { "overrideCommand": "foo" }});
155 patch_json_for_outdated_configs(&mut json);
156 assert_eq!(
157 json,
158 json!({ "checkOnSave": { "overrideCommand": "foo" }, "check": { "overrideCommand": "foo" }})
159 );
160}
161
162#[test]
163fn check_on_save_patching_enable() {
164 let mut json = json!({ "checkOnSave": { "enable": true, "overrideCommand": "foo" }});
165 patch_json_for_outdated_configs(&mut json);
166 assert_eq!(
167 json,
168 json!({ "checkOnSave": true, "check": { "enable": true, "overrideCommand": "foo" }})
169 );
170}