aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/ra_hir/src/ids.rs3
-rw-r--r--crates/ra_hir/src/lib.rs1
-rw-r--r--crates/ra_hir/src/macros.rs43
3 files changed, 35 insertions, 12 deletions
diff --git a/crates/ra_hir/src/ids.rs b/crates/ra_hir/src/ids.rs
index 3504317ed..6d59ef659 100644
--- a/crates/ra_hir/src/ids.rs
+++ b/crates/ra_hir/src/ids.rs
@@ -29,6 +29,8 @@ use crate::{
29pub struct HirFileId(HirFileIdRepr); 29pub struct HirFileId(HirFileIdRepr);
30 30
31impl HirFileId { 31impl HirFileId {
32 /// For macro-expansion files, returns the file original source file the
33 /// expansionoriginated from.
32 pub(crate) fn original_file_id(self, db: &impl HirDatabase) -> FileId { 34 pub(crate) fn original_file_id(self, db: &impl HirDatabase) -> FileId {
33 match self.0 { 35 match self.0 {
34 HirFileIdRepr::File(file_id) => file_id, 36 HirFileIdRepr::File(file_id) => file_id,
@@ -45,6 +47,7 @@ impl HirFileId {
45 HirFileIdRepr::Macro(_r) => panic!("macro generated file: {:?}", self), 47 HirFileIdRepr::Macro(_r) => panic!("macro generated file: {:?}", self),
46 } 48 }
47 } 49 }
50
48 pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode { 51 pub(crate) fn hir_source_file(db: &impl HirDatabase, file_id: HirFileId) -> SourceFileNode {
49 match file_id.0 { 52 match file_id.0 {
50 HirFileIdRepr::File(file_id) => db.source_file(file_id), 53 HirFileIdRepr::File(file_id) => db.source_file(file_id),
diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs
index 018ead9fb..8ee52a466 100644
--- a/crates/ra_hir/src/lib.rs
+++ b/crates/ra_hir/src/lib.rs
@@ -25,6 +25,7 @@ pub mod source_binder;
25mod ids; 25mod ids;
26mod macros; 26mod macros;
27mod name; 27mod name;
28// can't use `crate` or `r#crate` here :(
28mod krate; 29mod krate;
29mod module; 30mod module;
30mod function; 31mod function;
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 }