aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/ids.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/ids.rs')
-rw-r--r--crates/ra_hir/src/ids.rs42
1 files changed, 33 insertions, 9 deletions
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 2a1ed9b81..c7849c995 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -63,11 +63,15 @@ impl HirFileId {
63 match file_id.0 { 63 match file_id.0 {
64 HirFileIdRepr::File(file_id) => db.parse(file_id), 64 HirFileIdRepr::File(file_id) => db.parse(file_id),
65 HirFileIdRepr::Macro(macro_call_id) => { 65 HirFileIdRepr::Macro(macro_call_id) => {
66 parse_macro(db, macro_call_id).unwrap_or_else(|| { 66 parse_macro(db, macro_call_id).unwrap_or_else(|err| {
67 // Note: 67 // Note:
68 // The final goal we would like to make all parse_macro success, 68 // The final goal we would like to make all parse_macro success,
69 // such that the following log will not call anyway. 69 // such that the following log will not call anyway.
70 log::warn!("fail on macro_parse: {}", macro_call_id.debug_dump(db)); 70 log::warn!(
71 "fail on macro_parse: (reason: {}) {}",
72 err,
73 macro_call_id.debug_dump(db)
74 );
71 75
72 // returning an empty string looks fishy... 76 // returning an empty string looks fishy...
73 SourceFile::parse("") 77 SourceFile::parse("")
@@ -77,14 +81,27 @@ impl HirFileId {
77 } 81 }
78} 82}
79 83
80fn parse_macro(db: &impl DefDatabase, macro_call_id: MacroCallId) -> Option<TreeArc<SourceFile>> { 84fn parse_macro(
85 db: &impl DefDatabase,
86 macro_call_id: MacroCallId,
87) -> Result<TreeArc<SourceFile>, String> {
81 let loc = macro_call_id.loc(db); 88 let loc = macro_call_id.loc(db);
82 let macro_call = loc.ast_id.to_node(db); 89 let macro_call = loc.ast_id.to_node(db);
83 let (macro_arg, _) = macro_call.token_tree().and_then(mbe::ast_to_token_tree)?; 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
95 let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition")?;
96 let tt = macro_rules.expand(&macro_arg).map_err(|err| format!("{:?}", err))?;
97
98 // Set a hard limit for the expanded tt
99 let count = tt.count();
100 if count > 65536 {
101 return Err(format!("Total tokens count exceed limit : count = {}", count));
102 }
84 103
85 let macro_rules = db.macro_def(loc.def)?; 104 Ok(mbe::token_tree_to_ast_item_list(&tt))
86 let tt = macro_rules.expand(&macro_arg).ok()?;
87 Some(mbe::token_tree_to_ast_item_list(&tt))
88} 105}
89 106
90#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 107#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -311,11 +328,18 @@ impl MacroCallId {
311 pub fn debug_dump(&self, db: &impl DefDatabase) -> String { 328 pub fn debug_dump(&self, db: &impl DefDatabase) -> String {
312 let loc = self.clone().loc(db); 329 let loc = self.clone().loc(db);
313 let node = loc.ast_id.to_node(db); 330 let node = loc.ast_id.to_node(db);
314 let syntax_str = node.syntax().to_string(); 331 let syntax_str = node.syntax().text().chunks().collect::<Vec<_>>().join(" ");
315 332
316 // dump the file name 333 // dump the file name
317 let file_id: HirFileId = self.clone().into(); 334 let file_id: HirFileId = self.clone().into();
318 let original = file_id.original_file(db); 335 let original = file_id.original_file(db);
319 format!("macro call [file: {:#?}] : {}", db.file_relative_path(original), syntax_str) 336 let macro_rules = db.macro_def(loc.def);
337
338 format!(
339 "macro call [file: {:#?}] : {}\nhas rules: {}",
340 db.file_relative_path(original),
341 syntax_str,
342 macro_rules.is_some()
343 )
320 } 344 }
321} 345}