diff options
author | Edwin Cheng <[email protected]> | 2019-12-20 21:02:31 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-12-20 21:02:31 +0000 |
commit | 360de5ba71a631a118a088dba7c975e9ae592452 (patch) | |
tree | aa270c12c8cebc72908444d9f28722d159b040c3 | |
parent | 6eab968c601637361e8fbd1ee93ded1b0d967bee (diff) |
Recursive collect macros in impl items
-rw-r--r-- | crates/ra_hir_def/src/data.rs | 38 | ||||
-rw-r--r-- | crates/ra_hir_ty/src/tests/macros.rs | 23 |
2 files changed, 51 insertions, 10 deletions
diff --git a/crates/ra_hir_def/src/data.rs b/crates/ra_hir_def/src/data.rs index b0a3f1784..6a65633ae 100644 --- a/crates/ra_hir_def/src/data.rs +++ b/crates/ra_hir_def/src/data.rs | |||
@@ -226,21 +226,39 @@ fn collect_impl_items_in_macros( | |||
226 | let mut res = Vec::new(); | 226 | let mut res = Vec::new(); |
227 | 227 | ||
228 | for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { | 228 | for m in impl_block.value.syntax().children().filter_map(ast::MacroCall::cast) { |
229 | if let Some((mark, items)) = expander.enter_expand(db, m) { | 229 | res.extend(collect_impl_items_in_macro(db, &mut expander, m, id)) |
230 | let items: InFile<ast::MacroItems> = expander.to_source(items); | ||
231 | expander.exit(db, mark); | ||
232 | res.extend(collect_impl_items( | ||
233 | db, | ||
234 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | ||
235 | items.file_id, | ||
236 | id, | ||
237 | )); | ||
238 | } | ||
239 | } | 230 | } |
240 | 231 | ||
241 | res | 232 | res |
242 | } | 233 | } |
243 | 234 | ||
235 | fn collect_impl_items_in_macro( | ||
236 | db: &impl DefDatabase, | ||
237 | expander: &mut Expander, | ||
238 | m: ast::MacroCall, | ||
239 | id: ImplId, | ||
240 | ) -> Vec<AssocItemId> { | ||
241 | if let Some((mark, items)) = expander.enter_expand(db, m) { | ||
242 | let items: InFile<ast::MacroItems> = expander.to_source(items); | ||
243 | let mut res = collect_impl_items( | ||
244 | db, | ||
245 | items.value.items().filter_map(|it| ImplItem::cast(it.syntax().clone())), | ||
246 | items.file_id, | ||
247 | id, | ||
248 | ); | ||
249 | // Recursive collect macros | ||
250 | // Note that ast::ModuleItem do not include ast::MacroCall | ||
251 | // We cannot use ModuleItemOwner::items here | ||
252 | for it in items.value.syntax().children().filter_map(ast::MacroCall::cast) { | ||
253 | res.extend(collect_impl_items_in_macro(db, expander, it, id)) | ||
254 | } | ||
255 | expander.exit(db, mark); | ||
256 | res | ||
257 | } else { | ||
258 | Vec::new() | ||
259 | } | ||
260 | } | ||
261 | |||
244 | fn collect_impl_items( | 262 | fn collect_impl_items( |
245 | db: &impl DefDatabase, | 263 | db: &impl DefDatabase, |
246 | impl_items: impl Iterator<Item = ImplItem>, | 264 | impl_items: impl Iterator<Item = ImplItem>, |
diff --git a/crates/ra_hir_ty/src/tests/macros.rs b/crates/ra_hir_ty/src/tests/macros.rs index 7fdbf996f..69c695cc8 100644 --- a/crates/ra_hir_ty/src/tests/macros.rs +++ b/crates/ra_hir_ty/src/tests/macros.rs | |||
@@ -202,6 +202,29 @@ fn test() { S.foo()<|>; } | |||
202 | } | 202 | } |
203 | 203 | ||
204 | #[test] | 204 | #[test] |
205 | fn infer_impl_items_generated_by_macros_chain() { | ||
206 | let t = type_at( | ||
207 | r#" | ||
208 | //- /main.rs | ||
209 | macro_rules! m_inner { | ||
210 | () => {fn foo(&self) -> u128 {0}} | ||
211 | } | ||
212 | macro_rules! m { | ||
213 | () => {m_inner!();} | ||
214 | } | ||
215 | |||
216 | struct S; | ||
217 | impl S { | ||
218 | m!(); | ||
219 | } | ||
220 | |||
221 | fn test() { S.foo()<|>; } | ||
222 | "#, | ||
223 | ); | ||
224 | assert_eq!(t, "u128"); | ||
225 | } | ||
226 | |||
227 | #[test] | ||
205 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { | 228 | fn infer_macro_with_dollar_crate_is_correct_in_expr() { |
206 | let (db, pos) = TestDB::with_position( | 229 | let (db, pos) = TestDB::with_position( |
207 | r#" | 230 | r#" |