aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand/src')
-rw-r--r--crates/ra_hir_expand/src/db.rs24
-rw-r--r--crates/ra_hir_expand/src/eager.rs17
2 files changed, 28 insertions, 13 deletions
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs
index d171d2dfd..5a696542f 100644
--- a/crates/ra_hir_expand/src/db.rs
+++ b/crates/ra_hir_expand/src/db.rs
@@ -6,7 +6,7 @@ use mbe::{ExpandResult, MacroRules};
6use ra_db::{salsa, SourceDatabase}; 6use ra_db::{salsa, SourceDatabase};
7use ra_parser::FragmentKind; 7use ra_parser::FragmentKind;
8use ra_prof::profile; 8use ra_prof::profile;
9use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode}; 9use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode};
10 10
11use crate::{ 11use crate::{
12 ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId, 12 ast_id_map::AstIdMap, BuiltinDeriveExpander, BuiltinFnLikeExpander, EagerCallLoc, EagerMacroId,
@@ -238,7 +238,7 @@ pub fn parse_macro_with_arg(
238 } else { 238 } else {
239 db.macro_expand(macro_call_id) 239 db.macro_expand(macro_call_id)
240 }; 240 };
241 if let Some(err) = err { 241 if let Some(err) = &err {
242 // Note: 242 // Note:
243 // The final goal we would like to make all parse_macro success, 243 // The final goal we would like to make all parse_macro success,
244 // such that the following log will not call anyway. 244 // such that the following log will not call anyway.
@@ -272,7 +272,25 @@ pub fn parse_macro_with_arg(
272 let fragment_kind = to_fragment_kind(db, macro_call_id); 272 let fragment_kind = to_fragment_kind(db, macro_call_id);
273 273
274 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?; 274 let (parse, rev_token_map) = mbe::token_tree_to_syntax_node(&tt, fragment_kind).ok()?;
275 Some((parse, Arc::new(rev_token_map))) 275
276 if err.is_none() {
277 Some((parse, Arc::new(rev_token_map)))
278 } else {
279 // FIXME:
280 // In future, we should propagate the actual error with recovery information
281 // instead of ignore the error here.
282
283 // Safe check for recurisve identity macro
284 let node = parse.syntax_node();
285 let file: HirFileId = macro_file.into();
286 let call_node = file.call_node(db)?;
287
288 if !diff(&node, &call_node.value).is_empty() {
289 Some((parse, Arc::new(rev_token_map)))
290 } else {
291 None
292 }
293 }
276} 294}
277 295
278/// Given a `MacroCallId`, return what `FragmentKind` it belongs to. 296/// Given a `MacroCallId`, return what `FragmentKind` it belongs to.
diff --git a/crates/ra_hir_expand/src/eager.rs b/crates/ra_hir_expand/src/eager.rs
index 4cbce4df5..687d40294 100644
--- a/crates/ra_hir_expand/src/eager.rs
+++ b/crates/ra_hir_expand/src/eager.rs
@@ -26,8 +26,8 @@ use crate::{
26}; 26};
27 27
28use ra_parser::FragmentKind; 28use ra_parser::FragmentKind;
29use ra_syntax::{algo::replace_descendants, SyntaxElement, SyntaxNode}; 29use ra_syntax::{algo::SyntaxRewriter, SyntaxNode};
30use std::{collections::HashMap, sync::Arc}; 30use std::sync::Arc;
31 31
32pub fn expand_eager_macro( 32pub fn expand_eager_macro(
33 db: &dyn AstDatabase, 33 db: &dyn AstDatabase,
@@ -95,10 +95,10 @@ fn eager_macro_recur(
95 curr: InFile<SyntaxNode>, 95 curr: InFile<SyntaxNode>,
96 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 96 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
97) -> Option<SyntaxNode> { 97) -> Option<SyntaxNode> {
98 let mut original = curr.value.clone(); 98 let original = curr.value.clone();
99 99
100 let children = curr.value.descendants().filter_map(ast::MacroCall::cast); 100 let children = curr.value.descendants().filter_map(ast::MacroCall::cast);
101 let mut replaces: HashMap<SyntaxElement, SyntaxElement> = HashMap::default(); 101 let mut rewriter = SyntaxRewriter::default();
102 102
103 // Collect replacement 103 // Collect replacement
104 for child in children { 104 for child in children {
@@ -119,12 +119,9 @@ fn eager_macro_recur(
119 } 119 }
120 }; 120 };
121 121
122 replaces.insert(child.syntax().clone().into(), insert.into()); 122 rewriter.replace(child.syntax(), &insert);
123 } 123 }
124 124
125 if !replaces.is_empty() { 125 let res = rewriter.rewrite(&original);
126 original = replace_descendants(&original, |n| replaces.get(n).cloned()); 126 Some(res)
127 }
128
129 Some(original)
130} 127}