Unnamed repository; edit this file 'description' to name the repository.
Diffstat (limited to 'crates/hir-def/src/body/tests.rs')
| -rw-r--r-- | crates/hir-def/src/body/tests.rs | 127 |
1 files changed, 127 insertions, 0 deletions
diff --git a/crates/hir-def/src/body/tests.rs b/crates/hir-def/src/body/tests.rs new file mode 100644 index 0000000000..c9601f8552 --- /dev/null +++ b/crates/hir-def/src/body/tests.rs @@ -0,0 +1,127 @@ +mod block; + +use base_db::{fixture::WithFixture, SourceDatabase}; +use expect_test::Expect; + +use crate::ModuleDefId; + +use super::*; + +fn lower(ra_fixture: &str) -> Arc<Body> { + let db = crate::test_db::TestDB::with_files(ra_fixture); + + let krate = db.crate_graph().iter().next().unwrap(); + let def_map = db.crate_def_map(krate); + let mut fn_def = None; + 'outer: for (_, module) in def_map.modules() { + for decl in module.scope.declarations() { + if let ModuleDefId::FunctionId(it) = decl { + fn_def = Some(it); + break 'outer; + } + } + } + + db.body(fn_def.unwrap().into()) +} + +fn block_def_map_at(ra_fixture: &str) -> String { + let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); + + let module = db.module_at_position(position); + module.def_map(&db).dump(&db) +} + +fn check_block_scopes_at(ra_fixture: &str, expect: Expect) { + let (db, position) = crate::test_db::TestDB::with_position(ra_fixture); + + let module = db.module_at_position(position); + let actual = module.def_map(&db).dump_block_scopes(&db); + expect.assert_eq(&actual); +} + +fn check_at(ra_fixture: &str, expect: Expect) { + let actual = block_def_map_at(ra_fixture); + expect.assert_eq(&actual); +} + +#[test] +fn your_stack_belongs_to_me() { + cov_mark::check!(your_stack_belongs_to_me); + lower( + r#" +macro_rules! n_nuple { + ($e:tt) => (); + ($($rest:tt)*) => {{ + (n_nuple!($($rest)*)None,) + }}; +} +fn main() { n_nuple!(1,2,3); } +"#, + ); +} + +#[test] +fn recursion_limit() { + cov_mark::check!(your_stack_belongs_to_me); + + lower( + r#" +#![recursion_limit = "2"] +macro_rules! n_nuple { + ($e:tt) => (); + ($first:tt $($rest:tt)*) => {{ + n_nuple!($($rest)*) + }}; +} +fn main() { n_nuple!(1,2,3); } +"#, + ); +} + +#[test] +fn issue_3642_bad_macro_stackover() { + lower( + r#" +#[macro_export] +macro_rules! match_ast { + (match $node:ident { $($tt:tt)* }) => { match_ast!(match ($node) { $($tt)* }) }; + + (match ($node:expr) { + $( ast::$ast:ident($it:ident) => $res:expr, )* + _ => $catch_all:expr $(,)? + }) => {{ + $( if let Some($it) = ast::$ast::cast($node.clone()) { $res } else )* + { $catch_all } + }}; +} + +fn main() { + let anchor = match_ast! { + match parent { + as => {}, + _ => return None + } + }; +}"#, + ); +} + +#[test] +fn macro_resolve() { + // Regression test for a path resolution bug introduced with inner item handling. + lower( + r#" +macro_rules! vec { + () => { () }; + ($elem:expr; $n:expr) => { () }; + ($($x:expr),+ $(,)?) => { () }; +} +mod m { + fn outer() { + let _ = vec![FileSet::default(); self.len()]; + } +} +"#, + ); +} |