diff options
-rw-r--r-- | crates/hir_expand/src/eager.rs | 18 | ||||
-rw-r--r-- | crates/ide/src/expand_macro.rs | 23 |
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; | |||
29 | use mbe::ExpandResult; | 29 | use mbe::ExpandResult; |
30 | use parser::FragmentKind; | 30 | use parser::FragmentKind; |
31 | use std::sync::Arc; | 31 | use std::sync::Arc; |
32 | use syntax::{algo::SyntaxRewriter, SyntaxNode}; | 32 | use syntax::{ted, SyntaxNode}; |
33 | 33 | ||
34 | #[derive(Debug)] | 34 | #[derive(Debug)] |
35 | pub struct ErrorEmitted { | 35 | pub 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; | |||
3 | use hir::Semantics; | 3 | use hir::Semantics; |
4 | use ide_db::RootDatabase; | 4 | use ide_db::RootDatabase; |
5 | use syntax::{ | 5 | use 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, |