diff options
Diffstat (limited to 'crates/hir_expand')
-rw-r--r-- | crates/hir_expand/src/builtin_derive.rs | 47 | ||||
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 79 | ||||
-rw-r--r-- | crates/hir_expand/src/db.rs | 16 | ||||
-rw-r--r-- | crates/hir_expand/src/eager.rs | 25 | ||||
-rw-r--r-- | crates/hir_expand/src/hygiene.rs | 12 | ||||
-rw-r--r-- | crates/hir_expand/src/lib.rs | 58 | ||||
-rw-r--r-- | crates/hir_expand/src/name.rs | 5 |
7 files changed, 156 insertions, 86 deletions
diff --git a/crates/hir_expand/src/builtin_derive.rs b/crates/hir_expand/src/builtin_derive.rs index 5e908b223..6ece4b289 100644 --- a/crates/hir_expand/src/builtin_derive.rs +++ b/crates/hir_expand/src/builtin_derive.rs | |||
@@ -61,8 +61,7 @@ pub fn find_builtin_derive( | |||
61 | let expander = BuiltinDeriveExpander::find_by_name(ident)?; | 61 | let expander = BuiltinDeriveExpander::find_by_name(ident)?; |
62 | Some(MacroDefId { | 62 | Some(MacroDefId { |
63 | krate, | 63 | krate, |
64 | ast_id: Some(ast_id), | 64 | kind: MacroDefKind::BuiltInDerive(expander, ast_id), |
65 | kind: MacroDefKind::BuiltInDerive(expander), | ||
66 | local_inner: false, | 65 | local_inner: false, |
67 | }) | 66 | }) |
68 | } | 67 | } |
@@ -268,14 +267,13 @@ fn partial_ord_expand( | |||
268 | mod tests { | 267 | mod tests { |
269 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; | 268 | use base_db::{fixture::WithFixture, CrateId, SourceDatabase}; |
270 | use expect_test::{expect, Expect}; | 269 | use expect_test::{expect, Expect}; |
271 | use name::{known, Name}; | 270 | use name::AsName; |
272 | 271 | ||
273 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; | 272 | use crate::{test_db::TestDB, AstId, MacroCallId, MacroCallKind, MacroCallLoc}; |
274 | 273 | ||
275 | use super::*; | 274 | use super::*; |
276 | 275 | ||
277 | fn expand_builtin_derive(ra_fixture: &str, name: Name) -> String { | 276 | fn expand_builtin_derive(ra_fixture: &str) -> String { |
278 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); | ||
279 | let fixture = format!( | 277 | let fixture = format!( |
280 | r#"//- /main.rs crate:main deps:core | 278 | r#"//- /main.rs crate:main deps:core |
281 | $0 | 279 | $0 |
@@ -288,23 +286,38 @@ $0 | |||
288 | 286 | ||
289 | let (db, file_pos) = TestDB::with_position(&fixture); | 287 | let (db, file_pos) = TestDB::with_position(&fixture); |
290 | let file_id = file_pos.file_id; | 288 | let file_id = file_pos.file_id; |
289 | let ast_id_map = db.ast_id_map(file_id.into()); | ||
291 | let parsed = db.parse(file_id); | 290 | let parsed = db.parse(file_id); |
292 | let items: Vec<_> = | 291 | let macros: Vec<_> = |
293 | parsed.syntax_node().descendants().filter_map(ast::Item::cast).collect(); | 292 | parsed.syntax_node().descendants().filter_map(ast::Macro::cast).collect(); |
293 | let items: Vec<_> = parsed | ||
294 | .syntax_node() | ||
295 | .descendants() | ||
296 | .filter(|node| !ast::Macro::can_cast(node.kind())) | ||
297 | .filter_map(ast::Item::cast) | ||
298 | .collect(); | ||
299 | |||
300 | assert_eq!(macros.len(), 1, "test must contain exactly 1 macro definition"); | ||
301 | assert_eq!(items.len(), 1, "test must contain exactly 1 item"); | ||
302 | |||
303 | let macro_ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯os[0])); | ||
304 | let name = match ¯os[0] { | ||
305 | ast::Macro::MacroRules(rules) => rules.name().unwrap().as_name(), | ||
306 | ast::Macro::MacroDef(def) => def.name().unwrap().as_name(), | ||
307 | }; | ||
294 | 308 | ||
295 | let ast_id_map = db.ast_id_map(file_id.into()); | 309 | let expander = BuiltinDeriveExpander::find_by_name(&name).unwrap(); |
296 | 310 | ||
297 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); | 311 | let attr_id = AstId::new(file_id.into(), ast_id_map.ast_id(&items[0])); |
298 | 312 | ||
299 | let loc = MacroCallLoc { | 313 | let loc = MacroCallLoc { |
300 | def: MacroDefId { | 314 | def: MacroDefId { |
301 | krate: CrateId(0), | 315 | krate: CrateId(0), |
302 | ast_id: None, | 316 | kind: MacroDefKind::BuiltInDerive(expander, macro_ast_id), |
303 | kind: MacroDefKind::BuiltInDerive(expander), | ||
304 | local_inner: false, | 317 | local_inner: false, |
305 | }, | 318 | }, |
306 | krate: CrateId(0), | 319 | krate: CrateId(0), |
307 | kind: MacroCallKind::Attr(attr_id, name.to_string()), | 320 | kind: MacroCallKind::Derive(attr_id, name.to_string()), |
308 | }; | 321 | }; |
309 | 322 | ||
310 | let id: MacroCallId = db.intern_macro(loc).into(); | 323 | let id: MacroCallId = db.intern_macro(loc).into(); |
@@ -315,8 +328,8 @@ $0 | |||
315 | parsed.text().to_string() | 328 | parsed.text().to_string() |
316 | } | 329 | } |
317 | 330 | ||
318 | fn check_derive(ra_fixture: &str, name: Name, expected: Expect) { | 331 | fn check_derive(ra_fixture: &str, expected: Expect) { |
319 | let expanded = expand_builtin_derive(ra_fixture, name); | 332 | let expanded = expand_builtin_derive(ra_fixture); |
320 | expected.assert_eq(&expanded); | 333 | expected.assert_eq(&expanded); |
321 | } | 334 | } |
322 | 335 | ||
@@ -324,10 +337,10 @@ $0 | |||
324 | fn test_copy_expand_simple() { | 337 | fn test_copy_expand_simple() { |
325 | check_derive( | 338 | check_derive( |
326 | r#" | 339 | r#" |
340 | macro Copy {} | ||
327 | #[derive(Copy)] | 341 | #[derive(Copy)] |
328 | struct Foo; | 342 | struct Foo; |
329 | "#, | 343 | "#, |
330 | known::Copy, | ||
331 | expect![["impl< >core::marker::CopyforFoo< >{}"]], | 344 | expect![["impl< >core::marker::CopyforFoo< >{}"]], |
332 | ); | 345 | ); |
333 | } | 346 | } |
@@ -336,10 +349,10 @@ $0 | |||
336 | fn test_copy_expand_with_type_params() { | 349 | fn test_copy_expand_with_type_params() { |
337 | check_derive( | 350 | check_derive( |
338 | r#" | 351 | r#" |
352 | macro Copy {} | ||
339 | #[derive(Copy)] | 353 | #[derive(Copy)] |
340 | struct Foo<A, B>; | 354 | struct Foo<A, B>; |
341 | "#, | 355 | "#, |
342 | known::Copy, | ||
343 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], | 356 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], |
344 | ); | 357 | ); |
345 | } | 358 | } |
@@ -348,10 +361,10 @@ $0 | |||
348 | fn test_copy_expand_with_lifetimes() { | 361 | fn test_copy_expand_with_lifetimes() { |
349 | check_derive( | 362 | check_derive( |
350 | r#" | 363 | r#" |
364 | macro Copy {} | ||
351 | #[derive(Copy)] | 365 | #[derive(Copy)] |
352 | struct Foo<A, B, 'a, 'b>; | 366 | struct Foo<A, B, 'a, 'b>; |
353 | "#, | 367 | "#, |
354 | known::Copy, | ||
355 | // We currently just ignore lifetimes | 368 | // We currently just ignore lifetimes |
356 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], | 369 | expect![["impl<T0:core::marker::Copy,T1:core::marker::Copy>core::marker::CopyforFoo<T0,T1>{}"]], |
357 | ); | 370 | ); |
@@ -361,10 +374,10 @@ $0 | |||
361 | fn test_clone_expand() { | 374 | fn test_clone_expand() { |
362 | check_derive( | 375 | check_derive( |
363 | r#" | 376 | r#" |
377 | macro Clone {} | ||
364 | #[derive(Clone)] | 378 | #[derive(Clone)] |
365 | struct Foo<A, B>; | 379 | struct Foo<A, B>; |
366 | "#, | 380 | "#, |
367 | known::Clone, | ||
368 | expect![["impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"]], | 381 | expect![["impl<T0:core::clone::Clone,T1:core::clone::Clone>core::clone::CloneforFoo<T0,T1>{}"]], |
369 | ); | 382 | ); |
370 | } | 383 | } |
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index fce09a9e7..4d52904b9 100644 --- a/crates/hir_expand/src/builtin_macro.rs +++ b/crates/hir_expand/src/builtin_macro.rs | |||
@@ -43,7 +43,7 @@ macro_rules! register_builtin { | |||
43 | db: &dyn AstDatabase, | 43 | db: &dyn AstDatabase, |
44 | arg_id: EagerMacroId, | 44 | arg_id: EagerMacroId, |
45 | tt: &tt::Subtree, | 45 | tt: &tt::Subtree, |
46 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 46 | ) -> ExpandResult<Option<ExpandedEager>> { |
47 | let expander = match *self { | 47 | let expander = match *self { |
48 | $( EagerExpander::$e_kind => $e_expand, )* | 48 | $( EagerExpander::$e_kind => $e_expand, )* |
49 | }; | 49 | }; |
@@ -61,6 +61,20 @@ macro_rules! register_builtin { | |||
61 | }; | 61 | }; |
62 | } | 62 | } |
63 | 63 | ||
64 | #[derive(Debug)] | ||
65 | pub struct ExpandedEager { | ||
66 | pub(crate) subtree: tt::Subtree, | ||
67 | pub(crate) fragment: FragmentKind, | ||
68 | /// The included file ID of the include macro. | ||
69 | pub(crate) included_file: Option<FileId>, | ||
70 | } | ||
71 | |||
72 | impl ExpandedEager { | ||
73 | fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self { | ||
74 | ExpandedEager { subtree, fragment, included_file: None } | ||
75 | } | ||
76 | } | ||
77 | |||
64 | pub fn find_builtin_macro( | 78 | pub fn find_builtin_macro( |
65 | ident: &name::Name, | 79 | ident: &name::Name, |
66 | krate: CrateId, | 80 | krate: CrateId, |
@@ -71,14 +85,12 @@ pub fn find_builtin_macro( | |||
71 | match kind { | 85 | match kind { |
72 | Either::Left(kind) => Some(MacroDefId { | 86 | Either::Left(kind) => Some(MacroDefId { |
73 | krate, | 87 | krate, |
74 | ast_id: Some(ast_id), | 88 | kind: MacroDefKind::BuiltIn(kind, ast_id), |
75 | kind: MacroDefKind::BuiltIn(kind), | ||
76 | local_inner: false, | 89 | local_inner: false, |
77 | }), | 90 | }), |
78 | Either::Right(kind) => Some(MacroDefId { | 91 | Either::Right(kind) => Some(MacroDefId { |
79 | krate, | 92 | krate, |
80 | ast_id: Some(ast_id), | 93 | kind: MacroDefKind::BuiltInEager(kind, ast_id), |
81 | kind: MacroDefKind::BuiltInEager(kind), | ||
82 | local_inner: false, | 94 | local_inner: false, |
83 | }), | 95 | }), |
84 | } | 96 | } |
@@ -282,7 +294,7 @@ fn compile_error_expand( | |||
282 | _db: &dyn AstDatabase, | 294 | _db: &dyn AstDatabase, |
283 | _id: EagerMacroId, | 295 | _id: EagerMacroId, |
284 | tt: &tt::Subtree, | 296 | tt: &tt::Subtree, |
285 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 297 | ) -> ExpandResult<Option<ExpandedEager>> { |
286 | let err = match &*tt.token_trees { | 298 | let err = match &*tt.token_trees { |
287 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { | 299 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { |
288 | let text = it.text.as_str(); | 300 | let text = it.text.as_str(); |
@@ -296,14 +308,14 @@ fn compile_error_expand( | |||
296 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 308 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
297 | }; | 309 | }; |
298 | 310 | ||
299 | ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) } | 311 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } |
300 | } | 312 | } |
301 | 313 | ||
302 | fn concat_expand( | 314 | fn concat_expand( |
303 | _db: &dyn AstDatabase, | 315 | _db: &dyn AstDatabase, |
304 | _arg_id: EagerMacroId, | 316 | _arg_id: EagerMacroId, |
305 | tt: &tt::Subtree, | 317 | tt: &tt::Subtree, |
306 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 318 | ) -> ExpandResult<Option<ExpandedEager>> { |
307 | let mut err = None; | 319 | let mut err = None; |
308 | let mut text = String::new(); | 320 | let mut text = String::new(); |
309 | for (i, t) in tt.token_trees.iter().enumerate() { | 321 | for (i, t) in tt.token_trees.iter().enumerate() { |
@@ -327,7 +339,7 @@ fn concat_expand( | |||
327 | } | 339 | } |
328 | } | 340 | } |
329 | } | 341 | } |
330 | ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } | 342 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } |
331 | } | 343 | } |
332 | 344 | ||
333 | fn relative_file( | 345 | fn relative_file( |
@@ -363,21 +375,27 @@ fn include_expand( | |||
363 | db: &dyn AstDatabase, | 375 | db: &dyn AstDatabase, |
364 | arg_id: EagerMacroId, | 376 | arg_id: EagerMacroId, |
365 | tt: &tt::Subtree, | 377 | tt: &tt::Subtree, |
366 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 378 | ) -> ExpandResult<Option<ExpandedEager>> { |
367 | let res = (|| { | 379 | let res = (|| { |
368 | let path = parse_string(tt)?; | 380 | let path = parse_string(tt)?; |
369 | let file_id = relative_file(db, arg_id.into(), &path, false)?; | 381 | let file_id = relative_file(db, arg_id.into(), &path, false)?; |
370 | 382 | ||
371 | Ok(parse_to_token_tree(&db.file_text(file_id)) | 383 | let subtree = parse_to_token_tree(&db.file_text(file_id)) |
372 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 384 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
373 | .0) | 385 | .0; |
386 | Ok((subtree, file_id)) | ||
374 | })(); | 387 | })(); |
375 | 388 | ||
376 | match res { | 389 | match res { |
377 | Ok(res) => { | 390 | Ok((subtree, file_id)) => { |
378 | // FIXME: | 391 | // FIXME: |
379 | // Handle include as expression | 392 | // Handle include as expression |
380 | ExpandResult::ok(Some((res, FragmentKind::Items))) | 393 | |
394 | ExpandResult::ok(Some(ExpandedEager { | ||
395 | subtree, | ||
396 | fragment: FragmentKind::Items, | ||
397 | included_file: Some(file_id), | ||
398 | })) | ||
381 | } | 399 | } |
382 | Err(e) => ExpandResult::only_err(e), | 400 | Err(e) => ExpandResult::only_err(e), |
383 | } | 401 | } |
@@ -387,7 +405,7 @@ fn include_bytes_expand( | |||
387 | _db: &dyn AstDatabase, | 405 | _db: &dyn AstDatabase, |
388 | _arg_id: EagerMacroId, | 406 | _arg_id: EagerMacroId, |
389 | tt: &tt::Subtree, | 407 | tt: &tt::Subtree, |
390 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 408 | ) -> ExpandResult<Option<ExpandedEager>> { |
391 | if let Err(e) = parse_string(tt) { | 409 | if let Err(e) = parse_string(tt) { |
392 | return ExpandResult::only_err(e); | 410 | return ExpandResult::only_err(e); |
393 | } | 411 | } |
@@ -400,14 +418,14 @@ fn include_bytes_expand( | |||
400 | id: tt::TokenId::unspecified(), | 418 | id: tt::TokenId::unspecified(), |
401 | }))], | 419 | }))], |
402 | }; | 420 | }; |
403 | ExpandResult::ok(Some((res, FragmentKind::Expr))) | 421 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) |
404 | } | 422 | } |
405 | 423 | ||
406 | fn include_str_expand( | 424 | fn include_str_expand( |
407 | db: &dyn AstDatabase, | 425 | db: &dyn AstDatabase, |
408 | arg_id: EagerMacroId, | 426 | arg_id: EagerMacroId, |
409 | tt: &tt::Subtree, | 427 | tt: &tt::Subtree, |
410 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 428 | ) -> ExpandResult<Option<ExpandedEager>> { |
411 | let path = match parse_string(tt) { | 429 | let path = match parse_string(tt) { |
412 | Ok(it) => it, | 430 | Ok(it) => it, |
413 | Err(e) => return ExpandResult::only_err(e), | 431 | Err(e) => return ExpandResult::only_err(e), |
@@ -420,14 +438,14 @@ fn include_str_expand( | |||
420 | let file_id = match relative_file(db, arg_id.into(), &path, true) { | 438 | let file_id = match relative_file(db, arg_id.into(), &path, true) { |
421 | Ok(file_id) => file_id, | 439 | Ok(file_id) => file_id, |
422 | Err(_) => { | 440 | Err(_) => { |
423 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); | 441 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); |
424 | } | 442 | } |
425 | }; | 443 | }; |
426 | 444 | ||
427 | let text = db.file_text(file_id); | 445 | let text = db.file_text(file_id); |
428 | let text = &*text; | 446 | let text = &*text; |
429 | 447 | ||
430 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) | 448 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) |
431 | } | 449 | } |
432 | 450 | ||
433 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { | 451 | fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { |
@@ -439,7 +457,7 @@ fn env_expand( | |||
439 | db: &dyn AstDatabase, | 457 | db: &dyn AstDatabase, |
440 | arg_id: EagerMacroId, | 458 | arg_id: EagerMacroId, |
441 | tt: &tt::Subtree, | 459 | tt: &tt::Subtree, |
442 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 460 | ) -> ExpandResult<Option<ExpandedEager>> { |
443 | let key = match parse_string(tt) { | 461 | let key = match parse_string(tt) { |
444 | Ok(it) => it, | 462 | Ok(it) => it, |
445 | Err(e) => return ExpandResult::only_err(e), | 463 | Err(e) => return ExpandResult::only_err(e), |
@@ -463,14 +481,14 @@ fn env_expand( | |||
463 | }); | 481 | }); |
464 | let expanded = quote! { #s }; | 482 | let expanded = quote! { #s }; |
465 | 483 | ||
466 | ExpandResult { value: Some((expanded, FragmentKind::Expr)), err } | 484 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } |
467 | } | 485 | } |
468 | 486 | ||
469 | fn option_env_expand( | 487 | fn option_env_expand( |
470 | db: &dyn AstDatabase, | 488 | db: &dyn AstDatabase, |
471 | arg_id: EagerMacroId, | 489 | arg_id: EagerMacroId, |
472 | tt: &tt::Subtree, | 490 | tt: &tt::Subtree, |
473 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 491 | ) -> ExpandResult<Option<ExpandedEager>> { |
474 | let key = match parse_string(tt) { | 492 | let key = match parse_string(tt) { |
475 | Ok(it) => it, | 493 | Ok(it) => it, |
476 | Err(e) => return ExpandResult::only_err(e), | 494 | Err(e) => return ExpandResult::only_err(e), |
@@ -481,7 +499,7 @@ fn option_env_expand( | |||
481 | Some(s) => quote! { std::option::Some(#s) }, | 499 | Some(s) => quote! { std::option::Some(#s) }, |
482 | }; | 500 | }; |
483 | 501 | ||
484 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) | 502 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) |
485 | } | 503 | } |
486 | 504 | ||
487 | #[cfg(test)] | 505 | #[cfg(test)] |
@@ -512,6 +530,7 @@ mod tests { | |||
512 | let macro_call = macro_calls.pop().unwrap(); | 530 | let macro_call = macro_calls.pop().unwrap(); |
513 | 531 | ||
514 | let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); | 532 | let expander = find_by_name(¯o_rules.name().unwrap().as_name()).unwrap(); |
533 | let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules)); | ||
515 | 534 | ||
516 | let krate = CrateId(0); | 535 | let krate = CrateId(0); |
517 | let file_id = match expander { | 536 | let file_id = match expander { |
@@ -519,8 +538,7 @@ mod tests { | |||
519 | // the first one should be a macro_rules | 538 | // the first one should be a macro_rules |
520 | let def = MacroDefId { | 539 | let def = MacroDefId { |
521 | krate: CrateId(0), | 540 | krate: CrateId(0), |
522 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), | 541 | kind: MacroDefKind::BuiltIn(expander, ast_id), |
523 | kind: MacroDefKind::BuiltIn(expander), | ||
524 | local_inner: false, | 542 | local_inner: false, |
525 | }; | 543 | }; |
526 | 544 | ||
@@ -540,8 +558,7 @@ mod tests { | |||
540 | // the first one should be a macro_rules | 558 | // the first one should be a macro_rules |
541 | let def = MacroDefId { | 559 | let def = MacroDefId { |
542 | krate, | 560 | krate, |
543 | ast_id: Some(AstId::new(file_id.into(), ast_id_map.ast_id(¯o_rules))), | 561 | kind: MacroDefKind::BuiltInEager(expander, ast_id), |
544 | kind: MacroDefKind::BuiltInEager(expander), | ||
545 | local_inner: false, | 562 | local_inner: false, |
546 | }; | 563 | }; |
547 | 564 | ||
@@ -556,16 +573,18 @@ mod tests { | |||
556 | subtree: Arc::new(parsed_args.clone()), | 573 | subtree: Arc::new(parsed_args.clone()), |
557 | krate, | 574 | krate, |
558 | call: call_id, | 575 | call: call_id, |
576 | included_file: None, | ||
559 | } | 577 | } |
560 | }); | 578 | }); |
561 | 579 | ||
562 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); | 580 | let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
563 | let eager = EagerCallLoc { | 581 | let eager = EagerCallLoc { |
564 | def, | 582 | def, |
565 | fragment, | 583 | fragment: expanded.fragment, |
566 | subtree: Arc::new(subtree), | 584 | subtree: Arc::new(expanded.subtree), |
567 | krate, | 585 | krate, |
568 | call: call_id, | 586 | call: call_id, |
587 | included_file: expanded.included_file, | ||
569 | }; | 588 | }; |
570 | 589 | ||
571 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); | 590 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs index a3070f1f9..fc73e435b 100644 --- a/crates/hir_expand/src/db.rs +++ b/crates/hir_expand/src/db.rs | |||
@@ -130,8 +130,8 @@ fn ast_id_map(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<AstIdMap> { | |||
130 | 130 | ||
131 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { | 131 | fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { |
132 | match id.kind { | 132 | match id.kind { |
133 | MacroDefKind::Declarative => { | 133 | MacroDefKind::Declarative(ast_id) => { |
134 | let macro_rules = match id.ast_id?.to_node(db) { | 134 | let macro_rules = match ast_id.to_node(db) { |
135 | syntax::ast::Macro::MacroRules(mac) => mac, | 135 | syntax::ast::Macro::MacroRules(mac) => mac, |
136 | syntax::ast::Macro::MacroDef(_) => return None, | 136 | syntax::ast::Macro::MacroDef(_) => return None, |
137 | }; | 137 | }; |
@@ -150,14 +150,14 @@ fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, | |||
150 | }; | 150 | }; |
151 | Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) | 151 | Some(Arc::new((TokenExpander::MacroRules(rules), tmap))) |
152 | } | 152 | } |
153 | MacroDefKind::BuiltIn(expander) => { | 153 | MacroDefKind::BuiltIn(expander, _) => { |
154 | Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) | 154 | Some(Arc::new((TokenExpander::Builtin(expander), mbe::TokenMap::default()))) |
155 | } | 155 | } |
156 | MacroDefKind::BuiltInDerive(expander) => { | 156 | MacroDefKind::BuiltInDerive(expander, _) => { |
157 | Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) | 157 | Some(Arc::new((TokenExpander::BuiltinDerive(expander), mbe::TokenMap::default()))) |
158 | } | 158 | } |
159 | MacroDefKind::BuiltInEager(_) => None, | 159 | MacroDefKind::BuiltInEager(..) => None, |
160 | MacroDefKind::ProcMacro(expander) => { | 160 | MacroDefKind::ProcMacro(expander, ..) => { |
161 | Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default()))) | 161 | Some(Arc::new((TokenExpander::ProcMacro(expander), mbe::TokenMap::default()))) |
162 | } | 162 | } |
163 | } | 163 | } |
@@ -173,7 +173,7 @@ fn macro_arg_text(db: &dyn AstDatabase, id: MacroCallId) -> Option<GreenNode> { | |||
173 | }; | 173 | }; |
174 | let loc = db.lookup_intern_macro(id); | 174 | let loc = db.lookup_intern_macro(id); |
175 | let arg = loc.kind.arg(db)?; | 175 | let arg = loc.kind.arg(db)?; |
176 | Some(arg.green().to_owned()) | 176 | Some(arg.green()) |
177 | } | 177 | } |
178 | 178 | ||
179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { | 179 | fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { |
@@ -269,7 +269,7 @@ fn expand_proc_macro( | |||
269 | }; | 269 | }; |
270 | 270 | ||
271 | let expander = match loc.def.kind { | 271 | let expander = match loc.def.kind { |
272 | MacroDefKind::ProcMacro(expander) => expander, | 272 | MacroDefKind::ProcMacro(expander, ..) => expander, |
273 | _ => unreachable!(), | 273 | _ => unreachable!(), |
274 | }; | 274 | }; |
275 | 275 | ||
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs index dc618a9ee..9eedc8461 100644 --- a/crates/hir_expand/src/eager.rs +++ b/crates/hir_expand/src/eager.rs | |||
@@ -124,6 +124,7 @@ pub fn expand_eager_macro( | |||
124 | subtree: Arc::new(parsed_args.clone()), | 124 | subtree: Arc::new(parsed_args.clone()), |
125 | krate, | 125 | krate, |
126 | call: call_id, | 126 | call: call_id, |
127 | included_file: None, | ||
127 | } | 128 | } |
128 | }); | 129 | }); |
129 | let arg_file_id: MacroCallId = arg_id.into(); | 130 | let arg_file_id: MacroCallId = arg_id.into(); |
@@ -140,12 +141,18 @@ pub fn expand_eager_macro( | |||
140 | let subtree = | 141 | let subtree = |
141 | diagnostic_sink.option(to_subtree(&result), || err("failed to parse macro result"))?; | 142 | diagnostic_sink.option(to_subtree(&result), || err("failed to parse macro result"))?; |
142 | 143 | ||
143 | if let MacroDefKind::BuiltInEager(eager) = def.kind { | 144 | if let MacroDefKind::BuiltInEager(eager, _) = def.kind { |
144 | let res = eager.expand(db, arg_id, &subtree); | 145 | let res = eager.expand(db, arg_id, &subtree); |
145 | 146 | ||
146 | let (subtree, fragment) = diagnostic_sink.expand_result_option(res)?; | 147 | let expanded = diagnostic_sink.expand_result_option(res)?; |
147 | let eager = | 148 | let eager = EagerCallLoc { |
148 | EagerCallLoc { def, fragment, subtree: Arc::new(subtree), krate, call: call_id }; | 149 | def, |
150 | fragment: expanded.fragment, | ||
151 | subtree: Arc::new(expanded.subtree), | ||
152 | krate, | ||
153 | call: call_id, | ||
154 | included_file: expanded.included_file, | ||
155 | }; | ||
149 | 156 | ||
150 | Ok(db.intern_eager_expansion(eager)) | 157 | Ok(db.intern_eager_expansion(eager)) |
151 | } else { | 158 | } else { |
@@ -193,7 +200,7 @@ fn eager_macro_recur( | |||
193 | let def = diagnostic_sink | 200 | let def = diagnostic_sink |
194 | .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?; | 201 | .option_with(|| macro_resolver(child.path()?), || err("failed to resolve macro"))?; |
195 | let insert = match def.kind { | 202 | let insert = match def.kind { |
196 | MacroDefKind::BuiltInEager(_) => { | 203 | MacroDefKind::BuiltInEager(..) => { |
197 | let id: MacroCallId = expand_eager_macro( | 204 | let id: MacroCallId = expand_eager_macro( |
198 | db, | 205 | db, |
199 | krate, | 206 | krate, |
@@ -206,10 +213,10 @@ fn eager_macro_recur( | |||
206 | db.parse_or_expand(id.as_file()) | 213 | db.parse_or_expand(id.as_file()) |
207 | .expect("successful macro expansion should be parseable") | 214 | .expect("successful macro expansion should be parseable") |
208 | } | 215 | } |
209 | MacroDefKind::Declarative | 216 | MacroDefKind::Declarative(_) |
210 | | MacroDefKind::BuiltIn(_) | 217 | | MacroDefKind::BuiltIn(..) |
211 | | MacroDefKind::BuiltInDerive(_) | 218 | | MacroDefKind::BuiltInDerive(..) |
212 | | MacroDefKind::ProcMacro(_) => { | 219 | | MacroDefKind::ProcMacro(..) => { |
213 | let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate); | 220 | let res = lazy_expand(db, &def, curr.with_value(child.clone()), krate); |
214 | let val = diagnostic_sink.expand_result_option(res)?; | 221 | let val = diagnostic_sink.expand_result_option(res)?; |
215 | 222 | ||
diff --git a/crates/hir_expand/src/hygiene.rs b/crates/hir_expand/src/hygiene.rs index 87cad326d..0e0f7214a 100644 --- a/crates/hir_expand/src/hygiene.rs +++ b/crates/hir_expand/src/hygiene.rs | |||
@@ -145,7 +145,7 @@ fn make_hygiene_info( | |||
145 | ) -> Option<HygieneInfo> { | 145 | ) -> Option<HygieneInfo> { |
146 | let arg_tt = loc.kind.arg(db)?; | 146 | let arg_tt = loc.kind.arg(db)?; |
147 | 147 | ||
148 | let def_offset = loc.def.ast_id.and_then(|id| { | 148 | let def_offset = loc.def.ast_id().left().and_then(|id| { |
149 | let def_tt = match id.to_node(db) { | 149 | let def_tt = match id.to_node(db) { |
150 | ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), | 150 | ast::Macro::MacroRules(mac) => mac.token_tree()?.syntax().text_range().start(), |
151 | ast::Macro::MacroDef(_) => return None, | 151 | ast::Macro::MacroDef(_) => return None, |
@@ -176,13 +176,13 @@ impl HygieneFrame { | |||
176 | let loc = db.lookup_intern_macro(id); | 176 | let loc = db.lookup_intern_macro(id); |
177 | let info = make_hygiene_info(db, macro_file, &loc); | 177 | let info = make_hygiene_info(db, macro_file, &loc); |
178 | match loc.def.kind { | 178 | match loc.def.kind { |
179 | MacroDefKind::Declarative => { | 179 | MacroDefKind::Declarative(_) => { |
180 | (info, Some(loc.def.krate), loc.def.local_inner) | 180 | (info, Some(loc.def.krate), loc.def.local_inner) |
181 | } | 181 | } |
182 | MacroDefKind::BuiltIn(_) => (info, Some(loc.def.krate), false), | 182 | MacroDefKind::BuiltIn(..) => (info, Some(loc.def.krate), false), |
183 | MacroDefKind::BuiltInDerive(_) => (info, None, false), | 183 | MacroDefKind::BuiltInDerive(..) => (info, None, false), |
184 | MacroDefKind::BuiltInEager(_) => (info, None, false), | 184 | MacroDefKind::BuiltInEager(..) => (info, None, false), |
185 | MacroDefKind::ProcMacro(_) => (info, None, false), | 185 | MacroDefKind::ProcMacro(..) => (info, None, false), |
186 | } | 186 | } |
187 | } | 187 | } |
188 | }, | 188 | }, |
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs index 7532d00b8..b8045fda9 100644 --- a/crates/hir_expand/src/lib.rs +++ b/crates/hir_expand/src/lib.rs | |||
@@ -15,6 +15,7 @@ pub mod proc_macro; | |||
15 | pub mod quote; | 15 | pub mod quote; |
16 | pub mod eager; | 16 | pub mod eager; |
17 | 17 | ||
18 | use either::Either; | ||
18 | pub use mbe::{ExpandError, ExpandResult}; | 19 | pub use mbe::{ExpandError, ExpandResult}; |
19 | 20 | ||
20 | use std::hash::Hash; | 21 | use std::hash::Hash; |
@@ -83,7 +84,11 @@ impl HirFileId { | |||
83 | } | 84 | } |
84 | MacroCallId::EagerMacro(id) => { | 85 | MacroCallId::EagerMacro(id) => { |
85 | let loc = db.lookup_intern_eager_expansion(id); | 86 | let loc = db.lookup_intern_eager_expansion(id); |
86 | loc.call.file_id | 87 | if let Some(included_file) = loc.included_file { |
88 | return included_file; | ||
89 | } else { | ||
90 | loc.call.file_id | ||
91 | } | ||
87 | } | 92 | } |
88 | }; | 93 | }; |
89 | file_id.original_file(db) | 94 | file_id.original_file(db) |
@@ -143,7 +148,7 @@ impl HirFileId { | |||
143 | 148 | ||
144 | let arg_tt = loc.kind.arg(db)?; | 149 | let arg_tt = loc.kind.arg(db)?; |
145 | 150 | ||
146 | let def = loc.def.ast_id.and_then(|id| { | 151 | let def = loc.def.ast_id().left().and_then(|id| { |
147 | let def_tt = match id.to_node(db) { | 152 | let def_tt = match id.to_node(db) { |
148 | ast::Macro::MacroRules(mac) => mac.token_tree()?, | 153 | ast::Macro::MacroRules(mac) => mac.token_tree()?, |
149 | ast::Macro::MacroDef(_) => return None, | 154 | ast::Macro::MacroDef(_) => return None, |
@@ -180,13 +185,28 @@ impl HirFileId { | |||
180 | }; | 185 | }; |
181 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); | 186 | let loc: MacroCallLoc = db.lookup_intern_macro(lazy_id); |
182 | let item = match loc.def.kind { | 187 | let item = match loc.def.kind { |
183 | MacroDefKind::BuiltInDerive(_) => loc.kind.node(db), | 188 | MacroDefKind::BuiltInDerive(..) => loc.kind.node(db), |
184 | _ => return None, | 189 | _ => return None, |
185 | }; | 190 | }; |
186 | Some(item.with_value(ast::Item::cast(item.value.clone())?)) | 191 | Some(item.with_value(ast::Item::cast(item.value.clone())?)) |
187 | } | 192 | } |
188 | } | 193 | } |
189 | } | 194 | } |
195 | |||
196 | /// Return whether this file is an include macro | ||
197 | pub fn is_include_macro(&self, db: &dyn db::AstDatabase) -> bool { | ||
198 | match self.0 { | ||
199 | HirFileIdRepr::MacroFile(macro_file) => match macro_file.macro_call_id { | ||
200 | MacroCallId::EagerMacro(id) => { | ||
201 | let loc = db.lookup_intern_eager_expansion(id); | ||
202 | return loc.included_file.is_some(); | ||
203 | } | ||
204 | _ => {} | ||
205 | }, | ||
206 | _ => {} | ||
207 | } | ||
208 | false | ||
209 | } | ||
190 | } | 210 | } |
191 | 211 | ||
192 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 212 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
@@ -224,7 +244,6 @@ impl From<EagerMacroId> for MacroCallId { | |||
224 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 244 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
225 | pub struct MacroDefId { | 245 | pub struct MacroDefId { |
226 | pub krate: CrateId, | 246 | pub krate: CrateId, |
227 | pub ast_id: Option<AstId<ast::Macro>>, | ||
228 | pub kind: MacroDefKind, | 247 | pub kind: MacroDefKind, |
229 | 248 | ||
230 | pub local_inner: bool, | 249 | pub local_inner: bool, |
@@ -239,16 +258,27 @@ impl MacroDefId { | |||
239 | ) -> LazyMacroId { | 258 | ) -> LazyMacroId { |
240 | db.intern_macro(MacroCallLoc { def: self, krate, kind }) | 259 | db.intern_macro(MacroCallLoc { def: self, krate, kind }) |
241 | } | 260 | } |
261 | |||
262 | pub fn ast_id(&self) -> Either<AstId<ast::Macro>, AstId<ast::Fn>> { | ||
263 | let id = match &self.kind { | ||
264 | MacroDefKind::Declarative(id) => id, | ||
265 | MacroDefKind::BuiltIn(_, id) => id, | ||
266 | MacroDefKind::BuiltInDerive(_, id) => id, | ||
267 | MacroDefKind::BuiltInEager(_, id) => id, | ||
268 | MacroDefKind::ProcMacro(_, id) => return Either::Right(*id), | ||
269 | }; | ||
270 | Either::Left(*id) | ||
271 | } | ||
242 | } | 272 | } |
243 | 273 | ||
244 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 274 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
245 | pub enum MacroDefKind { | 275 | pub enum MacroDefKind { |
246 | Declarative, | 276 | Declarative(AstId<ast::Macro>), |
247 | BuiltIn(BuiltinFnLikeExpander), | 277 | BuiltIn(BuiltinFnLikeExpander, AstId<ast::Macro>), |
248 | // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander | 278 | // FIXME: maybe just Builtin and rename BuiltinFnLikeExpander to BuiltinExpander |
249 | BuiltInDerive(BuiltinDeriveExpander), | 279 | BuiltInDerive(BuiltinDeriveExpander, AstId<ast::Macro>), |
250 | BuiltInEager(EagerExpander), | 280 | BuiltInEager(EagerExpander, AstId<ast::Macro>), |
251 | ProcMacro(ProcMacroExpander), | 281 | ProcMacro(ProcMacroExpander, AstId<ast::Fn>), |
252 | } | 282 | } |
253 | 283 | ||
254 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 284 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
@@ -261,21 +291,21 @@ pub struct MacroCallLoc { | |||
261 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] | 291 | #[derive(Debug, Clone, PartialEq, Eq, Hash)] |
262 | pub enum MacroCallKind { | 292 | pub enum MacroCallKind { |
263 | FnLike(AstId<ast::MacroCall>), | 293 | FnLike(AstId<ast::MacroCall>), |
264 | Attr(AstId<ast::Item>, String), | 294 | Derive(AstId<ast::Item>, String), |
265 | } | 295 | } |
266 | 296 | ||
267 | impl MacroCallKind { | 297 | impl MacroCallKind { |
268 | fn file_id(&self) -> HirFileId { | 298 | fn file_id(&self) -> HirFileId { |
269 | match self { | 299 | match self { |
270 | MacroCallKind::FnLike(ast_id) => ast_id.file_id, | 300 | MacroCallKind::FnLike(ast_id) => ast_id.file_id, |
271 | MacroCallKind::Attr(ast_id, _) => ast_id.file_id, | 301 | MacroCallKind::Derive(ast_id, _) => ast_id.file_id, |
272 | } | 302 | } |
273 | } | 303 | } |
274 | 304 | ||
275 | fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { | 305 | fn node(&self, db: &dyn db::AstDatabase) -> InFile<SyntaxNode> { |
276 | match self { | 306 | match self { |
277 | MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), | 307 | MacroCallKind::FnLike(ast_id) => ast_id.with_value(ast_id.to_node(db).syntax().clone()), |
278 | MacroCallKind::Attr(ast_id, _) => { | 308 | MacroCallKind::Derive(ast_id, _) => { |
279 | ast_id.with_value(ast_id.to_node(db).syntax().clone()) | 309 | ast_id.with_value(ast_id.to_node(db).syntax().clone()) |
280 | } | 310 | } |
281 | } | 311 | } |
@@ -286,7 +316,7 @@ impl MacroCallKind { | |||
286 | MacroCallKind::FnLike(ast_id) => { | 316 | MacroCallKind::FnLike(ast_id) => { |
287 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) | 317 | Some(ast_id.to_node(db).token_tree()?.syntax().clone()) |
288 | } | 318 | } |
289 | MacroCallKind::Attr(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), | 319 | MacroCallKind::Derive(ast_id, _) => Some(ast_id.to_node(db).syntax().clone()), |
290 | } | 320 | } |
291 | } | 321 | } |
292 | } | 322 | } |
@@ -304,6 +334,8 @@ pub struct EagerCallLoc { | |||
304 | pub(crate) subtree: Arc<tt::Subtree>, | 334 | pub(crate) subtree: Arc<tt::Subtree>, |
305 | pub(crate) krate: CrateId, | 335 | pub(crate) krate: CrateId, |
306 | pub(crate) call: AstId<ast::MacroCall>, | 336 | pub(crate) call: AstId<ast::MacroCall>, |
337 | // The included file ID of the include macro. | ||
338 | pub(crate) included_file: Option<FileId>, | ||
307 | } | 339 | } |
308 | 340 | ||
309 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro | 341 | /// ExpansionInfo mainly describes how to map text range between src and expanded macro |
diff --git a/crates/hir_expand/src/name.rs b/crates/hir_expand/src/name.rs index 43de9edd6..0aeea48d5 100644 --- a/crates/hir_expand/src/name.rs +++ b/crates/hir_expand/src/name.rs | |||
@@ -48,9 +48,8 @@ impl Name { | |||
48 | 48 | ||
49 | /// Resolve a name from the text of token. | 49 | /// Resolve a name from the text of token. |
50 | fn resolve(raw_text: &str) -> Name { | 50 | fn resolve(raw_text: &str) -> Name { |
51 | let raw_start = "r#"; | 51 | if let Some(text) = raw_text.strip_prefix("r#") { |
52 | if raw_text.starts_with(raw_start) { | 52 | Name::new_text(SmolStr::new(text)) |
53 | Name::new_text(SmolStr::new(&raw_text[raw_start.len()..])) | ||
54 | } else { | 53 | } else { |
55 | Name::new_text(raw_text.into()) | 54 | Name::new_text(raw_text.into()) |
56 | } | 55 | } |