From 2544abbf867a7660bc2c9342181c8392774f1cca Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Wed, 2 Dec 2020 17:31:24 +0300 Subject: Make config.rs a single source of truth for configuration. Configuration is editor-independent. For this reason, we pick JSON-schema as the repr of the source of truth. We do specify it using rust-macros and some quick&dirty hackery though. The idea for syncing truth with package.json is to just do that manually, but there's a test to check that they are actually synced. There's CLI to print config's json schema: $ rust-analyzer --print-config-schema We go with a CLI rather than LSP request/response to make it easier to incorporate the thing into extension's static config. This is roughtly how we put the thing in package.json. --- crates/test_utils/src/lib.rs | 26 +++++++++++++++++--------- 1 file changed, 17 insertions(+), 9 deletions(-) (limited to 'crates/test_utils/src') diff --git a/crates/test_utils/src/lib.rs b/crates/test_utils/src/lib.rs index a49be4602..05940a546 100644 --- a/crates/test_utils/src/lib.rs +++ b/crates/test_utils/src/lib.rs @@ -321,12 +321,11 @@ fn lines_match_works() { /// as paths). You can use a `"{...}"` string literal as a wildcard for /// arbitrary nested JSON. Arrays are sorted before comparison. pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> { - use serde_json::Value::*; match (expected, actual) { - (&Number(ref l), &Number(ref r)) if l == r => None, - (&Bool(l), &Bool(r)) if l == r => None, - (&String(ref l), &String(ref r)) if lines_match(l, r) => None, - (&Array(ref l), &Array(ref r)) => { + (Value::Number(l), Value::Number(r)) if l == r => None, + (Value::Bool(l), Value::Bool(r)) if l == r => None, + (Value::String(l), Value::String(r)) if lines_match(l, r) => None, + (Value::Array(l), Value::Array(r)) => { if l.len() != r.len() { return Some((expected, actual)); } @@ -350,17 +349,26 @@ pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a None } } - (&Object(ref l), &Object(ref r)) => { + (Value::Object(l), Value::Object(r)) => { + fn sorted_values(obj: &serde_json::Map) -> Vec<&Value> { + let mut entries = obj.iter().collect::>(); + entries.sort_by_key(|it| it.0); + entries.into_iter().map(|(_k, v)| v).collect::>() + } + let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k)); if !same_keys { return Some((expected, actual)); } - l.values().zip(r.values()).filter_map(|(l, r)| find_mismatch(l, r)).next() + let l = sorted_values(l); + let r = sorted_values(r); + + l.into_iter().zip(r).filter_map(|(l, r)| find_mismatch(l, r)).next() } - (&Null, &Null) => None, + (Value::Null, Value::Null) => None, // magic string literal "{...}" acts as wildcard for any sub-JSON - (&String(ref l), _) if l == "{...}" => None, + (Value::String(l), _) if l == "{...}" => None, _ => Some((expected, actual)), } } -- cgit v1.2.3