diff options
Diffstat (limited to 'crates/ra_hir_expand/src')
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 24 | ||||
-rw-r--r-- | crates/ra_hir_expand/src/eager.rs | 17 |
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}; | |||
6 | use ra_db::{salsa, SourceDatabase}; | 6 | use ra_db::{salsa, SourceDatabase}; |
7 | use ra_parser::FragmentKind; | 7 | use ra_parser::FragmentKind; |
8 | use ra_prof::profile; | 8 | use ra_prof::profile; |
9 | use ra_syntax::{AstNode, Parse, SyntaxKind::*, SyntaxNode}; | 9 | use ra_syntax::{algo::diff, AstNode, Parse, SyntaxKind::*, SyntaxNode}; |
10 | 10 | ||
11 | use crate::{ | 11 | use 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 | ||
28 | use ra_parser::FragmentKind; | 28 | use ra_parser::FragmentKind; |
29 | use ra_syntax::{algo::replace_descendants, SyntaxElement, SyntaxNode}; | 29 | use ra_syntax::{algo::SyntaxRewriter, SyntaxNode}; |
30 | use std::{collections::HashMap, sync::Arc}; | 30 | use std::sync::Arc; |
31 | 31 | ||
32 | pub fn expand_eager_macro( | 32 | pub 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 | } |