Skip to content

Commit da73c93

Browse files
committed
Don't punish every crate with serde-json
1 parent d57c9f7 commit da73c93

File tree

4 files changed

+96
-99
lines changed

4 files changed

+96
-99
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/rust-analyzer/tests/rust-analyzer/support.rs

Lines changed: 96 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ use project_model::ProjectManifest;
1313
use rust_analyzer::{config::Config, lsp_ext, main_loop};
1414
use serde::Serialize;
1515
use serde_json::{json, to_string_pretty, Value};
16-
use test_utils::{find_mismatch, Fixture};
16+
use test_utils::Fixture;
1717
use vfs::AbsPathBuf;
1818

1919
use crate::testdir::TestDir;
@@ -279,3 +279,98 @@ fn recv_timeout(receiver: &Receiver<Message>) -> Result<Option<Message>, Timeout
279279
recv(after(timeout)) -> _ => Err(Timeout),
280280
}
281281
}
282+
283+
// Comparison functionality borrowed from cargo:
284+
285+
/// Compares JSON object for approximate equality.
286+
/// You can use `[..]` wildcard in strings (useful for OS dependent things such
287+
/// as paths). You can use a `"{...}"` string literal as a wildcard for
288+
/// arbitrary nested JSON. Arrays are sorted before comparison.
289+
fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> {
290+
match (expected, actual) {
291+
(Value::Number(l), Value::Number(r)) if l == r => None,
292+
(Value::Bool(l), Value::Bool(r)) if l == r => None,
293+
(Value::String(l), Value::String(r)) if lines_match(l, r) => None,
294+
(Value::Array(l), Value::Array(r)) => {
295+
if l.len() != r.len() {
296+
return Some((expected, actual));
297+
}
298+
299+
let mut l = l.iter().collect::<Vec<_>>();
300+
let mut r = r.iter().collect::<Vec<_>>();
301+
302+
l.retain(|l| match r.iter().position(|r| find_mismatch(l, r).is_none()) {
303+
Some(i) => {
304+
r.remove(i);
305+
false
306+
}
307+
None => true,
308+
});
309+
310+
if !l.is_empty() {
311+
assert!(!r.is_empty());
312+
Some((&l[0], &r[0]))
313+
} else {
314+
assert_eq!(r.len(), 0);
315+
None
316+
}
317+
}
318+
(Value::Object(l), Value::Object(r)) => {
319+
fn sorted_values(obj: &serde_json::Map<String, Value>) -> Vec<&Value> {
320+
let mut entries = obj.iter().collect::<Vec<_>>();
321+
entries.sort_by_key(|it| it.0);
322+
entries.into_iter().map(|(_k, v)| v).collect::<Vec<_>>()
323+
}
324+
325+
let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
326+
if !same_keys {
327+
return Some((expected, actual));
328+
}
329+
330+
let l = sorted_values(l);
331+
let r = sorted_values(r);
332+
333+
l.into_iter().zip(r).filter_map(|(l, r)| find_mismatch(l, r)).next()
334+
}
335+
(Value::Null, Value::Null) => None,
336+
// magic string literal "{...}" acts as wildcard for any sub-JSON
337+
(Value::String(l), _) if l == "{...}" => None,
338+
_ => Some((expected, actual)),
339+
}
340+
}
341+
342+
/// Compare a line with an expected pattern.
343+
/// - Use `[..]` as a wildcard to match 0 or more characters on the same line
344+
/// (similar to `.*` in a regex).
345+
fn lines_match(expected: &str, actual: &str) -> bool {
346+
// Let's not deal with / vs \ (windows...)
347+
// First replace backslash-escaped backslashes with forward slashes
348+
// which can occur in, for example, JSON output
349+
let expected = expected.replace(r"\\", "/").replace(r"\", "/");
350+
let mut actual: &str = &actual.replace(r"\\", "/").replace(r"\", "/");
351+
for (i, part) in expected.split("[..]").enumerate() {
352+
match actual.find(part) {
353+
Some(j) => {
354+
if i == 0 && j != 0 {
355+
return false;
356+
}
357+
actual = &actual[j + part.len()..];
358+
}
359+
None => return false,
360+
}
361+
}
362+
actual.is_empty() || expected.ends_with("[..]")
363+
}
364+
365+
#[test]
366+
fn lines_match_works() {
367+
assert!(lines_match("a b", "a b"));
368+
assert!(lines_match("a[..]b", "a b"));
369+
assert!(lines_match("a[..]", "a b"));
370+
assert!(lines_match("[..]", "a b"));
371+
assert!(lines_match("[..]b", "a b"));
372+
373+
assert!(!lines_match("[..]b", "c"));
374+
assert!(!lines_match("b", "c"));
375+
assert!(!lines_match("b", "cb"));
376+
}

crates/test_utils/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ doctest = false
1313
# Avoid adding deps here, this crate is widely used in tests it should compile fast!
1414
dissimilar = "1.0.2"
1515
text-size = "1.0.0"
16-
serde_json = "1.0.48"
1716
rustc-hash = "1.1.0"
1817

1918
stdx = { path = "../stdx", version = "0.0.0" }

crates/test_utils/src/lib.rs

Lines changed: 0 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ use std::{
1818
};
1919

2020
use profile::StopWatch;
21-
use serde_json::Value;
2221
use stdx::lines_with_ends;
2322
use text_size::{TextRange, TextSize};
2423

@@ -281,101 +280,6 @@ fn main() {
281280
);
282281
}
283282

284-
// Comparison functionality borrowed from cargo:
285-
286-
/// Compare a line with an expected pattern.
287-
/// - Use `[..]` as a wildcard to match 0 or more characters on the same line
288-
/// (similar to `.*` in a regex).
289-
pub fn lines_match(expected: &str, actual: &str) -> bool {
290-
// Let's not deal with / vs \ (windows...)
291-
// First replace backslash-escaped backslashes with forward slashes
292-
// which can occur in, for example, JSON output
293-
let expected = expected.replace(r"\\", "/").replace(r"\", "/");
294-
let mut actual: &str = &actual.replace(r"\\", "/").replace(r"\", "/");
295-
for (i, part) in expected.split("[..]").enumerate() {
296-
match actual.find(part) {
297-
Some(j) => {
298-
if i == 0 && j != 0 {
299-
return false;
300-
}
301-
actual = &actual[j + part.len()..];
302-
}
303-
None => return false,
304-
}
305-
}
306-
actual.is_empty() || expected.ends_with("[..]")
307-
}
308-
309-
#[test]
310-
fn lines_match_works() {
311-
assert!(lines_match("a b", "a b"));
312-
assert!(lines_match("a[..]b", "a b"));
313-
assert!(lines_match("a[..]", "a b"));
314-
assert!(lines_match("[..]", "a b"));
315-
assert!(lines_match("[..]b", "a b"));
316-
317-
assert!(!lines_match("[..]b", "c"));
318-
assert!(!lines_match("b", "c"));
319-
assert!(!lines_match("b", "cb"));
320-
}
321-
322-
/// Compares JSON object for approximate equality.
323-
/// You can use `[..]` wildcard in strings (useful for OS dependent things such
324-
/// as paths). You can use a `"{...}"` string literal as a wildcard for
325-
/// arbitrary nested JSON. Arrays are sorted before comparison.
326-
pub fn find_mismatch<'a>(expected: &'a Value, actual: &'a Value) -> Option<(&'a Value, &'a Value)> {
327-
match (expected, actual) {
328-
(Value::Number(l), Value::Number(r)) if l == r => None,
329-
(Value::Bool(l), Value::Bool(r)) if l == r => None,
330-
(Value::String(l), Value::String(r)) if lines_match(l, r) => None,
331-
(Value::Array(l), Value::Array(r)) => {
332-
if l.len() != r.len() {
333-
return Some((expected, actual));
334-
}
335-
336-
let mut l = l.iter().collect::<Vec<_>>();
337-
let mut r = r.iter().collect::<Vec<_>>();
338-
339-
l.retain(|l| match r.iter().position(|r| find_mismatch(l, r).is_none()) {
340-
Some(i) => {
341-
r.remove(i);
342-
false
343-
}
344-
None => true,
345-
});
346-
347-
if !l.is_empty() {
348-
assert!(!r.is_empty());
349-
Some((&l[0], &r[0]))
350-
} else {
351-
assert_eq!(r.len(), 0);
352-
None
353-
}
354-
}
355-
(Value::Object(l), Value::Object(r)) => {
356-
fn sorted_values(obj: &serde_json::Map<String, Value>) -> Vec<&Value> {
357-
let mut entries = obj.iter().collect::<Vec<_>>();
358-
entries.sort_by_key(|it| it.0);
359-
entries.into_iter().map(|(_k, v)| v).collect::<Vec<_>>()
360-
}
361-
362-
let same_keys = l.len() == r.len() && l.keys().all(|k| r.contains_key(k));
363-
if !same_keys {
364-
return Some((expected, actual));
365-
}
366-
367-
let l = sorted_values(l);
368-
let r = sorted_values(r);
369-
370-
l.into_iter().zip(r).filter_map(|(l, r)| find_mismatch(l, r)).next()
371-
}
372-
(Value::Null, Value::Null) => None,
373-
// magic string literal "{...}" acts as wildcard for any sub-JSON
374-
(Value::String(l), _) if l == "{...}" => None,
375-
_ => Some((expected, actual)),
376-
}
377-
}
378-
379283
/// Returns `false` if slow tests should not run, otherwise returns `true` and
380284
/// also creates a file at `./target/.slow_tests_cookie` which serves as a flag
381285
/// that slow tests did run.

0 commit comments

Comments
 (0)