aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_mbe/src/syntax_bridge.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_mbe/src/syntax_bridge.rs')
-rw-r--r--crates/ra_mbe/src/syntax_bridge.rs103
1 files changed, 103 insertions, 0 deletions
diff --git a/crates/ra_mbe/src/syntax_bridge.rs b/crates/ra_mbe/src/syntax_bridge.rs
index fcb73fbc7..0678c37ee 100644
--- a/crates/ra_mbe/src/syntax_bridge.rs
+++ b/crates/ra_mbe/src/syntax_bridge.rs
@@ -267,6 +267,108 @@ struct RawConvertor<'a> {
267 inner: std::slice::Iter<'a, Token>, 267 inner: std::slice::Iter<'a, Token>,
268} 268}
269 269
270trait SrcToken {
271 fn kind() -> SyntaxKind;
272}
273
274trait TokenConvertor {
275 type Token : SrcToken;
276
277 fn go(&mut self) -> Option<tt::Subtree> {
278 let mut subtree = tt::Subtree::default();
279 subtree.delimiter = None;
280 while self.peek().is_some() {
281 self.collect_leaf(&mut subtree.token_trees);
282 }
283 if subtree.token_trees.is_empty() {
284 return None;
285 }
286 if subtree.token_trees.len() == 1 {
287 if let tt::TokenTree::Subtree(first) = &subtree.token_trees[0] {
288 return Some(first.clone());
289 }
290 }
291 Some(subtree)
292 }
293
294 fn bump(&mut self) -> Option<(Self::Token, TextRange)>;
295
296 fn peek(&self) -> Option<Self::Token>;
297
298 fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
299 let (token, range) = match self.bump() {
300 None => return,
301 Some(it) => it,
302 };
303
304 let k: SyntaxKind = token.kind();
305 if k == COMMENT {
306 let node = doc_comment(&self.text[range]);
307 if let Some(tokens) = convert_doc_comment(&node) {
308 result.extend(tokens);
309 }
310 return;
311 }
312
313 result.push(if k.is_punct() {
314 let delim = match k {
315 T!['('] => Some((tt::DelimiterKind::Parenthesis, T![')'])),
316 T!['{'] => Some((tt::DelimiterKind::Brace, T!['}'])),
317 T!['['] => Some((tt::DelimiterKind::Bracket, T![']'])),
318 _ => None,
319 };
320
321 if let Some((kind, closed)) = delim {
322 let mut subtree = tt::Subtree::default();
323 let id = self.id_alloc.open_delim(range);
324 subtree.delimiter = Some(tt::Delimiter { kind, id });
325
326 while self.peek().map(|it| it.kind != closed).unwrap_or(false) {
327 self.collect_leaf(&mut subtree.token_trees);
328 }
329 let last_range = match self.bump() {
330 None => return,
331 Some(it) => it.1,
332 };
333 self.id_alloc.close_delim(id, last_range);
334 subtree.into()
335 } else {
336 let spacing = match self.peek() {
337 Some(next)
338 if next.kind.is_trivia()
339 || next.kind == T!['[']
340 || next.kind == T!['{']
341 || next.kind == T!['('] =>
342 {
343 tt::Spacing::Alone
344 }
345 Some(next) if next.kind.is_punct() => tt::Spacing::Joint,
346 _ => tt::Spacing::Alone,
347 };
348 let char =
349 self.text[range].chars().next().expect("Token from lexer must be single char");
350
351 tt::Leaf::from(tt::Punct { char, spacing, id: self.id_alloc.alloc(range) }).into()
352 }
353 } else {
354 macro_rules! make_leaf {
355 ($i:ident) => {
356 tt::$i { id: self.id_alloc.alloc(range), text: self.text[range].into() }.into()
357 };
358 }
359 let leaf: tt::Leaf = match k {
360 T![true] | T![false] => make_leaf!(Literal),
361 IDENT | LIFETIME => make_leaf!(Ident),
362 k if k.is_keyword() => make_leaf!(Ident),
363 k if k.is_literal() => make_leaf!(Literal),
364 _ => return,
365 };
366
367 leaf.into()
368 });
369 }
370}
371
270impl RawConvertor<'_> { 372impl RawConvertor<'_> {
271 fn go(&mut self) -> Option<tt::Subtree> { 373 fn go(&mut self) -> Option<tt::Subtree> {
272 let mut subtree = tt::Subtree::default(); 374 let mut subtree = tt::Subtree::default();
@@ -295,6 +397,7 @@ impl RawConvertor<'_> {
295 fn peek(&self) -> Option<Token> { 397 fn peek(&self) -> Option<Token> {
296 self.inner.as_slice().get(0).cloned() 398 self.inner.as_slice().get(0).cloned()
297 } 399 }
400
298 401
299 fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) { 402 fn collect_leaf(&mut self, result: &mut Vec<tt::TokenTree>) {
300 let (token, range) = match self.bump() { 403 let (token, range) = match self.bump() {