diff options
author | Aleksey Kladov <[email protected]> | 2019-05-04 15:38:09 +0100 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-05-04 15:38:09 +0100 |
commit | 5dc384132f7fe6f610ec21e62830ab83f45274a9 (patch) | |
tree | f9b89014aff6dab0353b2134dc5e8cf502f7fc4f /crates | |
parent | 8876f44054f57c1f4ee305eb47340609683bd566 (diff) |
introduce macro_arg intermediate query
Currently, when expanding macros, we look at the source code
directly (we invoke ast_id_to_node query via to_node method).
This is less then ideal, because it make us re-expand macros after
every source change.
This commit establishes a salsa-firewall: a query to get macro call's
token tree. Unlike the syntax tree, token tree changes only if we
actually modify the macro itself.
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir/src/db.rs | 5 | ||||
-rw-r--r-- | crates/ra_hir/src/expr.rs | 33 | ||||
-rw-r--r-- | crates/ra_hir/src/ids.rs | 14 |
3 files changed, 27 insertions, 25 deletions
diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 8af0a3176..f88ae61bb 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs | |||
@@ -42,7 +42,10 @@ pub trait DefDatabase: SourceDatabase { | |||
42 | #[salsa::invoke(crate::ids::macro_def_query)] | 42 | #[salsa::invoke(crate::ids::macro_def_query)] |
43 | fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; | 43 | fn macro_def(&self, macro_id: MacroDefId) -> Option<Arc<mbe::MacroRules>>; |
44 | 44 | ||
45 | #[salsa::invoke(HirFileId::hir_parse_query)] | 45 | #[salsa::invoke(crate::ids::macro_arg_query)] |
46 | fn macro_arg(&self, macro_call: ids::MacroCallId) -> Option<Arc<tt::Subtree>>; | ||
47 | |||
48 | #[salsa::invoke(crate::ids::HirFileId::hir_parse_query)] | ||
46 | fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; | 49 | fn hir_parse(&self, file_id: HirFileId) -> TreeArc<SourceFile>; |
47 | 50 | ||
48 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] | 51 | #[salsa::invoke(crate::adt::StructData::struct_data_query)] |
diff --git a/crates/ra_hir/src/expr.rs b/crates/ra_hir/src/expr.rs index cdadf3ba6..f9b3f5443 100644 --- a/crates/ra_hir/src/expr.rs +++ b/crates/ra_hir/src/expr.rs | |||
@@ -826,21 +826,20 @@ where | |||
826 | .with_file_id(self.current_file_id); | 826 | .with_file_id(self.current_file_id); |
827 | 827 | ||
828 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) { | 828 | if let Some(call_id) = self.resolver.resolve_macro_call(self.db, path, ast_id) { |
829 | if let Some(expr) = expand_macro_to_expr(self.db, call_id, e.token_tree()) { | 829 | if let Some(arg) = self.db.macro_arg(call_id) { |
830 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); | 830 | if let Some(expr) = expand_macro_to_expr(self.db, call_id, &arg) { |
831 | let old_file_id = | 831 | log::debug!("macro expansion {}", expr.syntax().debug_dump()); |
832 | std::mem::replace(&mut self.current_file_id, call_id.into()); | 832 | let old_file_id = |
833 | let id = self.collect_expr(&expr); | 833 | std::mem::replace(&mut self.current_file_id, call_id.into()); |
834 | self.current_file_id = old_file_id; | 834 | let id = self.collect_expr(&expr); |
835 | id | 835 | self.current_file_id = old_file_id; |
836 | } else { | 836 | return id; |
837 | // FIXME: Instead of just dropping the error from expansion | 837 | } |
838 | // report it | ||
839 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
840 | } | 838 | } |
841 | } else { | ||
842 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
843 | } | 839 | } |
840 | // FIXME: Instead of just dropping the error from expansion | ||
841 | // report it | ||
842 | self.alloc_expr(Expr::Missing, syntax_ptr) | ||
844 | } | 843 | } |
845 | } | 844 | } |
846 | } | 845 | } |
@@ -1002,14 +1001,10 @@ where | |||
1002 | fn expand_macro_to_expr( | 1001 | fn expand_macro_to_expr( |
1003 | db: &impl HirDatabase, | 1002 | db: &impl HirDatabase, |
1004 | macro_call: MacroCallId, | 1003 | macro_call: MacroCallId, |
1005 | args: Option<&ast::TokenTree>, | 1004 | arg: &tt::Subtree, |
1006 | ) -> Option<TreeArc<ast::Expr>> { | 1005 | ) -> Option<TreeArc<ast::Expr>> { |
1007 | let rules = db.macro_def(macro_call.loc(db).def)?; | 1006 | let rules = db.macro_def(macro_call.loc(db).def)?; |
1008 | 1007 | let expanded = rules.expand(&arg).ok()?; | |
1009 | let args = mbe::ast_to_token_tree(args?)?.0; | ||
1010 | |||
1011 | let expanded = rules.expand(&args).ok()?; | ||
1012 | |||
1013 | mbe::token_tree_to_expr(&expanded).ok() | 1008 | mbe::token_tree_to_expr(&expanded).ok() |
1014 | } | 1009 | } |
1015 | 1010 | ||
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs index b0e9b1f9a..24c5f412b 100644 --- a/crates/ra_hir/src/ids.rs +++ b/crates/ra_hir/src/ids.rs | |||
@@ -86,11 +86,7 @@ fn parse_macro( | |||
86 | macro_call_id: MacroCallId, | 86 | macro_call_id: MacroCallId, |
87 | ) -> Result<TreeArc<SourceFile>, String> { | 87 | ) -> Result<TreeArc<SourceFile>, String> { |
88 | let loc = macro_call_id.loc(db); | 88 | let loc = macro_call_id.loc(db); |
89 | let macro_call = loc.ast_id.to_node(db); | 89 | let macro_arg = db.macro_arg(macro_call_id).ok_or("Fail to args in to tt::TokenTree")?; |
90 | let (macro_arg, _) = macro_call | ||
91 | .token_tree() | ||
92 | .and_then(mbe::ast_to_token_tree) | ||
93 | .ok_or("Fail to args in to tt::TokenTree")?; | ||
94 | 90 | ||
95 | let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?; | 91 | let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?; |
96 | let tt = macro_rules.expand(¯o_arg).map_err(|err| format!("{:?}", err))?; | 92 | let tt = macro_rules.expand(¯o_arg).map_err(|err| format!("{:?}", err))?; |
@@ -139,6 +135,14 @@ pub(crate) fn macro_def_query(db: &impl DefDatabase, id: MacroDefId) -> Option<A | |||
139 | Some(Arc::new(rules)) | 135 | Some(Arc::new(rules)) |
140 | } | 136 | } |
141 | 137 | ||
138 | pub(crate) fn macro_arg_query(db: &impl DefDatabase, id: MacroCallId) -> Option<Arc<tt::Subtree>> { | ||
139 | let loc = id.loc(db); | ||
140 | let macro_call = loc.ast_id.to_node(db); | ||
141 | let arg = macro_call.token_tree()?; | ||
142 | let (tt, _) = mbe::ast_to_token_tree(arg)?; | ||
143 | Some(Arc::new(tt)) | ||
144 | } | ||
145 | |||
142 | macro_rules! impl_intern_key { | 146 | macro_rules! impl_intern_key { |
143 | ($name:ident) => { | 147 | ($name:ident) => { |
144 | impl salsa::InternKey for $name { | 148 | impl salsa::InternKey for $name { |