diff options
Diffstat (limited to 'crates/hir_expand/src/builtin_macro.rs')
-rw-r--r-- | crates/hir_expand/src/builtin_macro.rs | 66 |
1 files changed, 44 insertions, 22 deletions
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs index 8529b43b6..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, |
@@ -280,7 +294,7 @@ fn compile_error_expand( | |||
280 | _db: &dyn AstDatabase, | 294 | _db: &dyn AstDatabase, |
281 | _id: EagerMacroId, | 295 | _id: EagerMacroId, |
282 | tt: &tt::Subtree, | 296 | tt: &tt::Subtree, |
283 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 297 | ) -> ExpandResult<Option<ExpandedEager>> { |
284 | let err = match &*tt.token_trees { | 298 | let err = match &*tt.token_trees { |
285 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { | 299 | [tt::TokenTree::Leaf(tt::Leaf::Literal(it))] => { |
286 | let text = it.text.as_str(); | 300 | let text = it.text.as_str(); |
@@ -294,14 +308,14 @@ fn compile_error_expand( | |||
294 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), | 308 | _ => mbe::ExpandError::BindingError("`compile_error!` argument must be a string".into()), |
295 | }; | 309 | }; |
296 | 310 | ||
297 | ExpandResult { value: Some((quote! {}, FragmentKind::Items)), err: Some(err) } | 311 | ExpandResult { value: Some(ExpandedEager::new(quote! {}, FragmentKind::Items)), err: Some(err) } |
298 | } | 312 | } |
299 | 313 | ||
300 | fn concat_expand( | 314 | fn concat_expand( |
301 | _db: &dyn AstDatabase, | 315 | _db: &dyn AstDatabase, |
302 | _arg_id: EagerMacroId, | 316 | _arg_id: EagerMacroId, |
303 | tt: &tt::Subtree, | 317 | tt: &tt::Subtree, |
304 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 318 | ) -> ExpandResult<Option<ExpandedEager>> { |
305 | let mut err = None; | 319 | let mut err = None; |
306 | let mut text = String::new(); | 320 | let mut text = String::new(); |
307 | for (i, t) in tt.token_trees.iter().enumerate() { | 321 | for (i, t) in tt.token_trees.iter().enumerate() { |
@@ -325,7 +339,7 @@ fn concat_expand( | |||
325 | } | 339 | } |
326 | } | 340 | } |
327 | } | 341 | } |
328 | ExpandResult { value: Some((quote!(#text), FragmentKind::Expr)), err } | 342 | ExpandResult { value: Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr)), err } |
329 | } | 343 | } |
330 | 344 | ||
331 | fn relative_file( | 345 | fn relative_file( |
@@ -361,21 +375,27 @@ fn include_expand( | |||
361 | db: &dyn AstDatabase, | 375 | db: &dyn AstDatabase, |
362 | arg_id: EagerMacroId, | 376 | arg_id: EagerMacroId, |
363 | tt: &tt::Subtree, | 377 | tt: &tt::Subtree, |
364 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 378 | ) -> ExpandResult<Option<ExpandedEager>> { |
365 | let res = (|| { | 379 | let res = (|| { |
366 | let path = parse_string(tt)?; | 380 | let path = parse_string(tt)?; |
367 | let file_id = relative_file(db, arg_id.into(), &path, false)?; | 381 | let file_id = relative_file(db, arg_id.into(), &path, false)?; |
368 | 382 | ||
369 | Ok(parse_to_token_tree(&db.file_text(file_id)) | 383 | let subtree = parse_to_token_tree(&db.file_text(file_id)) |
370 | .ok_or_else(|| mbe::ExpandError::ConversionError)? | 384 | .ok_or_else(|| mbe::ExpandError::ConversionError)? |
371 | .0) | 385 | .0; |
386 | Ok((subtree, file_id)) | ||
372 | })(); | 387 | })(); |
373 | 388 | ||
374 | match res { | 389 | match res { |
375 | Ok(res) => { | 390 | Ok((subtree, file_id)) => { |
376 | // FIXME: | 391 | // FIXME: |
377 | // Handle include as expression | 392 | // Handle include as expression |
378 | 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 | })) | ||
379 | } | 399 | } |
380 | Err(e) => ExpandResult::only_err(e), | 400 | Err(e) => ExpandResult::only_err(e), |
381 | } | 401 | } |
@@ -385,7 +405,7 @@ fn include_bytes_expand( | |||
385 | _db: &dyn AstDatabase, | 405 | _db: &dyn AstDatabase, |
386 | _arg_id: EagerMacroId, | 406 | _arg_id: EagerMacroId, |
387 | tt: &tt::Subtree, | 407 | tt: &tt::Subtree, |
388 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 408 | ) -> ExpandResult<Option<ExpandedEager>> { |
389 | if let Err(e) = parse_string(tt) { | 409 | if let Err(e) = parse_string(tt) { |
390 | return ExpandResult::only_err(e); | 410 | return ExpandResult::only_err(e); |
391 | } | 411 | } |
@@ -398,14 +418,14 @@ fn include_bytes_expand( | |||
398 | id: tt::TokenId::unspecified(), | 418 | id: tt::TokenId::unspecified(), |
399 | }))], | 419 | }))], |
400 | }; | 420 | }; |
401 | ExpandResult::ok(Some((res, FragmentKind::Expr))) | 421 | ExpandResult::ok(Some(ExpandedEager::new(res, FragmentKind::Expr))) |
402 | } | 422 | } |
403 | 423 | ||
404 | fn include_str_expand( | 424 | fn include_str_expand( |
405 | db: &dyn AstDatabase, | 425 | db: &dyn AstDatabase, |
406 | arg_id: EagerMacroId, | 426 | arg_id: EagerMacroId, |
407 | tt: &tt::Subtree, | 427 | tt: &tt::Subtree, |
408 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 428 | ) -> ExpandResult<Option<ExpandedEager>> { |
409 | let path = match parse_string(tt) { | 429 | let path = match parse_string(tt) { |
410 | Ok(it) => it, | 430 | Ok(it) => it, |
411 | Err(e) => return ExpandResult::only_err(e), | 431 | Err(e) => return ExpandResult::only_err(e), |
@@ -418,14 +438,14 @@ fn include_str_expand( | |||
418 | 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) { |
419 | Ok(file_id) => file_id, | 439 | Ok(file_id) => file_id, |
420 | Err(_) => { | 440 | Err(_) => { |
421 | return ExpandResult::ok(Some((quote!(""), FragmentKind::Expr))); | 441 | return ExpandResult::ok(Some(ExpandedEager::new(quote!(""), FragmentKind::Expr))); |
422 | } | 442 | } |
423 | }; | 443 | }; |
424 | 444 | ||
425 | let text = db.file_text(file_id); | 445 | let text = db.file_text(file_id); |
426 | let text = &*text; | 446 | let text = &*text; |
427 | 447 | ||
428 | ExpandResult::ok(Some((quote!(#text), FragmentKind::Expr))) | 448 | ExpandResult::ok(Some(ExpandedEager::new(quote!(#text), FragmentKind::Expr))) |
429 | } | 449 | } |
430 | 450 | ||
431 | 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> { |
@@ -437,7 +457,7 @@ fn env_expand( | |||
437 | db: &dyn AstDatabase, | 457 | db: &dyn AstDatabase, |
438 | arg_id: EagerMacroId, | 458 | arg_id: EagerMacroId, |
439 | tt: &tt::Subtree, | 459 | tt: &tt::Subtree, |
440 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 460 | ) -> ExpandResult<Option<ExpandedEager>> { |
441 | let key = match parse_string(tt) { | 461 | let key = match parse_string(tt) { |
442 | Ok(it) => it, | 462 | Ok(it) => it, |
443 | Err(e) => return ExpandResult::only_err(e), | 463 | Err(e) => return ExpandResult::only_err(e), |
@@ -461,14 +481,14 @@ fn env_expand( | |||
461 | }); | 481 | }); |
462 | let expanded = quote! { #s }; | 482 | let expanded = quote! { #s }; |
463 | 483 | ||
464 | ExpandResult { value: Some((expanded, FragmentKind::Expr)), err } | 484 | ExpandResult { value: Some(ExpandedEager::new(expanded, FragmentKind::Expr)), err } |
465 | } | 485 | } |
466 | 486 | ||
467 | fn option_env_expand( | 487 | fn option_env_expand( |
468 | db: &dyn AstDatabase, | 488 | db: &dyn AstDatabase, |
469 | arg_id: EagerMacroId, | 489 | arg_id: EagerMacroId, |
470 | tt: &tt::Subtree, | 490 | tt: &tt::Subtree, |
471 | ) -> ExpandResult<Option<(tt::Subtree, FragmentKind)>> { | 491 | ) -> ExpandResult<Option<ExpandedEager>> { |
472 | let key = match parse_string(tt) { | 492 | let key = match parse_string(tt) { |
473 | Ok(it) => it, | 493 | Ok(it) => it, |
474 | Err(e) => return ExpandResult::only_err(e), | 494 | Err(e) => return ExpandResult::only_err(e), |
@@ -479,7 +499,7 @@ fn option_env_expand( | |||
479 | Some(s) => quote! { std::option::Some(#s) }, | 499 | Some(s) => quote! { std::option::Some(#s) }, |
480 | }; | 500 | }; |
481 | 501 | ||
482 | ExpandResult::ok(Some((expanded, FragmentKind::Expr))) | 502 | ExpandResult::ok(Some(ExpandedEager::new(expanded, FragmentKind::Expr))) |
483 | } | 503 | } |
484 | 504 | ||
485 | #[cfg(test)] | 505 | #[cfg(test)] |
@@ -553,16 +573,18 @@ mod tests { | |||
553 | subtree: Arc::new(parsed_args.clone()), | 573 | subtree: Arc::new(parsed_args.clone()), |
554 | krate, | 574 | krate, |
555 | call: call_id, | 575 | call: call_id, |
576 | included_file: None, | ||
556 | } | 577 | } |
557 | }); | 578 | }); |
558 | 579 | ||
559 | let (subtree, fragment) = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); | 580 | let expanded = expander.expand(&db, arg_id, &parsed_args).value.unwrap(); |
560 | let eager = EagerCallLoc { | 581 | let eager = EagerCallLoc { |
561 | def, | 582 | def, |
562 | fragment, | 583 | fragment: expanded.fragment, |
563 | subtree: Arc::new(subtree), | 584 | subtree: Arc::new(expanded.subtree), |
564 | krate, | 585 | krate, |
565 | call: call_id, | 586 | call: call_id, |
587 | included_file: expanded.included_file, | ||
566 | }; | 588 | }; |
567 | 589 | ||
568 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); | 590 | let id: MacroCallId = db.intern_eager_expansion(eager).into(); |