|
| 1 | +use serde_json::{json, Value}; |
| 2 | + |
| 3 | +/// This function patches the json config to the new expected keys. |
| 4 | +/// That is we try to load old known config keys here and convert them to the new ones. |
| 5 | +/// See https://github.com/rust-lang/rust-analyzer/pull/12010 |
| 6 | +pub(super) fn patch_json_for_outdated_configs(json: &mut Value) { |
| 7 | + let copy = json.clone(); |
| 8 | + |
| 9 | + macro_rules! patch { |
| 10 | + ($( |
| 11 | + $($src:ident).+ -> $($dst:ident).+ ; |
| 12 | + )+) => { $( |
| 13 | + if let Some(it) = copy.pointer(concat!($("/", stringify!($src)),+)).cloned() { |
| 14 | + let mut last = it; |
| 15 | + for segment in [$(stringify!($dst)),+].into_iter().rev() { |
| 16 | + last = Value::Object(serde_json::Map::from_iter(std::iter::once((segment.to_string(), last)))); |
| 17 | + } |
| 18 | + |
| 19 | + merge(json, last); |
| 20 | + } |
| 21 | + )+ }; |
| 22 | + } |
| 23 | + |
| 24 | + patch! { |
| 25 | + assist.allowMergingIntoGlobImports -> imports.merge.glob; |
| 26 | + assist.exprFillDefault -> assist.expressionFillDefault; |
| 27 | + assist.importEnforceGranularity -> imports.granularity.enforce; |
| 28 | + assist.importGranularity -> imports.granularity.group; |
| 29 | + assist.importMergeBehavior -> imports.granularity.group; |
| 30 | + assist.importMergeBehaviour -> imports.granularity.group; |
| 31 | + assist.importGroup -> imports.group.enable; |
| 32 | + assist.importPrefix -> imports.prefix; |
| 33 | + cache.warmup -> primeCaches.enable; |
| 34 | + cargo.loadOutDirsFromCheck -> cargo.buildScripts.enable; |
| 35 | + cargo.runBuildScripts -> cargo.runBuildScripts.overrideCommand; |
| 36 | + cargo.runBuildScriptsCommand -> cargo.runBuildScripts.overrideCommand; |
| 37 | + cargo.useRustcWrapperForBuildScripts -> cargo.runBuildScripts.useRustcWrapper; |
| 38 | + completion.snippets -> completion.snippets.custom; |
| 39 | + diagnostics.enableExperimental -> diagnostics.experimental.enable; |
| 40 | + experimental.procAttrMacros -> procMacro.attributes.enable; |
| 41 | + highlighting.strings -> semanticHighlighting.strings.enable; |
| 42 | + highlightRelated.breakPoints -> semanticHighlighting.breakPoints.enable; |
| 43 | + highlightRelated.exitPoints -> semanticHighlighting.exitPoints.enable; |
| 44 | + highlightRelated.yieldPoints -> semanticHighlighting.yieldPoints.enable; |
| 45 | + highlightRelated.references -> semanticHighlighting.references.enable; |
| 46 | + hover.documentation -> hover.documentation.enable; |
| 47 | + hover.linksInHover -> hover.links.enable; |
| 48 | + hoverActions.linksInHover -> hover.links.enable; |
| 49 | + hoverActions.debug -> hoverActions.debug.enable; |
| 50 | + hoverActions.enable -> hoverActions.enable.enable; |
| 51 | + hoverActions.gotoTypeDef -> hoverActions.gotoTypeDef.enable; |
| 52 | + hoverActions.implementations -> hoverActions.implementations.enable; |
| 53 | + hoverActions.references -> hoverActions.references.enable; |
| 54 | + hoverActions.run -> hoverActions.run.enable; |
| 55 | + inlayHints.chainingHints -> inlayHints.chainingHints.enable; |
| 56 | + inlayHints.closureReturnTypeHints -> inlayHints.closureReturnTypeHints.enable; |
| 57 | + inlayHints.hideNamedConstructorHints -> inlayHints.typeHints.hideNamedConstructorHints; |
| 58 | + inlayHints.parameterHints -> inlayHints.parameterHints.enable; |
| 59 | + inlayHints.reborrowHints -> inlayHints.reborrowHints.enable; |
| 60 | + inlayHints.typeHints -> inlayHints.typeHints.enable; |
| 61 | + lruCapacity -> lru.capacity; |
| 62 | + runnables.cargoExtraArgs -> runnables.extraArgs ; |
| 63 | + runnables.overrideCargo -> runnables.command ; |
| 64 | + rustcSource -> rustc.source; |
| 65 | + rustfmt.enableRangeFormatting -> rustfmt.rangeFormatting.enable; |
| 66 | + } |
| 67 | + |
| 68 | + // callInfo_full -> signatureInfo_detail, signatureInfo_documentation_enable |
| 69 | + if let Some(Value::Bool(b)) = copy.pointer("/callInfo/full") { |
| 70 | + let sig_info = match b { |
| 71 | + true => json!({ "signatureInfo": { |
| 72 | + "documentation": {"enable": true}}, |
| 73 | + "detail": "full" |
| 74 | + }), |
| 75 | + false => json!({ "signatureInfo": { |
| 76 | + "documentation": {"enable": false}}, |
| 77 | + "detail": "parameters" |
| 78 | + }), |
| 79 | + }; |
| 80 | + merge(json, sig_info); |
| 81 | + } |
| 82 | + |
| 83 | + // cargo_allFeatures, cargo_features -> cargo_features |
| 84 | + if let Some(Value::Bool(true)) = copy.pointer("/cargo/allFeatures") { |
| 85 | + merge(json, json!({ "cargo": { "features": "all" } })); |
| 86 | + } |
| 87 | + |
| 88 | + // checkOnSave_allFeatures, checkOnSave_features -> checkOnSave_features |
| 89 | + if let Some(Value::Bool(true)) = copy.pointer("/checkOnSave/allFeatures") { |
| 90 | + merge(json, json!({ "checkOnSave": { "features": "all" } })); |
| 91 | + } |
| 92 | + |
| 93 | + // completion_addCallArgumentSnippets completion_addCallParenthesis -> completion_callable_snippets |
| 94 | + let res = match ( |
| 95 | + copy.pointer("/completion/addCallArgumentSnippets"), |
| 96 | + copy.pointer("/completion/addCallParenthesis"), |
| 97 | + ) { |
| 98 | + (Some(Value::Bool(true)), Some(Value::Bool(true))) => json!("fill_arguments"), |
| 99 | + (Some(Value::Bool(true)), _) => json!("add_parentheses"), |
| 100 | + (_, _) => json!(null), |
| 101 | + }; |
| 102 | + merge(json, json!({ "completion": { "callable": {"snippets": res }} })); |
| 103 | +} |
| 104 | + |
| 105 | +fn merge(dst: &mut Value, src: Value) { |
| 106 | + match (dst, src) { |
| 107 | + (Value::Object(dst), Value::Object(src)) => { |
| 108 | + for (k, v) in src { |
| 109 | + merge(dst.entry(k).or_insert(v.clone()), v) |
| 110 | + } |
| 111 | + } |
| 112 | + (dst, src) => *dst = src, |
| 113 | + } |
| 114 | +} |
0 commit comments