aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbors[bot] <26634292+bors[bot]@users.noreply.github.com>2021-05-09 15:40:49 +0100
committerGitHub <[email protected]>2021-05-09 15:40:49 +0100
commit0900beeaa2ca4b9e91d51165545935d4e1db7bb6 (patch)
treedb1e1461562c7d8a90d816e5a241636f10468cdc
parent3f01edebecd5a73fc2abab75a8b29b9d64fd9fa0 (diff)
parentfd5a1d1765801ef3bda447b849951631f61f1d25 (diff)
Merge #8776
8776: fix: fix unnecessary recomputations due to macros r=jonas-schievink a=jonas-schievink This computes a macro's fragment kind eagerly (when the calling file is still available in parsed form) and stores it in the `MacroCallLoc`. This means that during expansion we no longer have to reparse the file containing the macro call, avoiding the unnecessary salsa dependencies (https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349). Marking as draft until I manage to find a test for this problem, since for some reason `typing_inside_a_function_should_not_invalidate_expansions` does not catch this (which might indicate that I misunderstand the problem). I've manually confirmed that this fixes the issue described in https://github.com/rust-analyzer/rust-analyzer/pull/8746#issuecomment-834776349: ``` 7ms - parse_query @ FileId(179) 12ms - SourceBinder::to_module_def 12ms - crate_def_map:wait 5ms - item_tree_query (1 calls) 7ms - ??? ``` Co-authored-by: Jonas Schievink <[email protected]>
-rw-r--r--crates/hir_def/src/item_tree.rs3
-rw-r--r--crates/hir_def/src/item_tree/lower.rs3
-rw-r--r--crates/hir_def/src/lib.rs12
-rw-r--r--crates/hir_def/src/nameres.rs2
-rw-r--r--crates/hir_def/src/nameres/collector.rs20
-rw-r--r--crates/hir_def/src/nameres/tests/incremental.rs6
-rw-r--r--crates/hir_expand/src/builtin_macro.rs1
-rw-r--r--crates/hir_expand/src/db.rs71
-rw-r--r--crates/hir_expand/src/eager.rs7
-rw-r--r--crates/hir_expand/src/lib.rs68
10 files changed, 119 insertions, 74 deletions
diff --git a/crates/hir_def/src/item_tree.rs b/crates/hir_def/src/item_tree.rs
index 8d13c7e04..cad8a7479 100644
--- a/crates/hir_def/src/item_tree.rs
+++ b/crates/hir_def/src/item_tree.rs
@@ -18,7 +18,7 @@ use hir_expand::{
18 ast_id_map::FileAstId, 18 ast_id_map::FileAstId,
19 hygiene::Hygiene, 19 hygiene::Hygiene,
20 name::{name, AsName, Name}, 20 name::{name, AsName, Name},
21 HirFileId, InFile, 21 FragmentKind, HirFileId, InFile,
22}; 22};
23use la_arena::{Arena, Idx, RawIdx}; 23use la_arena::{Arena, Idx, RawIdx};
24use profile::Count; 24use profile::Count;
@@ -656,6 +656,7 @@ pub struct MacroCall {
656 /// Path to the called macro. 656 /// Path to the called macro.
657 pub path: Interned<ModPath>, 657 pub path: Interned<ModPath>,
658 pub ast_id: FileAstId<ast::MacroCall>, 658 pub ast_id: FileAstId<ast::MacroCall>,
659 pub fragment: FragmentKind,
659} 660}
660 661
661#[derive(Debug, Clone, Eq, PartialEq)] 662#[derive(Debug, Clone, Eq, PartialEq)]
diff --git a/crates/hir_def/src/item_tree/lower.rs b/crates/hir_def/src/item_tree/lower.rs
index 5743b3386..fe348091d 100644
--- a/crates/hir_def/src/item_tree/lower.rs
+++ b/crates/hir_def/src/item_tree/lower.rs
@@ -624,7 +624,8 @@ impl<'a> Ctx<'a> {
624 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> { 624 fn lower_macro_call(&mut self, m: &ast::MacroCall) -> Option<FileItemTreeId<MacroCall>> {
625 let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?); 625 let path = Interned::new(ModPath::from_src(self.db, m.path()?, &self.hygiene)?);
626 let ast_id = self.source_ast_id_map.ast_id(m); 626 let ast_id = self.source_ast_id_map.ast_id(m);
627 let res = MacroCall { path, ast_id }; 627 let fragment = hir_expand::to_fragment_kind(m);
628 let res = MacroCall { path, ast_id, fragment };
628 Some(id(self.data().macro_calls.alloc(res))) 629 Some(id(self.data().macro_calls.alloc(res)))
629 } 630 }
630 631
diff --git a/crates/hir_def/src/lib.rs b/crates/hir_def/src/lib.rs
index da46f16f7..e96ca953f 100644
--- a/crates/hir_def/src/lib.rs
+++ b/crates/hir_def/src/lib.rs
@@ -62,7 +62,8 @@ use hir_expand::{
62 ast_id_map::FileAstId, 62 ast_id_map::FileAstId,
63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink}, 63 eager::{expand_eager_macro, ErrorEmitted, ErrorSink},
64 hygiene::Hygiene, 64 hygiene::Hygiene,
65 AstId, AttrId, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 65 AstId, AttrId, FragmentKind, HirFileId, InFile, MacroCallId, MacroCallKind, MacroDefId,
66 MacroDefKind,
66}; 67};
67use la_arena::Idx; 68use la_arena::Idx;
68use nameres::DefMap; 69use nameres::DefMap;
@@ -652,6 +653,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
652 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 653 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
653 mut error_sink: &mut dyn FnMut(mbe::ExpandError), 654 mut error_sink: &mut dyn FnMut(mbe::ExpandError),
654 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> { 655 ) -> Result<Result<MacroCallId, ErrorEmitted>, UnresolvedMacro> {
656 let fragment = hir_expand::to_fragment_kind(self.value);
655 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value)); 657 let ast_id = AstId::new(self.file_id, db.ast_id_map(self.file_id).ast_id(self.value));
656 let h = Hygiene::new(db.upcast(), self.file_id); 658 let h = Hygiene::new(db.upcast(), self.file_id);
657 let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h)); 659 let path = self.value.path().and_then(|path| path::ModPath::from_src(db, path, &h));
@@ -667,6 +669,7 @@ impl AsMacroCall for InFile<&ast::MacroCall> {
667 669
668 macro_call_as_call_id( 670 macro_call_as_call_id(
669 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path), 671 &AstIdWithPath::new(ast_id.file_id, ast_id.value, path),
672 fragment,
670 db, 673 db,
671 krate, 674 krate,
672 resolver, 675 resolver,
@@ -695,6 +698,7 @@ pub struct UnresolvedMacro {
695 698
696fn macro_call_as_call_id( 699fn macro_call_as_call_id(
697 call: &AstIdWithPath<ast::MacroCall>, 700 call: &AstIdWithPath<ast::MacroCall>,
701 fragment: FragmentKind,
698 db: &dyn db::DefDatabase, 702 db: &dyn db::DefDatabase,
699 krate: CrateId, 703 krate: CrateId,
700 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>, 704 resolver: impl Fn(path::ModPath) -> Option<MacroDefId>,
@@ -718,7 +722,11 @@ fn macro_call_as_call_id(
718 .map(MacroCallId::from) 722 .map(MacroCallId::from)
719 } else { 723 } else {
720 Ok(def 724 Ok(def
721 .as_lazy_macro(db.upcast(), krate, MacroCallKind::FnLike { ast_id: call.ast_id }) 725 .as_lazy_macro(
726 db.upcast(),
727 krate,
728 MacroCallKind::FnLike { ast_id: call.ast_id, fragment },
729 )
722 .into()) 730 .into())
723 }; 731 };
724 Ok(res) 732 Ok(res)
diff --git a/crates/hir_def/src/nameres.rs b/crates/hir_def/src/nameres.rs
index 1bc72ec1f..249af6fc8 100644
--- a/crates/hir_def/src/nameres.rs
+++ b/crates/hir_def/src/nameres.rs
@@ -629,7 +629,7 @@ mod diagnostics {
629 DiagnosticKind::UnresolvedProcMacro { ast } => { 629 DiagnosticKind::UnresolvedProcMacro { ast } => {
630 let mut precise_location = None; 630 let mut precise_location = None;
631 let (file, ast, name) = match ast { 631 let (file, ast, name) = match ast {
632 MacroCallKind::FnLike { ast_id } => { 632 MacroCallKind::FnLike { ast_id, .. } => {
633 let node = ast_id.to_node(db.upcast()); 633 let node = ast_id.to_node(db.upcast());
634 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None) 634 (ast_id.file_id, SyntaxNodePtr::from(AstPtr::new(&node)), None)
635 } 635 }
diff --git a/crates/hir_def/src/nameres/collector.rs b/crates/hir_def/src/nameres/collector.rs
index 05ceb1efb..e89136ed1 100644
--- a/crates/hir_def/src/nameres/collector.rs
+++ b/crates/hir_def/src/nameres/collector.rs
@@ -13,7 +13,7 @@ use hir_expand::{
13 builtin_macro::find_builtin_macro, 13 builtin_macro::find_builtin_macro,
14 name::{AsName, Name}, 14 name::{AsName, Name},
15 proc_macro::ProcMacroExpander, 15 proc_macro::ProcMacroExpander,
16 AttrId, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind, 16 AttrId, FragmentKind, HirFileId, MacroCallId, MacroCallKind, MacroDefId, MacroDefKind,
17}; 17};
18use hir_expand::{InFile, MacroCallLoc}; 18use hir_expand::{InFile, MacroCallLoc};
19use rustc_hash::{FxHashMap, FxHashSet}; 19use rustc_hash::{FxHashMap, FxHashSet};
@@ -215,7 +215,7 @@ struct MacroDirective {
215 215
216#[derive(Clone, Debug, Eq, PartialEq)] 216#[derive(Clone, Debug, Eq, PartialEq)]
217enum MacroDirectiveKind { 217enum MacroDirectiveKind {
218 FnLike { ast_id: AstIdWithPath<ast::MacroCall> }, 218 FnLike { ast_id: AstIdWithPath<ast::MacroCall>, fragment: FragmentKind },
219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId }, 219 Derive { ast_id: AstIdWithPath<ast::Item>, derive_attr: AttrId },
220} 220}
221 221
@@ -807,9 +807,10 @@ impl DefCollector<'_> {
807 let mut res = ReachedFixedPoint::Yes; 807 let mut res = ReachedFixedPoint::Yes;
808 macros.retain(|directive| { 808 macros.retain(|directive| {
809 match &directive.kind { 809 match &directive.kind {
810 MacroDirectiveKind::FnLike { ast_id } => { 810 MacroDirectiveKind::FnLike { ast_id, fragment } => {
811 match macro_call_as_call_id( 811 match macro_call_as_call_id(
812 ast_id, 812 ast_id,
813 *fragment,
813 self.db, 814 self.db,
814 self.def_map.krate, 815 self.def_map.krate,
815 |path| { 816 |path| {
@@ -926,8 +927,9 @@ impl DefCollector<'_> {
926 927
927 for directive in &self.unexpanded_macros { 928 for directive in &self.unexpanded_macros {
928 match &directive.kind { 929 match &directive.kind {
929 MacroDirectiveKind::FnLike { ast_id, .. } => match macro_call_as_call_id( 930 MacroDirectiveKind::FnLike { ast_id, fragment } => match macro_call_as_call_id(
930 ast_id, 931 ast_id,
932 *fragment,
931 self.db, 933 self.db,
932 self.def_map.krate, 934 self.def_map.krate,
933 |path| { 935 |path| {
@@ -1496,6 +1498,7 @@ impl ModCollector<'_, '_> {
1496 let mut error = None; 1498 let mut error = None;
1497 match macro_call_as_call_id( 1499 match macro_call_as_call_id(
1498 &ast_id, 1500 &ast_id,
1501 mac.fragment,
1499 self.def_collector.db, 1502 self.def_collector.db,
1500 self.def_collector.def_map.krate, 1503 self.def_collector.def_map.krate,
1501 |path| { 1504 |path| {
@@ -1524,9 +1527,14 @@ impl ModCollector<'_, '_> {
1524 } 1527 }
1525 Ok(Err(_)) => { 1528 Ok(Err(_)) => {
1526 // Built-in macro failed eager expansion. 1529 // Built-in macro failed eager expansion.
1530
1531 // FIXME: don't parse the file here
1532 let fragment = hir_expand::to_fragment_kind(
1533 &ast_id.ast_id.to_node(self.def_collector.db.upcast()),
1534 );
1527 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error( 1535 self.def_collector.def_map.diagnostics.push(DefDiagnostic::macro_error(
1528 self.module_id, 1536 self.module_id,
1529 MacroCallKind::FnLike { ast_id: ast_id.ast_id }, 1537 MacroCallKind::FnLike { ast_id: ast_id.ast_id, fragment },
1530 error.unwrap().to_string(), 1538 error.unwrap().to_string(),
1531 )); 1539 ));
1532 return; 1540 return;
@@ -1543,7 +1551,7 @@ impl ModCollector<'_, '_> {
1543 self.def_collector.unexpanded_macros.push(MacroDirective { 1551 self.def_collector.unexpanded_macros.push(MacroDirective {
1544 module_id: self.module_id, 1552 module_id: self.module_id,
1545 depth: self.macro_depth + 1, 1553 depth: self.macro_depth + 1,
1546 kind: MacroDirectiveKind::FnLike { ast_id }, 1554 kind: MacroDirectiveKind::FnLike { ast_id, fragment: mac.fragment },
1547 }); 1555 });
1548 } 1556 }
1549 1557
diff --git a/crates/hir_def/src/nameres/tests/incremental.rs b/crates/hir_def/src/nameres/tests/incremental.rs
index 227ecd162..d884a6eb4 100644
--- a/crates/hir_def/src/nameres/tests/incremental.rs
+++ b/crates/hir_def/src/nameres/tests/incremental.rs
@@ -137,6 +137,9 @@ m!(Z);
137 }); 137 });
138 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); 138 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
139 assert_eq!(n_recalculated_item_trees, 6); 139 assert_eq!(n_recalculated_item_trees, 6);
140 let n_reparsed_macros =
141 events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
142 assert_eq!(n_reparsed_macros, 3);
140 } 143 }
141 144
142 let new_text = r#" 145 let new_text = r#"
@@ -155,5 +158,8 @@ m!(Z);
155 }); 158 });
156 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count(); 159 let n_recalculated_item_trees = events.iter().filter(|it| it.contains("item_tree")).count();
157 assert_eq!(n_recalculated_item_trees, 1); 160 assert_eq!(n_recalculated_item_trees, 1);
161 let n_reparsed_macros =
162 events.iter().filter(|it| it.contains("parse_macro_expansion")).count();
163 assert_eq!(n_reparsed_macros, 0);
158 } 164 }
159} 165}
diff --git a/crates/hir_expand/src/builtin_macro.rs b/crates/hir_expand/src/builtin_macro.rs
index 0142a06ed..af9802144 100644
--- a/crates/hir_expand/src/builtin_macro.rs
+++ b/crates/hir_expand/src/builtin_macro.rs
@@ -578,6 +578,7 @@ mod tests {
578 krate, 578 krate,
579 kind: MacroCallKind::FnLike { 579 kind: MacroCallKind::FnLike {
580 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)), 580 ast_id: AstId::new(file_id.into(), ast_id_map.ast_id(&macro_call)),
581 fragment: FragmentKind::Expr,
581 }, 582 },
582 }; 583 };
583 584
diff --git a/crates/hir_expand/src/db.rs b/crates/hir_expand/src/db.rs
index d61f4b31a..6647e57e7 100644
--- a/crates/hir_expand/src/db.rs
+++ b/crates/hir_expand/src/db.rs
@@ -8,9 +8,7 @@ use parser::FragmentKind;
8use syntax::{ 8use syntax::{
9 algo::diff, 9 algo::diff,
10 ast::{self, NameOwner}, 10 ast::{self, NameOwner},
11 AstNode, GreenNode, Parse, 11 AstNode, GreenNode, Parse, SyntaxNode, SyntaxToken,
12 SyntaxKind::*,
13 SyntaxNode, SyntaxToken,
14}; 12};
15 13
16use crate::{ 14use crate::{
@@ -160,7 +158,7 @@ pub fn expand_hypothetical(
160 158
161 let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt); 159 let hypothetical_expansion = macro_def.expand(db, lazy_id, &tt);
162 160
163 let fragment_kind = to_fragment_kind(db, actual_macro_call); 161 let fragment_kind = macro_fragment_kind(db, actual_macro_call);
164 162
165 let (node, tmap_2) = 163 let (node, tmap_2) =
166 mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?; 164 mbe::token_tree_to_syntax_node(&hypothetical_expansion.value, fragment_kind).ok()?;
@@ -226,7 +224,7 @@ fn parse_macro_expansion(
226 None => return ExpandResult { value: None, err: result.err }, 224 None => return ExpandResult { value: None, err: result.err },
227 }; 225 };
228 226
229 let fragment_kind = to_fragment_kind(db, macro_file.macro_call_id); 227 let fragment_kind = macro_fragment_kind(db, macro_file.macro_call_id);
230 228
231 log::debug!("expanded = {}", tt.as_debug_string()); 229 log::debug!("expanded = {}", tt.as_debug_string());
232 log::debug!("kind = {:?}", fragment_kind); 230 log::debug!("kind = {:?}", fragment_kind);
@@ -427,62 +425,15 @@ fn hygiene_frame(db: &dyn AstDatabase, file_id: HirFileId) -> Arc<HygieneFrame>
427 Arc::new(HygieneFrame::new(db, file_id)) 425 Arc::new(HygieneFrame::new(db, file_id))
428} 426}
429 427
430/// Given a `MacroCallId`, return what `FragmentKind` it belongs to. 428fn macro_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind {
431/// FIXME: Not completed 429 match id {
432fn to_fragment_kind(db: &dyn AstDatabase, id: MacroCallId) -> FragmentKind { 430 MacroCallId::LazyMacro(id) => {
433 let lazy_id = match id { 431 let loc: MacroCallLoc = db.lookup_intern_macro(id);
434 MacroCallId::LazyMacro(id) => id, 432 loc.kind.fragment_kind()
435 MacroCallId::EagerMacro(id) => {
436 return db.lookup_intern_eager_expansion(id).fragment;
437 }
438 };
439 let syn = db.lookup_intern_macro(lazy_id).kind.node(db).value;
440
441 let parent = match syn.parent() {
442 Some(it) => it,
443 None => return FragmentKind::Statements,
444 };
445
446 match parent.kind() {
447 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
448 MACRO_STMTS => FragmentKind::Statements,
449 MACRO_PAT => FragmentKind::Pattern,
450 MACRO_TYPE => FragmentKind::Type,
451 ITEM_LIST => FragmentKind::Items,
452 LET_STMT => {
453 // FIXME: Handle LHS Pattern
454 FragmentKind::Expr
455 } 433 }
456 EXPR_STMT => FragmentKind::Statements, 434 MacroCallId::EagerMacro(id) => {
457 BLOCK_EXPR => FragmentKind::Statements, 435 let loc: EagerCallLoc = db.lookup_intern_eager_expansion(id);
458 ARG_LIST => FragmentKind::Expr, 436 loc.fragment
459 TRY_EXPR => FragmentKind::Expr,
460 TUPLE_EXPR => FragmentKind::Expr,
461 PAREN_EXPR => FragmentKind::Expr,
462 ARRAY_EXPR => FragmentKind::Expr,
463 FOR_EXPR => FragmentKind::Expr,
464 PATH_EXPR => FragmentKind::Expr,
465 CLOSURE_EXPR => FragmentKind::Expr,
466 CONDITION => FragmentKind::Expr,
467 BREAK_EXPR => FragmentKind::Expr,
468 RETURN_EXPR => FragmentKind::Expr,
469 MATCH_EXPR => FragmentKind::Expr,
470 MATCH_ARM => FragmentKind::Expr,
471 MATCH_GUARD => FragmentKind::Expr,
472 RECORD_EXPR_FIELD => FragmentKind::Expr,
473 CALL_EXPR => FragmentKind::Expr,
474 INDEX_EXPR => FragmentKind::Expr,
475 METHOD_CALL_EXPR => FragmentKind::Expr,
476 FIELD_EXPR => FragmentKind::Expr,
477 AWAIT_EXPR => FragmentKind::Expr,
478 CAST_EXPR => FragmentKind::Expr,
479 REF_EXPR => FragmentKind::Expr,
480 PREFIX_EXPR => FragmentKind::Expr,
481 RANGE_EXPR => FragmentKind::Expr,
482 BIN_EXPR => FragmentKind::Expr,
483 _ => {
484 // Unknown , Just guess it is `Items`
485 FragmentKind::Items
486 } 437 }
487 } 438 }
488} 439}
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index f12132f84..85491fe8b 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -175,8 +175,13 @@ fn lazy_expand(
175) -> ExpandResult<Option<InFile<SyntaxNode>>> { 175) -> ExpandResult<Option<InFile<SyntaxNode>>> {
176 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value); 176 let ast_id = db.ast_id_map(macro_call.file_id).ast_id(&macro_call.value);
177 177
178 let fragment = crate::to_fragment_kind(&macro_call.value);
178 let id: MacroCallId = def 179 let id: MacroCallId = def
179 .as_lazy_macro(db, krate, MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id) }) 180 .as_lazy_macro(
181 db,
182 krate,
183 MacroCallKind::FnLike { ast_id: macro_call.with_value(ast_id), fragment },
184 )
180 .into(); 185 .into();
181 186
182 let err = db.macro_expand_error(id); 187 let err = db.macro_expand_error(id);
diff --git a/crates/hir_expand/src/lib.rs b/crates/hir_expand/src/lib.rs
index 0402640de..80ab3aeee 100644
--- a/crates/hir_expand/src/lib.rs
+++ b/crates/hir_expand/src/lib.rs
@@ -16,7 +16,9 @@ pub mod quote;
16pub mod eager; 16pub mod eager;
17 17
18use either::Either; 18use either::Either;
19
19pub use mbe::{ExpandError, ExpandResult}; 20pub use mbe::{ExpandError, ExpandResult};
21pub use parser::FragmentKind;
20 22
21use std::hash::Hash; 23use std::hash::Hash;
22use std::sync::Arc; 24use std::sync::Arc;
@@ -290,7 +292,7 @@ pub struct MacroCallLoc {
290 292
291#[derive(Debug, Clone, PartialEq, Eq, Hash)] 293#[derive(Debug, Clone, PartialEq, Eq, Hash)]
292pub enum MacroCallKind { 294pub enum MacroCallKind {
293 FnLike { ast_id: AstId<ast::MacroCall> }, 295 FnLike { ast_id: AstId<ast::MacroCall>, fragment: FragmentKind },
294 Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId }, 296 Derive { ast_id: AstId<ast::Item>, derive_name: String, derive_attr: AttrId },
295} 297}
296 298
@@ -324,6 +326,13 @@ impl MacroCallKind {
324 MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()), 326 MacroCallKind::Derive { ast_id, .. } => Some(ast_id.to_node(db).syntax().clone()),
325 } 327 }
326 } 328 }
329
330 fn fragment_kind(&self) -> FragmentKind {
331 match self {
332 MacroCallKind::FnLike { fragment, .. } => *fragment,
333 MacroCallKind::Derive { .. } => FragmentKind::Items,
334 }
335 }
327} 336}
328 337
329impl MacroCallId { 338impl MacroCallId {
@@ -357,7 +366,6 @@ pub struct ExpansionInfo {
357} 366}
358 367
359pub use mbe::Origin; 368pub use mbe::Origin;
360use parser::FragmentKind;
361 369
362impl ExpansionInfo { 370impl ExpansionInfo {
363 pub fn call_node(&self) -> Option<InFile<SyntaxNode>> { 371 pub fn call_node(&self) -> Option<InFile<SyntaxNode>> {
@@ -562,3 +570,59 @@ impl<N: AstNode> InFile<N> {
562 self.with_value(self.value.syntax()) 570 self.with_value(self.value.syntax())
563 } 571 }
564} 572}
573
574/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
575/// FIXME: Not completed
576pub fn to_fragment_kind(call: &ast::MacroCall) -> FragmentKind {
577 use syntax::SyntaxKind::*;
578
579 let syn = call.syntax();
580
581 let parent = match syn.parent() {
582 Some(it) => it,
583 None => return FragmentKind::Statements,
584 };
585
586 match parent.kind() {
587 MACRO_ITEMS | SOURCE_FILE => FragmentKind::Items,
588 MACRO_STMTS => FragmentKind::Statements,
589 MACRO_PAT => FragmentKind::Pattern,
590 MACRO_TYPE => FragmentKind::Type,
591 ITEM_LIST => FragmentKind::Items,
592 LET_STMT => {
593 // FIXME: Handle LHS Pattern
594 FragmentKind::Expr
595 }
596 EXPR_STMT => FragmentKind::Statements,
597 BLOCK_EXPR => FragmentKind::Statements,
598 ARG_LIST => FragmentKind::Expr,
599 TRY_EXPR => FragmentKind::Expr,
600 TUPLE_EXPR => FragmentKind::Expr,
601 PAREN_EXPR => FragmentKind::Expr,
602 ARRAY_EXPR => FragmentKind::Expr,
603 FOR_EXPR => FragmentKind::Expr,
604 PATH_EXPR => FragmentKind::Expr,
605 CLOSURE_EXPR => FragmentKind::Expr,
606 CONDITION => FragmentKind::Expr,
607 BREAK_EXPR => FragmentKind::Expr,
608 RETURN_EXPR => FragmentKind::Expr,
609 MATCH_EXPR => FragmentKind::Expr,
610 MATCH_ARM => FragmentKind::Expr,
611 MATCH_GUARD => FragmentKind::Expr,
612 RECORD_EXPR_FIELD => FragmentKind::Expr,
613 CALL_EXPR => FragmentKind::Expr,
614 INDEX_EXPR => FragmentKind::Expr,
615 METHOD_CALL_EXPR => FragmentKind::Expr,
616 FIELD_EXPR => FragmentKind::Expr,
617 AWAIT_EXPR => FragmentKind::Expr,
618 CAST_EXPR => FragmentKind::Expr,
619 REF_EXPR => FragmentKind::Expr,
620 PREFIX_EXPR => FragmentKind::Expr,
621 RANGE_EXPR => FragmentKind::Expr,
622 BIN_EXPR => FragmentKind::Expr,
623 _ => {
624 // Unknown , Just guess it is `Items`
625 FragmentKind::Items
626 }
627 }
628}