aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/macros.rs
diff options
context:
space:
mode:
authorAleksey Kladov <[email protected]>2019-01-02 13:00:01 +0000
committerAleksey Kladov <[email protected]>2019-01-02 13:00:01 +0000
commit35b3fc02e02fa21deb51105d04132d55d4282754 (patch)
treef4ef767d1c24203047693ee771b12ab0354c892f /crates/ra_hir/src/macros.rs
parent4fe0ec5497cdbd7910b0197d254c2b2356fe1874 (diff)
comments
Diffstat (limited to 'crates/ra_hir/src/macros.rs')
-rw-r--r--crates/ra_hir/src/macros.rs43
1 files changed, 31 insertions, 12 deletions
diff --git a/crates/ra_hir/src/macros.rs b/crates/ra_hir/src/macros.rs
index 71646b22d..b7b75e702 100644
--- a/crates/ra_hir/src/macros.rs
+++ b/crates/ra_hir/src/macros.rs
@@ -1,3 +1,12 @@
1/// Machinery for macro expansion.
2///
3/// One of the more complicated things about macros is managing the source code
4/// that is produced after expansion. See `HirFileId` and `MacroCallId` for how
5/// do we do that.
6///
7/// When file-management question is resolved, all that is left is a token tree
8/// to token tree transformation plus hygent. We don't have either of thouse
9/// yet, so all macros are string based at the moment!
1use std::sync::Arc; 10use std::sync::Arc;
2 11
3use ra_db::LocalSyntaxPtr; 12use ra_db::LocalSyntaxPtr;
@@ -16,6 +25,8 @@ pub enum MacroDef {
16} 25}
17 26
18impl MacroDef { 27impl MacroDef {
28 /// Expands macro call, returning the expansion and offset to be used to
29 /// convert ranges between expansion and original source.
19 pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> { 30 pub fn ast_expand(macro_call: ast::MacroCall) -> Option<(TextUnit, MacroExpansion)> {
20 let (def, input) = MacroDef::from_call(macro_call)?; 31 let (def, input) = MacroDef::from_call(macro_call)?;
21 let exp = def.expand(input)?; 32 let exp = def.expand(input)?;
@@ -109,14 +120,20 @@ pub struct MacroInput {
109 120
110#[derive(Debug, Clone, PartialEq, Eq)] 121#[derive(Debug, Clone, PartialEq, Eq)]
111pub struct MacroExpansion { 122pub struct MacroExpansion {
123 /// The result of macro expansion. Should be token tree as well.
112 text: String, 124 text: String,
125 /// Correspondence between ranges in the original source code and ranges in
126 /// the macro.
113 ranges_map: Vec<(TextRange, TextRange)>, 127 ranges_map: Vec<(TextRange, TextRange)>,
128 /// Implementation detail: internally, a macro is expanded to the whole file,
129 /// even if it is an expression. This `ptr` selects the actual expansion from
130 /// the expanded file.
114 ptr: LocalSyntaxPtr, 131 ptr: LocalSyntaxPtr,
115} 132}
116 133
117impl MacroExpansion { 134impl MacroExpansion {
118 //FIXME: does not really make sense, macro expansion is not neccessary a 135 // FIXME: does not really make sense, macro expansion is not neccessary a
119 //whole file. 136 // whole file. See `MacroExpansion::ptr` as well.
120 pub(crate) fn file(&self) -> SourceFileNode { 137 pub(crate) fn file(&self) -> SourceFileNode {
121 SourceFileNode::parse(&self.text) 138 SourceFileNode::parse(&self.text)
122 } 139 }
@@ -124,23 +141,25 @@ impl MacroExpansion {
124 pub fn syntax(&self) -> SyntaxNode { 141 pub fn syntax(&self) -> SyntaxNode {
125 self.ptr.resolve(&self.file()) 142 self.ptr.resolve(&self.file())
126 } 143 }
127 pub fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> { 144 /// Maps range in the source code to the range in the expanded code.
145 pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> {
128 for (s_range, t_range) in self.ranges_map.iter() { 146 for (s_range, t_range) in self.ranges_map.iter() {
129 if tgt_range.is_subrange(&t_range) { 147 if src_range.is_subrange(&s_range) {
130 let tgt_at_zero_range = tgt_range - tgt_range.start(); 148 let src_at_zero_range = src_range - src_range.start();
131 let tgt_range_offset = tgt_range.start() - t_range.start(); 149 let src_range_offset = src_range.start() - s_range.start();
132 let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start(); 150 let src_range = src_at_zero_range + src_range_offset + t_range.start();
133 return Some(src_range); 151 return Some(src_range);
134 } 152 }
135 } 153 }
136 None 154 None
137 } 155 }
138 pub fn map_range_forward(&self, src_range: TextRange) -> Option<TextRange> { 156 /// Maps range in the expanded code to the range in the source code.
157 pub fn map_range_back(&self, tgt_range: TextRange) -> Option<TextRange> {
139 for (s_range, t_range) in self.ranges_map.iter() { 158 for (s_range, t_range) in self.ranges_map.iter() {
140 if src_range.is_subrange(&s_range) { 159 if tgt_range.is_subrange(&t_range) {
141 let src_at_zero_range = src_range - src_range.start(); 160 let tgt_at_zero_range = tgt_range - tgt_range.start();
142 let src_range_offset = src_range.start() - s_range.start(); 161 let tgt_range_offset = tgt_range.start() - t_range.start();
143 let src_range = src_at_zero_range + src_range_offset + t_range.start(); 162 let src_range = tgt_at_zero_range + tgt_range_offset + s_range.start();
144 return Some(src_range); 163 return Some(src_range);
145 } 164 }
146 } 165 }