aboutsummaryrefslogtreecommitdiff
path: root/crates/hir_expand
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir_expand')
-rw-r--r--crates/hir_expand/src/builtin_derive.rs47
-rw-r--r--crates/hir_expand/src/builtin_macro.rs79
-rw-r--r--crates/hir_expand/src/db.rs16
-rw-r--r--crates/hir_expand/src/eager.rs25
-rw-r--r--crates/hir_expand/src/hygiene.rs12
-rw-r--r--crates/hir_expand/src/lib.rs58
-rw-r--r--crates/hir_expand/src/name.rs5
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(
268mod tests { 267mod 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(&macros[0]));
304 let name = match &macros[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)]
65pub 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
72impl ExpandedEager {
73 fn new(subtree: tt::Subtree, fragment: FragmentKind) -> Self {
74 ExpandedEager { subtree, fragment, included_file: None }
75 }
76}
77
64pub fn find_builtin_macro( 78pub 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
302fn concat_expand( 314fn 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
333fn relative_file( 345fn 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
406fn include_str_expand( 424fn 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
433fn get_env_inner(db: &dyn AstDatabase, arg_id: EagerMacroId, key: &str) -> Option<String> { 451fn 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
469fn option_env_expand( 487fn 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(&macro_rules.name().unwrap().as_name()).unwrap(); 532 let expander = find_by_name(&macro_rules.name().unwrap().as_name()).unwrap();
533 let ast_id = AstId::new(file_id.into(), ast_id_map.ast_id(&macro_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(&macro_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(&macro_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
131fn macro_def(db: &dyn AstDatabase, id: MacroDefId) -> Option<Arc<(TokenExpander, mbe::TokenMap)>> { 131fn 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
179fn macro_arg(db: &dyn AstDatabase, id: MacroCallId) -> Option<Arc<(tt::Subtree, mbe::TokenMap)>> { 179fn 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;
15pub mod quote; 15pub mod quote;
16pub mod eager; 16pub mod eager;
17 17
18use either::Either;
18pub use mbe::{ExpandError, ExpandResult}; 19pub use mbe::{ExpandError, ExpandResult};
19 20
20use std::hash::Hash; 21use 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)]
225pub struct MacroDefId { 245pub 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)]
245pub enum MacroDefKind { 275pub 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)]
262pub enum MacroCallKind { 292pub 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
267impl MacroCallKind { 297impl 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 }