Recursive collect macros in impl items
This commit is contained in:
parent
6eab968c60
commit
360de5ba71
@ -226,21 +226,39 @@ fn collect_impl_items_in_macros(
|
|||||||
let mut res = Vec::new();
|
let mut res = Vec::new();
|
||||||
|
|
||||||
for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
|
for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) {
|
||||||
if let Some((mark, items)) = expander.enter_expand(db, m) {
|
res.extend(collect_impl_items_in_macro(db, &mut expander, m, id))
|
||||||
let items: InFile<ast::MacroItems> = expander.to_source(items);
|
|
||||||
expander.exit(db, mark);
|
|
||||||
res.extend(collect_impl_items(
|
|
||||||
db,
|
|
||||||
items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
|
|
||||||
items.file_id,
|
|
||||||
id,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
res
|
res
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn collect_impl_items_in_macro(
|
||||||
|
db: &impl DefDatabase,
|
||||||
|
expander: &mut Expander,
|
||||||
|
m: ast::MacroCall,
|
||||||
|
id: ImplId,
|
||||||
|
) -> Vec<AssocItemId> {
|
||||||
|
if let Some((mark, items)) = expander.enter_expand(db, m) {
|
||||||
|
let items: InFile<ast::MacroItems> = expander.to_source(items);
|
||||||
|
let mut res = collect_impl_items(
|
||||||
|
db,
|
||||||
|
items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())),
|
||||||
|
items.file_id,
|
||||||
|
id,
|
||||||
|
);
|
||||||
|
// Recursive collect macros
|
||||||
|
// Note that ast::ModuleItem do not include ast::MacroCall
|
||||||
|
// We cannot use ModuleItemOwner::items here
|
||||||
|
for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) {
|
||||||
|
res.extend(collect_impl_items_in_macro(db, expander, it, id))
|
||||||
|
}
|
||||||
|
expander.exit(db, mark);
|
||||||
|
res
|
||||||
|
} else {
|
||||||
|
Vec::new()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn collect_impl_items(
|
fn collect_impl_items(
|
||||||
db: &impl DefDatabase,
|
db: &impl DefDatabase,
|
||||||
impl_items: impl Iterator<Item = ImplItem>,
|
impl_items: impl Iterator<Item = ImplItem>,
|
||||||
|
@ -201,6 +201,29 @@ fn test() { S.foo()<|>; }
|
|||||||
assert_eq!(t, "u128");
|
assert_eq!(t, "u128");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn infer_impl_items_generated_by_macros_chain() {
|
||||||
|
let t = type_at(
|
||||||
|
r#"
|
||||||
|
//- /main.rs
|
||||||
|
macro_rules! m_inner {
|
||||||
|
() => {fn foo(&self) -> u128 {0}}
|
||||||
|
}
|
||||||
|
macro_rules! m {
|
||||||
|
() => {m_inner!();}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct S;
|
||||||
|
impl S {
|
||||||
|
m!();
|
||||||
|
}
|
||||||
|
|
||||||
|
fn test() { S.foo()<|>; }
|
||||||
|
"#,
|
||||||
|
);
|
||||||
|
assert_eq!(t, "u128");
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn infer_macro_with_dollar_crate_is_correct_in_expr() {
|
fn infer_macro_with_dollar_crate_is_correct_in_expr() {
|
||||||
let (db, pos) = TestDB::with_position(
|
let (db, pos) = TestDB::with_position(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user