aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authorEdwin Cheng <[email protected]>2019-11-04 18:09:16 +0000
committerEdwin Cheng <[email protected]>2019-11-04 18:09:16 +0000
commit604bdc6ffeea69dffed6d03f10b2fd4e05d04cda (patch)
treec1bdf4142663cf259c026ae134fd32c254707db5 /crates
parent7e28924012409352bbacbfebf9fac4e4409f09b8 (diff)
Use macro_rules shift to map text ranges
Diffstat (limited to 'crates')
-rw-r--r--crates/ra_hir_expand/src/db.rs13
-rw-r--r--crates/ra_mbe/src/lib.rs4
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs41
-rw-r--r--crates/ra_tt/src/lib.rs19
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
123impl Rule { 127impl 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
13use crate::subtree_source::SubtreeTokenSource; 13use crate::subtree_source::SubtreeTokenSource;
14use crate::ExpandError; 14use crate::ExpandError;
15use 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)]
19pub struct TokenMap { 18pub 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
25static TOKEN_MAP_COUNTER: AtomicU32 = AtomicU32::new(0);
26
27/// Generate an unique token map id for each instance
28fn 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
36impl 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
141impl TokenMap { 122impl 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)]
28pub struct TokenId { 28pub struct TokenId(pub u32);
29 token_id: u32,
30 map_id: u32,
31}
32 29
33impl TokenId { 30impl 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