aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src')
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs36
-rw-r--r--crates/ra_mbe/src/tests.rs99
2 files changed, 108 insertions, 27 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index 8e8ae2b29..9fb5cb058 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -137,21 +137,23 @@ impl TokenMap {
137 token_id: tt::TokenId, 137 token_id: tt::TokenId,
138 open_relative_range: TextRange, 138 open_relative_range: TextRange,
139 close_relative_range: TextRange, 139 close_relative_range: TextRange,
140 ) { 140 ) -> usize {
141 let res = self.entries.len();
141 self.entries 142 self.entries
142 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range))); 143 .push((token_id, TokenTextRange::Delimiter(open_relative_range, close_relative_range)));
144 res
143 } 145 }
144 146
145 fn update_close_delim(&mut self, token_id: tt::TokenId, close_relative_range: TextRange) { 147 fn update_close_delim(&mut self, idx: usize, close_relative_range: TextRange) {
146 if let Some(entry) = self.entries.iter_mut().find(|(tid, _)| *tid == token_id) { 148 let (_, token_text_range) = &mut self.entries[idx];
147 if let TokenTextRange::Delimiter(dim, _) = entry.1 { 149 if let TokenTextRange::Delimiter(dim, _) = token_text_range {
148 entry.1 = TokenTextRange::Delimiter(dim, close_relative_range); 150 *token_text_range = TokenTextRange::Delimiter(*dim, close_relative_range);
149 }
150 } 151 }
151 } 152 }
152 153
153 fn remove_delim(&mut self, token_id: tt::TokenId) { 154 fn remove_delim(&mut self, idx: usize) {
154 self.entries.retain(|(tid, _)| *tid != token_id); 155 // FIXME: This could be accidently quadratic
156 self.entries.remove(idx);
155 } 157 }
156} 158}
157 159
@@ -238,24 +240,24 @@ impl TokenIdAlloc {
238 token_id 240 token_id
239 } 241 }
240 242
241 fn open_delim(&mut self, open_abs_range: TextRange) -> tt::TokenId { 243 fn open_delim(&mut self, open_abs_range: TextRange) -> (tt::TokenId, usize) {
242 let token_id = tt::TokenId(self.next_id); 244 let token_id = tt::TokenId(self.next_id);
243 self.next_id += 1; 245 self.next_id += 1;
244 self.map.insert_delim( 246 let idx = self.map.insert_delim(
245 token_id, 247 token_id,
246 open_abs_range - self.global_offset, 248 open_abs_range - self.global_offset,
247 open_abs_range - self.global_offset, 249 open_abs_range - self.global_offset,
248 ); 250 );
249 token_id 251 (token_id, idx)
250 } 252 }
251 253
252 fn close_delim(&mut self, id: tt::TokenId, close_abs_range: Option<TextRange>) { 254 fn close_delim(&mut self, idx: usize, close_abs_range: Option<TextRange>) {
253 match close_abs_range { 255 match close_abs_range {
254 None => { 256 None => {
255 self.map.remove_delim(id); 257 self.map.remove_delim(idx);
256 } 258 }
257 Some(close) => { 259 Some(close) => {
258 self.map.update_close_delim(id, close - self.global_offset); 260 self.map.update_close_delim(idx, close - self.global_offset);
259 } 261 }
260 } 262 }
261 } 263 }
@@ -322,7 +324,7 @@ trait TokenConvertor {
322 324
323 if let Some((kind, closed)) = delim { 325 if let Some((kind, closed)) = delim {
324 let mut subtree = tt::Subtree::default(); 326 let mut subtree = tt::Subtree::default();
325 let id = self.id_alloc().open_delim(range); 327 let (id, idx) = self.id_alloc().open_delim(range);
326 subtree.delimiter = Some(tt::Delimiter { kind, id }); 328 subtree.delimiter = Some(tt::Delimiter { kind, id });
327 329
328 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) { 330 while self.peek().map(|it| it.kind() != closed).unwrap_or(false) {
@@ -331,7 +333,7 @@ trait TokenConvertor {
331 let last_range = match self.bump() { 333 let last_range = match self.bump() {
332 None => { 334 None => {
333 // For error resilience, we insert an char punct for the opening delim here 335 // For error resilience, we insert an char punct for the opening delim here
334 self.id_alloc().close_delim(id, None); 336 self.id_alloc().close_delim(idx, None);
335 let leaf: tt::Leaf = tt::Punct { 337 let leaf: tt::Leaf = tt::Punct {
336 id: self.id_alloc().alloc(range), 338 id: self.id_alloc().alloc(range),
337 char: token.to_char().unwrap(), 339 char: token.to_char().unwrap(),
@@ -344,7 +346,7 @@ trait TokenConvertor {
344 } 346 }
345 Some(it) => it.1, 347 Some(it) => it.1,
346 }; 348 };
347 self.id_alloc().close_delim(id, Some(last_range)); 349 self.id_alloc().close_delim(idx, Some(last_range));
348 subtree.into() 350 subtree.into()
349 } else { 351 } else {
350 let spacing = match self.peek() { 352 let spacing = match self.peek() {
diff --git a/crates/ra_mbe/src/tests.rs b/crates/ra_mbe/src/tests.rs
index 254318e23..5d1274d21 100644
--- a/crates/ra_mbe/src/tests.rs
+++ b/crates/ra_mbe/src/tests.rs
@@ -142,6 +142,79 @@ macro_rules! impl_froms {
142} 142}
143 143
144#[test] 144#[test]
145fn test_convert_tt2() {
146 parse_macro(
147 r#"
148macro_rules! impl_froms {
149 ($e:ident: $($v:ident),*) => {
150 $(
151 impl From<$v> for $e {
152 fn from(it: $v) -> $e {
153 $e::$v(it)
154 }
155 }
156 )*
157 }
158}
159"#,
160 )
161 .assert_expand(
162 "impl_froms!(TokenTree: Leaf, Subtree);",
163 r#"
164SUBTREE $
165 IDENT impl 20
166 IDENT From 21
167 PUNCH < [joint] 22
168 IDENT Leaf 53
169 PUNCH > [alone] 25
170 IDENT for 26
171 IDENT TokenTree 51
172 SUBTREE {} 29
173 IDENT fn 30
174 IDENT from 31
175 SUBTREE () 32
176 IDENT it 33
177 PUNCH : [alone] 34
178 IDENT Leaf 53
179 PUNCH - [joint] 37
180 PUNCH > [alone] 38
181 IDENT TokenTree 51
182 SUBTREE {} 41
183 IDENT TokenTree 51
184 PUNCH : [joint] 44
185 PUNCH : [joint] 45
186 IDENT Leaf 53
187 SUBTREE () 48
188 IDENT it 49
189 IDENT impl 20
190 IDENT From 21
191 PUNCH < [joint] 22
192 IDENT Subtree 55
193 PUNCH > [alone] 25
194 IDENT for 26
195 IDENT TokenTree 51
196 SUBTREE {} 29
197 IDENT fn 30
198 IDENT from 31
199 SUBTREE () 32
200 IDENT it 33
201 PUNCH : [alone] 34
202 IDENT Subtree 55
203 PUNCH - [joint] 37
204 PUNCH > [alone] 38
205 IDENT TokenTree 51
206 SUBTREE {} 41
207 IDENT TokenTree 51
208 PUNCH : [joint] 44
209 PUNCH : [joint] 45
210 IDENT Subtree 55
211 SUBTREE () 48
212 IDENT it 49
213"#,
214 );
215}
216
217#[test]
145fn test_expr_order() { 218fn test_expr_order() {
146 let expanded = parse_macro( 219 let expanded = parse_macro(
147 r#" 220 r#"
@@ -179,7 +252,7 @@ fn test_expr_order() {
179 STAR@[11; 12) "*" 252 STAR@[11; 12) "*"
180 LITERAL@[12; 13) 253 LITERAL@[12; 13)
181 INT_NUMBER@[12; 13) "2" 254 INT_NUMBER@[12; 13) "2"
182 SEMI@[13; 14) ";" 255 SEMICOLON@[13; 14) ";"
183 R_CURLY@[14; 15) "}""#, 256 R_CURLY@[14; 15) "}""#,
184 ); 257 );
185} 258}
@@ -532,7 +605,7 @@ fn test_tt_to_stmts() {
532 EQ@[4; 5) "=" 605 EQ@[4; 5) "="
533 LITERAL@[5; 6) 606 LITERAL@[5; 6)
534 INT_NUMBER@[5; 6) "0" 607 INT_NUMBER@[5; 6) "0"
535 SEMI@[6; 7) ";" 608 SEMICOLON@[6; 7) ";"
536 EXPR_STMT@[7; 14) 609 EXPR_STMT@[7; 14)
537 BIN_EXPR@[7; 13) 610 BIN_EXPR@[7; 13)
538 PATH_EXPR@[7; 8) 611 PATH_EXPR@[7; 8)
@@ -547,7 +620,7 @@ fn test_tt_to_stmts() {
547 PLUS@[11; 12) "+" 620 PLUS@[11; 12) "+"
548 LITERAL@[12; 13) 621 LITERAL@[12; 13)
549 INT_NUMBER@[12; 13) "1" 622 INT_NUMBER@[12; 13) "1"
550 SEMI@[13; 14) ";" 623 SEMICOLON@[13; 14) ";"
551 EXPR_STMT@[14; 15) 624 EXPR_STMT@[14; 15)
552 PATH_EXPR@[14; 15) 625 PATH_EXPR@[14; 15)
553 PATH@[14; 15) 626 PATH@[14; 15)
@@ -880,7 +953,7 @@ fn test_tt_composite2() {
880 PATH_SEGMENT@[0; 3) 953 PATH_SEGMENT@[0; 3)
881 NAME_REF@[0; 3) 954 NAME_REF@[0; 3)
882 IDENT@[0; 3) "abs" 955 IDENT@[0; 3) "abs"
883 EXCL@[3; 4) "!" 956 BANG@[3; 4) "!"
884 TOKEN_TREE@[4; 10) 957 TOKEN_TREE@[4; 10)
885 L_PAREN@[4; 5) "(" 958 L_PAREN@[4; 5) "("
886 EQ@[5; 6) "=" 959 EQ@[5; 6) "="
@@ -1000,14 +1073,14 @@ fn test_vec() {
1000 PATH_SEGMENT@[9; 12) 1073 PATH_SEGMENT@[9; 12)
1001 NAME_REF@[9; 12) 1074 NAME_REF@[9; 12)
1002 IDENT@[9; 12) "Vec" 1075 IDENT@[9; 12) "Vec"
1003 COLONCOLON@[12; 14) "::" 1076 COLON2@[12; 14) "::"
1004 PATH_SEGMENT@[14; 17) 1077 PATH_SEGMENT@[14; 17)
1005 NAME_REF@[14; 17) 1078 NAME_REF@[14; 17)
1006 IDENT@[14; 17) "new" 1079 IDENT@[14; 17) "new"
1007 ARG_LIST@[17; 19) 1080 ARG_LIST@[17; 19)
1008 L_PAREN@[17; 18) "(" 1081 L_PAREN@[17; 18) "("
1009 R_PAREN@[18; 19) ")" 1082 R_PAREN@[18; 19) ")"
1010 SEMI@[19; 20) ";" 1083 SEMICOLON@[19; 20) ";"
1011 EXPR_STMT@[20; 33) 1084 EXPR_STMT@[20; 33)
1012 METHOD_CALL_EXPR@[20; 32) 1085 METHOD_CALL_EXPR@[20; 32)
1013 PATH_EXPR@[20; 21) 1086 PATH_EXPR@[20; 21)
@@ -1023,7 +1096,7 @@ fn test_vec() {
1023 LITERAL@[27; 31) 1096 LITERAL@[27; 31)
1024 INT_NUMBER@[27; 31) "1u32" 1097 INT_NUMBER@[27; 31) "1u32"
1025 R_PAREN@[31; 32) ")" 1098 R_PAREN@[31; 32) ")"
1026 SEMI@[32; 33) ";" 1099 SEMICOLON@[32; 33) ";"
1027 EXPR_STMT@[33; 43) 1100 EXPR_STMT@[33; 43)
1028 METHOD_CALL_EXPR@[33; 42) 1101 METHOD_CALL_EXPR@[33; 42)
1029 PATH_EXPR@[33; 34) 1102 PATH_EXPR@[33; 34)
@@ -1039,7 +1112,7 @@ fn test_vec() {
1039 LITERAL@[40; 41) 1112 LITERAL@[40; 41)
1040 INT_NUMBER@[40; 41) "2" 1113 INT_NUMBER@[40; 41) "2"
1041 R_PAREN@[41; 42) ")" 1114 R_PAREN@[41; 42) ")"
1042 SEMI@[42; 43) ";" 1115 SEMICOLON@[42; 43) ";"
1043 PATH_EXPR@[43; 44) 1116 PATH_EXPR@[43; 44)
1044 PATH@[43; 44) 1117 PATH@[43; 44)
1045 PATH_SEGMENT@[43; 44) 1118 PATH_SEGMENT@[43; 44)
@@ -1479,6 +1552,12 @@ impl MacroFixture {
1479 assert_eq!(expansion.to_string(), expected); 1552 assert_eq!(expansion.to_string(), expected);
1480 } 1553 }
1481 1554
1555 fn assert_expand(&self, invocation: &str, expected: &str) {
1556 let expansion = self.expand_tt(invocation);
1557 let actual = format!("{:?}", expansion);
1558 test_utils::assert_eq_text!(&actual.trim(), &expected.trim());
1559 }
1560
1482 fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture { 1561 fn assert_expand_items(&self, invocation: &str, expected: &str) -> &MacroFixture {
1483 self.assert_expansion(FragmentKind::Items, invocation, expected); 1562 self.assert_expansion(FragmentKind::Items, invocation, expected);
1484 self 1563 self
@@ -1681,7 +1760,7 @@ fn test_no_space_after_semi_colon() {
1681 MOD_KW@[21; 24) "mod" 1760 MOD_KW@[21; 24) "mod"
1682 NAME@[24; 25) 1761 NAME@[24; 25)
1683 IDENT@[24; 25) "m" 1762 IDENT@[24; 25) "m"
1684 SEMI@[25; 26) ";" 1763 SEMICOLON@[25; 26) ";"
1685 MODULE@[26; 52) 1764 MODULE@[26; 52)
1686 ATTR@[26; 47) 1765 ATTR@[26; 47)
1687 POUND@[26; 27) "#" 1766 POUND@[26; 27) "#"
@@ -1700,7 +1779,7 @@ fn test_no_space_after_semi_colon() {
1700 MOD_KW@[47; 50) "mod" 1779 MOD_KW@[47; 50) "mod"
1701 NAME@[50; 51) 1780 NAME@[50; 51)
1702 IDENT@[50; 51) "f" 1781 IDENT@[50; 51) "f"
1703 SEMI@[51; 52) ";""###, 1782 SEMICOLON@[51; 52) ";""###,
1704 ); 1783 );
1705} 1784}
1706 1785