aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir_expand/src/lib.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir_expand/src/lib.rs')
-rw-r--r--crates/ra_hir_expand/src/lib.rs40
1 files changed, 24 insertions, 16 deletions
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs
index 63ba17158..1a1d6bdd4 100644
--- a/crates/ra_hir_expand/src/lib.rs
+++ b/crates/ra_hir_expand/src/lib.rs
@@ -20,7 +20,6 @@ use ra_syntax::{
20}; 20};
21 21
22use crate::ast_id_map::FileAstId; 22use crate::ast_id_map::FileAstId;
23use std::sync::Arc;
24 23
25/// Input to the analyzer is a set of files, where each file is identified by 24/// Input to the analyzer is a set of files, where each file is identified by
26/// `FileId` and contains source code. However, another source of source code in 25/// `FileId` and contains source code. However, another source of source code in
@@ -69,19 +68,29 @@ impl HirFileId {
69 } 68 }
70 69
71 /// Return expansion information if it is a macro-expansion file 70 /// Return expansion information if it is a macro-expansion file
72 pub fn parent_expansion( 71 pub fn parent_expansion(self, db: &dyn db::AstDatabase) -> Option<ExpansionInfo> {
73 self,
74 db: &dyn db::AstDatabase,
75 ) -> Option<((HirFileId, HirFileId), Arc<ExpansionInfo>)> {
76 match self.0 { 72 match self.0 {
77 HirFileIdRepr::FileId(_) => None, 73 HirFileIdRepr::FileId(_) => None,
78 HirFileIdRepr::MacroFile(macro_file) => { 74 HirFileIdRepr::MacroFile(macro_file) => {
79 let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id); 75 let loc: MacroCallLoc = db.lookup_intern_macro(macro_file.macro_call_id);
80 76
81 let def_file = loc.def.ast_id.file_id; 77 let arg_range = loc.ast_id.to_node(db).token_tree()?.syntax().text_range();
78 let def_range = loc.def.ast_id.to_node(db).token_tree()?.syntax().text_range();
79
80 let macro_def = db.macro_def(loc.def)?;
81 let shift = macro_def.0.shift();
82 let rev_map = db.parse_macro(macro_file)?.1;
83
84 let arg_token_map = db.macro_arg(macro_file.macro_call_id)?.1;
85 let def_token_map = macro_def.1;
86
87 let arg_map = rev_map.map_ranges(&arg_token_map, arg_range, shift);
88 let def_map = rev_map.map_ranges(&def_token_map, def_range, 0);
89
82 let arg_file = loc.ast_id.file_id; 90 let arg_file = loc.ast_id.file_id;
91 let def_file = loc.def.ast_id.file_id;
83 92
84 db.macro_expansion_info(macro_file).map(|ex| ((arg_file, def_file), ex)) 93 Some(ExpansionInfo { arg_file, def_file, arg_map, def_map })
85 } 94 }
86 } 95 }
87 } 96 }
@@ -134,25 +143,24 @@ impl MacroCallId {
134#[derive(Debug, Clone, PartialEq, Eq)] 143#[derive(Debug, Clone, PartialEq, Eq)]
135/// ExpansionInfo mainly describes how to map text range between src and expanded macro 144/// ExpansionInfo mainly describes how to map text range between src and expanded macro
136pub struct ExpansionInfo { 145pub struct ExpansionInfo {
137 pub arg_map: Vec<(TextRange, TextRange)>, 146 pub(crate) arg_file: HirFileId,
138 pub def_map: Vec<(TextRange, TextRange)>, 147 pub(crate) def_file: HirFileId,
148
149 pub(crate) arg_map: Vec<(TextRange, TextRange)>,
150 pub(crate) def_map: Vec<(TextRange, TextRange)>,
139} 151}
140 152
141impl ExpansionInfo { 153impl ExpansionInfo {
142 pub fn find_range( 154 pub fn find_range(&self, from: TextRange) -> Option<(HirFileId, TextRange)> {
143 &self,
144 from: TextRange,
145 (arg_file_id, def_file_id): (HirFileId, HirFileId),
146 ) -> Option<(HirFileId, TextRange)> {
147 for (src, dest) in &self.arg_map { 155 for (src, dest) in &self.arg_map {
148 if src.is_subrange(&from) { 156 if src.is_subrange(&from) {
149 return Some((arg_file_id, *dest)); 157 return Some((self.arg_file, *dest));
150 } 158 }
151 } 159 }
152 160
153 for (src, dest) in &self.def_map { 161 for (src, dest) in &self.def_map {
154 if src.is_subrange(&from) { 162 if src.is_subrange(&from) {
155 return Some((def_file_id, *dest)); 163 return Some((self.def_file, *dest));
156 } 164 }
157 } 165 }
158 166