diff options
author | Edwin Cheng <[email protected]> | 2019-11-04 18:09:16 +0000 |
---|---|---|
committer | Edwin Cheng <[email protected]> | 2019-11-04 18:09:16 +0000 |
commit | 604bdc6ffeea69dffed6d03f10b2fd4e05d04cda (patch) | |
tree | c1bdf4142663cf259c026ae134fd32c254707db5 /crates | |
parent | 7e28924012409352bbacbfebf9fac4e4409f09b8 (diff) |
Use macro_rules shift to map text ranges
Diffstat (limited to 'crates')
-rw-r--r-- | crates/ra_hir_expand/src/db.rs | 13 | ||||
-rw-r--r-- | crates/ra_mbe/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 41 | ||||
-rw-r--r-- | crates/ra_tt/src/lib.rs | 19 |
4 files changed, 26 insertions, 51 deletions
diff --git a/crates/ra_hir_expand/src/db.rs b/crates/ra_hir_expand/src/db.rs index 8369c2b40..72c728c93 100644 --- a/crates/ra_hir_expand/src/db.rs +++ b/crates/ra_hir_expand/src/db.rs | |||
@@ -151,10 +151,15 @@ pub(crate) fn parse_macro_with_info( | |||
151 | let arg_start = arg_tt.map(|t| t.syntax().text_range().start()); | 151 | let arg_start = arg_tt.map(|t| t.syntax().text_range().start()); |
152 | let def_start = def_tt.map(|t| t.syntax().text_range().start()); | 152 | let def_start = def_tt.map(|t| t.syntax().text_range().start()); |
153 | 153 | ||
154 | let arg_map = | 154 | let macro_rules = db.macro_def(loc.def).ok_or("Fail to find macro definition").ok()?.0; |
155 | arg_start.map(|start| exp_map.ranges(&expand_info.arg_map, start)).unwrap_or_default(); | 155 | let shift = macro_rules.shift(); |
156 | let def_map = | 156 | |
157 | def_start.map(|start| exp_map.ranges(&expand_info.def_map, start)).unwrap_or_default(); | 157 | let arg_map = arg_start |
158 | .map(|start| exp_map.map_ranges(&expand_info.arg_map, start, shift)) | ||
159 | .unwrap_or_default(); | ||
160 | let def_map = def_start | ||
161 | .map(|start| exp_map.map_ranges(&expand_info.def_map, start, 0)) | ||
162 | .unwrap_or_default(); | ||
158 | 163 | ||
159 | let info = ExpansionInfo { arg_map, def_map }; | 164 | let info = ExpansionInfo { arg_map, def_map }; |
160 | 165 | ||
diff --git a/crates/ra_mbe/src/lib.rs b/crates/ra_mbe/src/lib.rs index 2926b29fd..a0f1a6881 100644 --- a/crates/ra_mbe/src/lib.rs +++ b/crates/ra_mbe/src/lib.rs | |||
@@ -118,6 +118,10 @@ impl MacroRules { | |||
118 | shift_subtree(&mut tt, self.shift); | 118 | shift_subtree(&mut tt, self.shift); |
119 | mbe_expander::expand(self, &tt) | 119 | mbe_expander::expand(self, &tt) |
120 | } | 120 | } |
121 | |||
122 | pub fn shift(&self) -> u32 { | ||
123 | self.shift | ||
124 | } | ||
121 | } | 125 | } |
122 | 126 | ||
123 | impl Rule { | 127 | impl Rule { |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index 2f21ad6e0..0c499cd03 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -12,31 +12,12 @@ use tt::buffer::{Cursor, TokenBuffer}; | |||
12 | 12 | ||
13 | use crate::subtree_source::SubtreeTokenSource; | 13 | use crate::subtree_source::SubtreeTokenSource; |
14 | use crate::ExpandError; | 14 | use crate::ExpandError; |
15 | use std::sync::atomic::{AtomicU32, Ordering}; | ||
16 | 15 | ||
17 | /// Maps `tt::TokenId` to the relative range of the original token. | 16 | /// Maps `tt::TokenId` to the relative range of the original token. |
18 | #[derive(Debug, PartialEq, Eq)] | 17 | #[derive(Debug, PartialEq, Eq, Default)] |
19 | pub struct TokenMap { | 18 | pub struct TokenMap { |
20 | /// Maps `tt::TokenId` to the *relative* source range. | 19 | /// Maps `tt::TokenId` to the *relative* source range. |
21 | tokens: Vec<TextRange>, | 20 | tokens: Vec<TextRange>, |
22 | map_id: u32, | ||
23 | } | ||
24 | |||
25 | static TOKEN_MAP_COUNTER: AtomicU32 = AtomicU32::new(0); | ||
26 | |||
27 | /// Generate an unique token map id for each instance | ||
28 | fn make_uniq_token_map_id() -> u32 { | ||
29 | let res = TOKEN_MAP_COUNTER.fetch_add(1, Ordering::SeqCst); | ||
30 | if res == std::u32::MAX { | ||
31 | panic!("TOKEN_MAP_COUNTER is overflowed"); | ||
32 | } | ||
33 | res | ||
34 | } | ||
35 | |||
36 | impl std::default::Default for TokenMap { | ||
37 | fn default() -> TokenMap { | ||
38 | TokenMap { tokens: Default::default(), map_id: make_uniq_token_map_id() } | ||
39 | } | ||
40 | } | 21 | } |
41 | 22 | ||
42 | /// Maps relative range of the expanded syntax node to `tt::TokenId` | 23 | /// Maps relative range of the expanded syntax node to `tt::TokenId` |
@@ -140,17 +121,14 @@ pub fn token_tree_to_items( | |||
140 | 121 | ||
141 | impl TokenMap { | 122 | impl TokenMap { |
142 | pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> { | 123 | pub fn relative_range_of(&self, tt: tt::TokenId) -> Option<TextRange> { |
143 | if self.map_id != tt.map_id() { | 124 | let idx = tt.0 as usize; |
144 | return None; | ||
145 | } | ||
146 | let idx = tt.token_id() as usize; | ||
147 | self.tokens.get(idx).copied() | 125 | self.tokens.get(idx).copied() |
148 | } | 126 | } |
149 | 127 | ||
150 | fn alloc(&mut self, relative_range: TextRange) -> tt::TokenId { | 128 | fn alloc(&mut self, relative_range: TextRange) -> tt::TokenId { |
151 | let id = self.tokens.len(); | 129 | let id = self.tokens.len(); |
152 | self.tokens.push(relative_range); | 130 | self.tokens.push(relative_range); |
153 | tt::TokenId::new(id as u32, self.map_id) | 131 | tt::TokenId(id as u32) |
154 | } | 132 | } |
155 | } | 133 | } |
156 | 134 | ||
@@ -159,14 +137,17 @@ impl ExpandedRangeMap { | |||
159 | self.ranges.push((relative_range, token_id.clone())) | 137 | self.ranges.push((relative_range, token_id.clone())) |
160 | } | 138 | } |
161 | 139 | ||
162 | pub fn ranges(&self, to: &TokenMap, start: TextUnit) -> Vec<(TextRange, TextRange)> { | 140 | pub fn map_ranges( |
141 | &self, | ||
142 | to: &TokenMap, | ||
143 | start: TextUnit, | ||
144 | shift: u32, | ||
145 | ) -> Vec<(TextRange, TextRange)> { | ||
163 | self.ranges | 146 | self.ranges |
164 | .iter() | 147 | .iter() |
148 | .filter_map(|(r, tid)| if shift <= tid.0 { Some((r, tid.0 - shift)) } else { None }) | ||
165 | .filter_map(|(r, tid)| { | 149 | .filter_map(|(r, tid)| { |
166 | if to.map_id != tid.map_id() { | 150 | if let Some(to_range) = to.relative_range_of(tt::TokenId(tid)) { |
167 | return None; | ||
168 | } | ||
169 | if let Some(to_range) = to.relative_range_of(*tid) { | ||
170 | Some((*r, TextRange::from_to(to_range.start() + start, to_range.end() + start))) | 151 | Some((*r, TextRange::from_to(to_range.start() + start, to_range.end() + start))) |
171 | } else { | 152 | } else { |
172 | None | 153 | None |
diff --git a/crates/ra_tt/src/lib.rs b/crates/ra_tt/src/lib.rs index 1449618f3..20c251ff4 100644 --- a/crates/ra_tt/src/lib.rs +++ b/crates/ra_tt/src/lib.rs | |||
@@ -25,26 +25,11 @@ use smol_str::SmolStr; | |||
25 | /// source token and making sure that identities are preserved during macro | 25 | /// source token and making sure that identities are preserved during macro |
26 | /// expansion. | 26 | /// expansion. |
27 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] | 27 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] |
28 | pub struct TokenId { | 28 | pub struct TokenId(pub u32); |
29 | token_id: u32, | ||
30 | map_id: u32, | ||
31 | } | ||
32 | 29 | ||
33 | impl TokenId { | 30 | impl TokenId { |
34 | pub fn new(token_id: u32, map_id: u32) -> TokenId { | ||
35 | TokenId { token_id, map_id } | ||
36 | } | ||
37 | |||
38 | pub const fn unspecified() -> TokenId { | 31 | pub const fn unspecified() -> TokenId { |
39 | TokenId { token_id: !0, map_id: !0 } | 32 | TokenId(!0) |
40 | } | ||
41 | |||
42 | pub fn token_id(&self) -> u32 { | ||
43 | self.token_id | ||
44 | } | ||
45 | |||
46 | pub fn map_id(&self) -> u32 { | ||
47 | self.map_id | ||
48 | } | 33 | } |
49 | } | 34 | } |
50 | 35 | ||