diff options
author | bors[bot] <26634292+bors[bot]@users.noreply.github.com> | 2020-03-15 12:15:09 +0000 |
---|---|---|
committer | GitHub <[email protected]> | 2020-03-15 12:15:09 +0000 |
commit | efa72c899d0c1e628d2e944cac91ac3266da2c59 (patch) | |
tree | 5ddbf69ebecbba36403358829ba63c22a3046dd1 /crates/ra_hir_def/src/body | |
parent | 5429e6831c7a59425b37dec475f153848254a87d (diff) | |
parent | fe78a14bbb9769c8ccd5cc41415702f5176a8e88 (diff) |
Merge #3591
3591: Support local macro_rules r=matklad a=edwin0cheng
This PR implement local `macro_rules` in function body, by adding following things:
1. While lowering, add a `MacroDefId` in body's `ItemScope` as a textual legacy macro.
2. Make `Expander::enter_expand` search with given `ItemScope`.
3. Make `Resolver::resolve_path_as_macro` search with `LocalItemScope`.
Fix #2181
Co-authored-by: Edwin Cheng <[email protected]>
Diffstat (limited to 'crates/ra_hir_def/src/body')
-rw-r--r-- | crates/ra_hir_def/src/body/lower.rs | 48 |
1 files changed, 36 insertions, 12 deletions
diff --git a/crates/ra_hir_def/src/body/lower.rs b/crates/ra_hir_def/src/body/lower.rs index ec1b0c2e7..54b5591d3 100644 --- a/crates/ra_hir_def/src/body/lower.rs +++ b/crates/ra_hir_def/src/body/lower.rs | |||
@@ -3,7 +3,10 @@ | |||
3 | 3 | ||
4 | use either::Either; | 4 | use either::Either; |
5 | 5 | ||
6 | use hir_expand::name::{name, AsName, Name}; | 6 | use hir_expand::{ |
7 | name::{name, AsName, Name}, | ||
8 | MacroDefId, MacroDefKind, | ||
9 | }; | ||
7 | use ra_arena::Arena; | 10 | use ra_arena::Arena; |
8 | use ra_syntax::{ | 11 | use ra_syntax::{ |
9 | ast::{ | 12 | ast::{ |
@@ -452,19 +455,30 @@ where | |||
452 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | 455 | None => self.alloc_expr(Expr::Missing, syntax_ptr), |
453 | } | 456 | } |
454 | } | 457 | } |
455 | // FIXME expand to statements in statement position | ||
456 | ast::Expr::MacroCall(e) => { | 458 | ast::Expr::MacroCall(e) => { |
457 | let macro_call = self.expander.to_source(AstPtr::new(&e)); | 459 | if let Some(name) = is_macro_rules(&e) { |
458 | match self.expander.enter_expand(self.db, e) { | 460 | let mac = MacroDefId { |
459 | Some((mark, expansion)) => { | 461 | krate: Some(self.expander.module.krate), |
460 | self.source_map | 462 | ast_id: Some(self.expander.ast_id(&e)), |
461 | .expansions | 463 | kind: MacroDefKind::Declarative, |
462 | .insert(macro_call, self.expander.current_file_id); | 464 | }; |
463 | let id = self.collect_expr(expansion); | 465 | self.body.item_scope.define_legacy_macro(name, mac); |
464 | self.expander.exit(self.db, mark); | 466 | |
465 | id | 467 | // FIXME: do we still need to allocate this as missing ? |
468 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
469 | } else { | ||
470 | let macro_call = self.expander.to_source(AstPtr::new(&e)); | ||
471 | match self.expander.enter_expand(self.db, Some(&self.body.item_scope), e) { | ||
472 | Some((mark, expansion)) => { | ||
473 | self.source_map | ||
474 | .expansions | ||
475 | .insert(macro_call, self.expander.current_file_id); | ||
476 | let id = self.collect_expr(expansion); | ||
477 | self.expander.exit(self.db, mark); | ||
478 | id | ||
479 | } | ||
480 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
466 | } | 481 | } |
467 | None => self.alloc_expr(Expr::Missing, syntax_ptr), | ||
468 | } | 482 | } |
469 | } | 483 | } |
470 | 484 | ||
@@ -686,6 +700,16 @@ where | |||
686 | } | 700 | } |
687 | } | 701 | } |
688 | 702 | ||
703 | fn is_macro_rules(m: &ast::MacroCall) -> Option<Name> { | ||
704 | let name = m.path()?.segment()?.name_ref()?.as_name(); | ||
705 | |||
706 | if name == name![macro_rules] { | ||
707 | Some(m.name()?.as_name()) | ||
708 | } else { | ||
709 | None | ||
710 | } | ||
711 | } | ||
712 | |||
689 | impl From<ast::BinOp> for BinaryOp { | 713 | impl From<ast::BinOp> for BinaryOp { |
690 | fn from(ast_op: ast::BinOp) -> Self { | 714 | fn from(ast_op: ast::BinOp) -> Self { |
691 | match ast_op { | 715 | match ast_op { |