optimize snapshot-testing macro detection and add tests

This commit is contained in:
roife 2024-12-26 15:55:03 +08:00
parent c54bfcb181
commit 1dcce45f48
2 changed files with 136 additions and 44 deletions

View file

@ -9926,3 +9926,99 @@ fn bar() {
"#]], "#]],
); );
} }
#[test]
fn test_runnables_with_snapshot_tests() {
check_actions(
r#"
//- /lib.rs crate:foo deps:expect_test,insta,snapbox
use expect_test::expect;
use insta::assert_debug_snapshot;
use snapbox::Assert;
#[test]
fn test$0() {
let actual = "new25";
expect!["new25"].assert_eq(&actual);
Assert::new()
.action_env("SNAPSHOTS")
.eq(actual, snapbox::str!["new25"]);
assert_debug_snapshot!(actual);
}
//- /lib.rs crate:expect_test
struct Expect;
impl Expect {
fn assert_eq(&self, actual: &str) {}
}
#[macro_export]
macro_rules! expect {
($e:expr) => Expect; // dummy
}
//- /lib.rs crate:insta
#[macro_export]
macro_rules! assert_debug_snapshot {
($e:expr) => {}; // dummy
}
//- /lib.rs crate:snapbox
pub struct Assert;
impl Assert {
pub fn new() -> Self { Assert }
pub fn action_env(&self, env: &str) -> &Self { self }
pub fn eq(&self, actual: &str, expected: &str) {}
}
#[macro_export]
macro_rules! str {
($e:expr) => ""; // dummy
}
"#,
expect![[r#"
[
Reference(
FilePositionWrapper {
file_id: FileId(
0,
),
offset: 92,
},
),
Runnable(
Runnable {
use_name_in_title: false,
nav: NavigationTarget {
file_id: FileId(
0,
),
full_range: 81..301,
focus_range: 92..96,
name: "test",
kind: Function,
},
kind: Test {
test_id: Path(
"test",
),
attr: TestAttr {
ignore: false,
},
},
cfg: None,
update_test: UpdateTest {
expect_test: true,
insta: true,
snapbox: true,
},
},
),
]
"#]],
);
}

View file

@ -657,62 +657,58 @@ impl<'a, 'b> TestDefs<'a, 'b> {
} }
fn expect_test(&self) -> bool { fn expect_test(&self) -> bool {
self.find_macro("expect_test:expect") || self.find_macro("expect_test::expect_file") self.find_macro("expect_test", &["expect", "expect_file"])
} }
fn insta(&self) -> bool { fn insta(&self) -> bool {
self.find_macro("insta:assert_snapshot") self.find_macro(
|| self.find_macro("insta:assert_debug_snapshot") "insta",
|| self.find_macro("insta:assert_display_snapshot") &[
|| self.find_macro("insta:assert_json_snapshot") "assert_snapshot",
|| self.find_macro("insta:assert_yaml_snapshot") "assert_debug_snapshot",
|| self.find_macro("insta:assert_ron_snapshot") "assert_display_snapshot",
|| self.find_macro("insta:assert_toml_snapshot") "assert_json_snapshot",
|| self.find_macro("insta:assert_csv_snapshot") "assert_yaml_snapshot",
|| self.find_macro("insta:assert_compact_json_snapshot") "assert_ron_snapshot",
|| self.find_macro("insta:assert_compact_debug_snapshot") "assert_toml_snapshot",
|| self.find_macro("insta:assert_binary_snapshot") "assert_csv_snapshot",
"assert_compact_json_snapshot",
"assert_compact_debug_snapshot",
"assert_binary_snapshot",
],
)
} }
fn snapbox(&self) -> bool { fn snapbox(&self) -> bool {
self.find_macro("snapbox:assert_data_eq") self.find_macro("snapbox", &["assert_data_eq", "file", "str"])
|| self.find_macro("snapbox:file")
|| self.find_macro("snapbox:str")
} }
fn find_macro(&self, path: &str) -> bool { fn find_macro(&self, crate_name: &str, paths: &[&str]) -> bool {
let Some(hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(it))) = self.find_def(path) else { let db = self.0.db;
let Some(dep) =
self.1.dependencies(db).into_iter().find(|dep| dep.name.eq_ident(crate_name))
else {
return false; return false;
}; };
let module = dep.krate.root_module();
let scope = module.scope(db, None);
Definition::Macro(it) paths
.iter()
.filter_map(|path| {
let (_, def) = scope.iter().find(|(name, _)| name.eq_ident(path))?;
match def {
hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(it)) => Some(it),
_ => None,
}
})
.any(|makro| {
Definition::Macro(*makro)
.usages(self.0) .usages(self.0)
.in_scope(&SearchScope::file_range(self.2)) .in_scope(&SearchScope::file_range(self.2))
.at_least_one() .at_least_one()
} })
fn find_def(&self, path: &str) -> Option<hir::ScopeDef> {
let db = self.0.db;
let mut path = path.split(':');
let item = path.next_back()?;
let krate = path.next()?;
let dep = self.1.dependencies(db).into_iter().find(|dep| dep.name.eq_ident(krate))?;
let mut module = dep.krate.root_module();
for segment in path {
module = module.children(db).find_map(|child| {
let name = child.name(db)?;
if name.eq_ident(segment) {
Some(child)
} else {
None
}
})?;
}
let (_, def) = module.scope(db, None).into_iter().find(|(name, _)| name.eq_ident(item))?;
Some(def)
} }
} }