diff options
author | Aleksey Kladov <[email protected]> | 2019-01-02 13:00:01 +0000 |
---|---|---|
committer | Aleksey Kladov <[email protected]> | 2019-01-02 13:00:01 +0000 |
commit | 35b3fc02e02fa21deb51105d04132d55d4282754 (patch) | |
tree | f4ef767d1c24203047693ee771b12ab0354c892f | |
parent | 4fe0ec5497cdbd7910b0197d254c2b2356fe1874 (diff) |
comments
-rw-r--r-- | crates/ra_hir/src/ids.rs | 3 | ||||
-rw-r--r-- | crates/ra_hir/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/ra_hir/src/macros.rs | 43 |
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::{ | |||
29 | pub struct HirFileId(HirFileIdRepr); | 29 | pub struct HirFileId(HirFileIdRepr); |
30 | 30 | ||
31 | impl HirFileId { | 31 | impl 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; | |||
25 | mod ids; | 25 | mod ids; |
26 | mod macros; | 26 | mod macros; |
27 | mod name; | 27 | mod name; |
28 | // can't use `crate` or `r#crate` here :( | ||
28 | mod krate; | 29 | mod krate; |
29 | mod module; | 30 | mod module; |
30 | mod function; | 31 | mod 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! | ||
1 | use std::sync::Arc; | 10 | use std::sync::Arc; |
2 | 11 | ||
3 | use ra_db::LocalSyntaxPtr; | 12 | use ra_db::LocalSyntaxPtr; |
@@ -16,6 +25,8 @@ pub enum MacroDef { | |||
16 | } | 25 | } |
17 | 26 | ||
18 | impl MacroDef { | 27 | impl 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)] |
111 | pub struct MacroExpansion { | 122 | pub 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 | ||
117 | impl MacroExpansion { | 134 | impl 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 | } |