From: Aleksey Kladov Date: Sun, 10 Oct 2021 13:08:01 +0000 (+0300) Subject: internal: move derived tests to the unified macro infra X-Git-Url: https://git.lizzy.rs/?a=commitdiff_plain;h=5af80d83726e01fe54e569d77fee6a504d1d4bd2;p=rust.git internal: move derived tests to the unified macro infra --- diff --git a/crates/hir_def/src/macro_expansion_tests.rs b/crates/hir_def/src/macro_expansion_tests.rs index f29d1443b92..5f8bf44cc93 100644 --- a/crates/hir_def/src/macro_expansion_tests.rs +++ b/crates/hir_def/src/macro_expansion_tests.rs @@ -11,6 +11,7 @@ mod mbe; mod builtin_fn_macro; +mod builtin_derive_macro; use std::{iter, ops::Range}; @@ -26,7 +27,8 @@ }; use crate::{ - db::DefDatabase, nameres::ModuleSource, resolver::HasResolver, test_db::TestDB, AsMacroCall, + db::DefDatabase, nameres::ModuleSource, resolver::HasResolver, src::HasSource, test_db::TestDB, + AsMacroCall, Lookup, }; #[track_caller] @@ -43,6 +45,21 @@ fn check(ra_fixture: &str, mut expect: Expect) { ModuleSource::Module(_) | ModuleSource::BlockExpr(_) => panic!(), }; + // What we want to do is to replace all macros (fn-like, derive, attr) with + // their expansions. Turns out, we don't actually store enough information + // to do this precisely though! Specifically, if a macro expands to nothing, + // it leaves zero traces in def-map, so we can't get its expansion after the + // fact. + // + // This is the usual + // + // resolve/record tension! + // + // So here we try to do a resolve, which is necessary a heuristic. For macro + // calls, we use `as_call_id_with_errors`. For derives, we look at the impls + // in the module and assume that, if impls's source is a different + // `HirFileId`, than it came from macro expansion. + let mut expansions = Vec::new(); for macro_call in source_file.syntax().descendants().filter_map(ast::MacroCall::cast) { let macro_call = InFile::new(source.file_id, ¯o_call); @@ -63,6 +80,7 @@ fn check(ra_fixture: &str, mut expect: Expect) { } let mut expanded_text = source_file.to_string(); + for (call, exp) in expansions.into_iter().rev() { let mut tree = false; let mut expect_errors = false; @@ -106,6 +124,14 @@ fn check(ra_fixture: &str, mut expect: Expect) { expanded_text.replace_range(range, &expn_text) } + for impl_id in def_map[local_id].scope.impls() { + let src = impl_id.lookup(&db).source(&db); + if src.file_id.is_builtin_derive(&db).is_some() { + let pp = pretty_print_macro_expansion(src.value.syntax().clone()); + format_to!(expanded_text, "\n{}", pp) + } + } + expect.indent(false); expect.assert_eq(&expanded_text); } diff --git a/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs b/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs new file mode 100644 index 00000000000..177409dc380 --- /dev/null +++ b/crates/hir_def/src/macro_expansion_tests/builtin_derive_macro.rs @@ -0,0 +1,70 @@ +//! Tests for `builtin_derive_macro.rs` from `hir_expand`. + +use expect_test::expect; + +use crate::macro_expansion_tests::check; + +#[test] +fn test_copy_expand_simple() { + check( + r#" +//- minicore: derive, copy +#[derive(Copy)] +struct Foo; +"#, + expect![[r##" +#[derive(Copy)] +struct Foo; + +impl < > core::marker::Copy for Foo< > {}"##]], + ); +} + +#[test] +fn test_copy_expand_with_type_params() { + check( + r#" +//- minicore: derive, copy +#[derive(Copy)] +struct Foo; +"#, + expect![[r##" +#[derive(Copy)] +struct Foo; + +impl core::marker::Copy for Foo {}"##]], + ); +} + +#[test] +fn test_copy_expand_with_lifetimes() { + // We currently just ignore lifetimes + check( + r#" +//- minicore: derive, copy +#[derive(Copy)] +struct Foo; +"#, + expect![[r##" +#[derive(Copy)] +struct Foo; + +impl core::marker::Copy for Foo {}"##]], + ); +} + +#[test] +fn test_clone_expand() { + check( + r#" +//- minicore: derive, clone +#[derive(Clone)] +struct Foo; +"#, + expect![[r##" +#[derive(Clone)] +struct Foo; + +impl core::clone::Clone for Foo {}"##]], + ); +} diff --git a/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs b/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs index 6982116522c..06039e95c5f 100644 --- a/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs +++ b/crates/hir_def/src/macro_expansion_tests/builtin_fn_macro.rs @@ -1,4 +1,4 @@ -//! Tests for builtin macros (see `builtin_macro.rs` in `hir_expand`). +//! Tests for `builtin_fn_macro.rs` from `hir_expand`. use expect_test::expect; diff --git a/crates/hir_expand/src/builtin_derive_macro.rs b/crates/hir_expand/src/builtin_derive_macro.rs index eeebe87acd6..d4fcf42dd3f 100644 --- a/crates/hir_expand/src/builtin_derive_macro.rs +++ b/crates/hir_expand/src/builtin_derive_macro.rs @@ -258,128 +258,3 @@ fn partial_ord_expand( let krate = find_builtin_crate(db, id); expand_simple_derive(tt, quote! { #krate::cmp::PartialOrd }) } - -#[cfg(test)] -mod tests { - use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; - use expect_test::{expect, Expect}; - use name::AsName; - - use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; - - use super::*; - - fn expand_builtin_derive(ra_fixture: &str) -> String { - let fixture = format!( - r#"//- /main.rs crate:main deps:core -$0 -{} -//- /lib.rs crate:core -// empty -"#, - ra_fixture - ); - - let (db, file_pos) = TestDB::with_position(&fixture); - let file_id = file_pos.file_id; - let ast_id_map = db.ast_id_map(file_id.into()); - let parsed = db.parse(file_id); - let macros: Vec<_> = - parsed.syntax_node().descendants().filter_map(ast::Macro::cast).collect(); - let items: Vec<_> = parsed - .syntax_node() - .descendants() - .filter(|node| !ast::Macro::can_cast(node.kind())) - .filter_map(ast::Item::cast) - .collect(); - - assert_eq!(macros.len(), 1, "test must contain exactly 1 macro definition"); - assert_eq!(items.len(), 1, "test must contain exactly 1 item"); - - let macro_ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯os[0])); - let name = match ¯os[0] { - ast::Macro::MacroRules(rules) => rules.name().unwrap().as_name(), - ast::Macro::MacroDef(def) => def.name().unwrap().as_name(), - }; - - let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); - - let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); - - let loc = MacroCallLoc { - def: MacroDefId { - krate: CrateId(0), - kind: MacroDefKind::BuiltInDerive(expander, macro_ast_id), - local_inner: false, - }, - krate: CrateId(0), - eager: None, - kind: MacroCallKind::Derive { - ast_id, - derive_name: name.to_string(), - derive_attr_index: 0, - }, - }; - - let id: MacroCallId = db.intern_macro(loc); - let parsed = db.parse_or_expand(id.as_file()).unwrap(); - - // FIXME text() for syntax nodes parsed from token tree looks weird - // because there's no whitespace, see below - parsed.text().to_string() - } - - fn check_derive(ra_fixture: &str, expected: Expect) { - let expanded = expand_builtin_derive(ra_fixture); - expected.assert_eq(&expanded); - } - - #[test] - fn test_copy_expand_simple() { - check_derive( - r#" - macro Copy {} - #[derive(Copy)] - struct Foo; - "#, - expect![["impl< >core::marker::CopyforFoo< >{}"]], - ); - } - - #[test] - fn test_copy_expand_with_type_params() { - check_derive( - r#" - macro Copy {} - #[derive(Copy)] - struct Foo; - "#, - expect![["implcore::marker::CopyforFoo{}"]], - ); - } - - #[test] - fn test_copy_expand_with_lifetimes() { - check_derive( - r#" - macro Copy {} - #[derive(Copy)] - struct Foo; - "#, - // We currently just ignore lifetimes - expect![["implcore::marker::CopyforFoo{}"]], - ); - } - - #[test] - fn test_clone_expand() { - check_derive( - r#" - macro Clone {} - #[derive(Clone)] - struct Foo; - "#, - expect![["implcore::clone::CloneforFoo{}"]], - ); - } -}