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_macro.rs66
-rw-r--r--crates/hir_expand/src/eager.rs13
-rw-r--r--crates/hir_expand/src/lib.rs23
3 files changed, 76 insertions, 26 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)]
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,
@@ -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
300fn concat_expand( 314fn 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
331fn relative_file( 345fn 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
404fn include_str_expand( 424fn 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
431fn 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> {
@@ -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
467fn option_env_expand( 487fn 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();
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index 04f374a29..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();
@@ -143,9 +144,15 @@ pub fn expand_eager_macro(
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 {
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index f49fd4fda..b8045fda9 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -84,7 +84,11 @@ impl HirFileId {
84 } 84 }
85 MacroCallId::EagerMacro(id) => { 85 MacroCallId::EagerMacro(id) => {
86 let loc = db.lookup_intern_eager_expansion(id); 86 let loc = db.lookup_intern_eager_expansion(id);
87 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 }
88 } 92 }
89 }; 93 };
90 file_id.original_file(db) 94 file_id.original_file(db)
@@ -188,6 +192,21 @@ impl HirFileId {
188 } 192 }
189 } 193 }
190 } 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 }
191} 210}
192 211
193#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 212#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -315,6 +334,8 @@ pub struct EagerCallLoc {
315 pub(crate) subtree: Arc<tt::Subtree>, 334 pub(crate) subtree: Arc<tt::Subtree>,
316 pub(crate) krate: CrateId, 335 pub(crate) krate: CrateId,
317 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>,
318} 339}
319 340
320/// 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