aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/hir_expand/src/eager.rs18
-rw-r--r--crates/ide/src/expand_macro.rs23
2 files changed, 18 insertions, 23 deletions
diff --git a/crates/hir_expand/src/eager.rs b/crates/hir_expand/src/eager.rs
index a5ac32d3c..f12132f84 100644
--- a/crates/hir_expand/src/eager.rs
+++ b/crates/hir_expand/src/eager.rs
@@ -29,7 +29,7 @@ use base_db::CrateId;
29use mbe::ExpandResult; 29use mbe::ExpandResult;
30use parser::FragmentKind; 30use parser::FragmentKind;
31use std::sync::Arc; 31use std::sync::Arc;
32use syntax::{algo::SyntaxRewriter, SyntaxNode}; 32use syntax::{ted, SyntaxNode};
33 33
34#[derive(Debug)] 34#[derive(Debug)]
35pub struct ErrorEmitted { 35pub struct ErrorEmitted {
@@ -192,10 +192,10 @@ fn eager_macro_recur(
192 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>, 192 macro_resolver: &dyn Fn(ast::Path) -> Option<MacroDefId>,
193 mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError), 193 mut diagnostic_sink: &mut dyn FnMut(mbe::ExpandError),
194) -> Result<SyntaxNode, ErrorEmitted> { 194) -> Result<SyntaxNode, ErrorEmitted> {
195 let original = curr.value.clone(); 195 let original = curr.value.clone().clone_for_update();
196 196
197 let children = curr.value.descendants().filter_map(ast::MacroCall::cast); 197 let children = original.descendants().filter_map(ast::MacroCall::cast);
198 let mut rewriter = SyntaxRewriter::default(); 198 let mut replacements = Vec::new();
199 199
200 // Collect replacement 200 // Collect replacement
201 for child in children { 201 for child in children {
@@ -214,6 +214,7 @@ fn eager_macro_recur(
214 .into(); 214 .into();
215 db.parse_or_expand(id.as_file()) 215 db.parse_or_expand(id.as_file())
216 .expect("successful macro expansion should be parseable") 216 .expect("successful macro expansion should be parseable")
217 .clone_for_update()
217 } 218 }
218 MacroDefKind::Declarative(_) 219 MacroDefKind::Declarative(_)
219 | MacroDefKind::BuiltIn(..) 220 | MacroDefKind::BuiltIn(..)
@@ -227,15 +228,14 @@ fn eager_macro_recur(
227 } 228 }
228 }; 229 };
229 230
230 // check if the whole original sytnax is replaced 231 // check if the whole original syntax is replaced
231 // Note that SyntaxRewriter cannot replace the root node itself
232 if child.syntax() == &original { 232 if child.syntax() == &original {
233 return Ok(insert); 233 return Ok(insert);
234 } 234 }
235 235
236 rewriter.replace(child.syntax(), &insert); 236 replacements.push((child, insert));
237 } 237 }
238 238
239 let res = rewriter.rewrite(&original); 239 replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new));
240 Ok(res) 240 Ok(original)
241} 241}
diff --git a/crates/ide/src/expand_macro.rs b/crates/ide/src/expand_macro.rs
index be0ee03bf..eebae5ebe 100644
--- a/crates/ide/src/expand_macro.rs
+++ b/crates/ide/src/expand_macro.rs
@@ -3,9 +3,7 @@ use std::iter;
3use hir::Semantics; 3use hir::Semantics;
4use ide_db::RootDatabase; 4use ide_db::RootDatabase;
5use syntax::{ 5use syntax::{
6 algo::{find_node_at_offset, SyntaxRewriter}, 6 algo::find_node_at_offset, ast, ted, AstNode, NodeOrToken, SyntaxKind, SyntaxKind::*,
7 ast, AstNode, NodeOrToken, SyntaxKind,
8 SyntaxKind::*,
9 SyntaxNode, WalkEvent, T, 7 SyntaxNode, WalkEvent, T,
10}; 8};
11 9
@@ -46,26 +44,23 @@ fn expand_macro_recur(
46 sema: &Semantics<RootDatabase>, 44 sema: &Semantics<RootDatabase>,
47 macro_call: &ast::MacroCall, 45 macro_call: &ast::MacroCall,
48) -> Option<SyntaxNode> { 46) -> Option<SyntaxNode> {
49 let mut expanded = sema.expand(macro_call)?; 47 let expanded = sema.expand(macro_call)?.clone_for_update();
50 48
51 let children = expanded.descendants().filter_map(ast::MacroCall::cast); 49 let children = expanded.descendants().filter_map(ast::MacroCall::cast);
52 let mut rewriter = SyntaxRewriter::default(); 50 let mut replacements = Vec::new();
53 51
54 for child in children.into_iter() { 52 for child in children {
55 if let Some(new_node) = expand_macro_recur(sema, &child) { 53 if let Some(new_node) = expand_macro_recur(sema, &child) {
56 // Replace the whole node if it is root 54 // check if the whole original syntax is replaced
57 // `replace_descendants` will not replace the parent node
58 // but `SyntaxNode::descendants include itself
59 if expanded == *child.syntax() { 55 if expanded == *child.syntax() {
60 expanded = new_node; 56 return Some(new_node);
61 } else {
62 rewriter.replace(child.syntax(), &new_node)
63 } 57 }
58 replacements.push((child, new_node));
64 } 59 }
65 } 60 }
66 61
67 let res = rewriter.rewrite(&expanded); 62 replacements.into_iter().rev().for_each(|(old, new)| ted::replace(old.syntax(), new));
68 Some(res) 63 Some(expanded)
69} 64}
70 65
71// FIXME: It would also be cool to share logic here and in the mbe tests, 66// FIXME: It would also be cool to share logic here and in the mbe tests,