diff options
-rw-r--r-- | crates/ra_hir_expand/src/lib.rs | 4 | ||||
-rw-r--r-- | crates/ra_mbe/src/syntax_bridge.rs | 41 |
2 files changed, 35 insertions, 10 deletions
diff --git a/crates/ra_hir_expand/src/lib.rs b/crates/ra_hir_expand/src/lib.rs index cb4e1950b..720a29ea5 100644 --- a/crates/ra_hir_expand/src/lib.rs +++ b/crates/ra_hir_expand/src/lib.rs | |||
@@ -227,7 +227,7 @@ impl ExpansionInfo { | |||
227 | let token_id = self.macro_arg.1.token_by_range(range)?; | 227 | let token_id = self.macro_arg.1.token_by_range(range)?; |
228 | let token_id = self.macro_def.0.map_id_down(token_id); | 228 | let token_id = self.macro_def.0.map_id_down(token_id); |
229 | 229 | ||
230 | let range = self.exp_map.range_by_token(token_id)?; | 230 | let range = self.exp_map.range_by_token(token_id)?.range(token.value.kind())?; |
231 | 231 | ||
232 | let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; | 232 | let token = algo::find_covering_element(&self.expanded.value, range).into_token()?; |
233 | 233 | ||
@@ -248,7 +248,7 @@ impl ExpansionInfo { | |||
248 | } | 248 | } |
249 | }; | 249 | }; |
250 | 250 | ||
251 | let range = token_map.range_by_token(token_id)?; | 251 | let range = token_map.range_by_token(token_id)?.range(token.value.kind())?; |
252 | let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) | 252 | let token = algo::find_covering_element(&tt.value, range + tt.value.text_range().start()) |
253 | .into_token()?; | 253 | .into_token()?; |
254 | Some((tt.with_value(token), origin)) | 254 | Some((tt.with_value(token), origin)) |
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs index a85bb058b..44a51b7a5 100644 --- a/crates/ra_mbe/src/syntax_bridge.rs +++ b/crates/ra_mbe/src/syntax_bridge.rs | |||
@@ -12,11 +12,30 @@ use tt::buffer::{Cursor, TokenBuffer}; | |||
12 | use crate::subtree_source::SubtreeTokenSource; | 12 | use crate::subtree_source::SubtreeTokenSource; |
13 | use crate::ExpandError; | 13 | use crate::ExpandError; |
14 | 14 | ||
15 | #[derive(Debug, PartialEq, Eq, Clone, Copy)] | ||
16 | pub enum TokenTextRange { | ||
17 | Token(TextRange), | ||
18 | Delimiter(TextRange, TextRange), | ||
19 | } | ||
20 | |||
21 | impl TokenTextRange { | ||
22 | pub fn range(self, kind: SyntaxKind) -> Option<TextRange> { | ||
23 | match self { | ||
24 | TokenTextRange::Token(it) => Some(it), | ||
25 | TokenTextRange::Delimiter(open, close) => match kind { | ||
26 | T!['{'] | T!['('] | T!['['] => Some(open), | ||
27 | T!['}'] | T![')'] | T![']'] => Some(close), | ||
28 | _ => None, | ||
29 | }, | ||
30 | } | ||
31 | } | ||
32 | } | ||
33 | |||
15 | /// Maps `tt::TokenId` to the relative range of the original token. | 34 | /// Maps `tt::TokenId` to the relative range of the original token. |
16 | #[derive(Debug, PartialEq, Eq, Default)] | 35 | #[derive(Debug, PartialEq, Eq, Default)] |
17 | pub struct TokenMap { | 36 | pub struct TokenMap { |
18 | /// Maps `tt::TokenId` to the *relative* source range. | 37 | /// Maps `tt::TokenId` to the *relative* source range. |
19 | entries: Vec<(tt::TokenId, TextRange)>, | 38 | entries: Vec<(tt::TokenId, TokenTextRange)>, |
20 | } | 39 | } |
21 | 40 | ||
22 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro | 41 | /// Convert the syntax tree (what user has written) to a `TokenTree` (what macro |
@@ -72,26 +91,32 @@ pub fn token_tree_to_syntax_node( | |||
72 | 91 | ||
73 | impl TokenMap { | 92 | impl TokenMap { |
74 | pub fn token_by_range(&self, relative_range: TextRange) -> Option<tt::TokenId> { | 93 | pub fn token_by_range(&self, relative_range: TextRange) -> Option<tt::TokenId> { |
75 | let &(token_id, _) = self.entries.iter().find(|(_, range)| *range == relative_range)?; | 94 | let &(token_id, _) = self.entries.iter().find(|(_, range)| match range { |
95 | TokenTextRange::Token(it) => *it == relative_range, | ||
96 | TokenTextRange::Delimiter(open, close) => { | ||
97 | *open == relative_range || *close == relative_range | ||
98 | } | ||
99 | })?; | ||
76 | Some(token_id) | 100 | Some(token_id) |
77 | } | 101 | } |
78 | 102 | ||
79 | pub fn range_by_token(&self, token_id: tt::TokenId) -> Option<TextRange> { | 103 | pub fn range_by_token(&self, token_id: tt::TokenId) -> Option<TokenTextRange> { |
80 | let &(_, range) = self.entries.iter().find(|(tid, _)| *tid == token_id)?; | 104 | let &(_, range) = self.entries.iter().find(|(tid, _)| *tid == token_id)?; |
81 | Some(range) | 105 | Some(range) |
82 | } | 106 | } |
83 | 107 | ||
84 | fn insert(&mut self, token_id: tt::TokenId, relative_range: TextRange) { | 108 | fn insert(&mut self, token_id: tt::TokenId, relative_range: TextRange) { |
85 | self.entries.push((token_id, relative_range)); | 109 | self.entries.push((token_id, TokenTextRange::Token(relative_range))); |
86 | } | 110 | } |
87 | 111 | ||
88 | fn insert_delim( | 112 | fn insert_delim( |
89 | &mut self, | 113 | &mut self, |
90 | _token_id: tt::TokenId, | 114 | token_id: tt::TokenId, |
91 | _open_relative_range: TextRange, | 115 | open_relative_range: TextRange, |
92 | _close_relative_range: TextRange, | 116 | close_relative_range: TextRange, |
93 | ) { | 117 | ) { |
94 | // FIXME: Add entries for delimiter | 118 | self.entries |
119 | .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); | ||
95 | } | 120 | } |
96 | } | 121 | } |
97 | 122 | ||