diff options
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r-- | crates/ra_syntax/src/ast/extensions.rs | 147 |
1 files changed, 75 insertions, 72 deletions
diff --git a/crates/ra_syntax/src/ast/extensions.rs b/crates/ra_syntax/src/ast/extensions.rs index bf7d137be..33fe60762 100644 --- a/crates/ra_syntax/src/ast/extensions.rs +++ b/crates/ra_syntax/src/ast/extensions.rs | |||
@@ -4,7 +4,9 @@ | |||
4 | use itertools::Itertools; | 4 | use itertools::Itertools; |
5 | 5 | ||
6 | use crate::{ | 6 | use crate::{ |
7 | ast::{self, child_opt, children, AstNode, AttrInput, NameOwner, SyntaxNode}, | 7 | ast::{ |
8 | self, child_opt, children, support, AstNode, AstToken, AttrInput, NameOwner, SyntaxNode, | ||
9 | }, | ||
8 | SmolStr, SyntaxElement, | 10 | SmolStr, SyntaxElement, |
9 | SyntaxKind::*, | 11 | SyntaxKind::*, |
10 | SyntaxToken, T, | 12 | SyntaxToken, T, |
@@ -130,13 +132,6 @@ impl ast::PathSegment { | |||
130 | }; | 132 | }; |
131 | Some(res) | 133 | Some(res) |
132 | } | 134 | } |
133 | |||
134 | pub fn has_colon_colon(&self) -> bool { | ||
135 | match self.syntax.first_child_or_token().map(|s| s.kind()) { | ||
136 | Some(T![::]) => true, | ||
137 | _ => false, | ||
138 | } | ||
139 | } | ||
140 | } | 135 | } |
141 | 136 | ||
142 | impl ast::Path { | 137 | impl ast::Path { |
@@ -154,12 +149,6 @@ impl ast::Module { | |||
154 | } | 149 | } |
155 | } | 150 | } |
156 | 151 | ||
157 | impl ast::UseTree { | ||
158 | pub fn has_star(&self) -> bool { | ||
159 | self.syntax().children_with_tokens().any(|it| it.kind() == T![*]) | ||
160 | } | ||
161 | } | ||
162 | |||
163 | impl ast::UseTreeList { | 152 | impl ast::UseTreeList { |
164 | pub fn parent_use_tree(&self) -> ast::UseTree { | 153 | pub fn parent_use_tree(&self) -> ast::UseTree { |
165 | self.syntax() | 154 | self.syntax() |
@@ -167,20 +156,6 @@ impl ast::UseTreeList { | |||
167 | .and_then(ast::UseTree::cast) | 156 | .and_then(ast::UseTree::cast) |
168 | .expect("UseTreeLists are always nested in UseTrees") | 157 | .expect("UseTreeLists are always nested in UseTrees") |
169 | } | 158 | } |
170 | pub fn l_curly(&self) -> Option<SyntaxToken> { | ||
171 | self.token(T!['{']) | ||
172 | } | ||
173 | |||
174 | pub fn r_curly(&self) -> Option<SyntaxToken> { | ||
175 | self.token(T!['}']) | ||
176 | } | ||
177 | |||
178 | fn token(&self, kind: SyntaxKind) -> Option<SyntaxToken> { | ||
179 | self.syntax() | ||
180 | .children_with_tokens() | ||
181 | .filter_map(|it| it.into_token()) | ||
182 | .find(|it| it.kind() == kind) | ||
183 | } | ||
184 | } | 159 | } |
185 | 160 | ||
186 | impl ast::ImplDef { | 161 | impl ast::ImplDef { |
@@ -387,24 +362,9 @@ pub enum SelfParamKind { | |||
387 | } | 362 | } |
388 | 363 | ||
389 | impl ast::SelfParam { | 364 | impl ast::SelfParam { |
390 | pub fn self_kw_token(&self) -> SyntaxToken { | ||
391 | self.syntax() | ||
392 | .children_with_tokens() | ||
393 | .filter_map(|it| it.into_token()) | ||
394 | .find(|it| it.kind() == T![self]) | ||
395 | .expect("invalid tree: self param must have self") | ||
396 | } | ||
397 | |||
398 | pub fn kind(&self) -> SelfParamKind { | 365 | pub fn kind(&self) -> SelfParamKind { |
399 | let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == T![&]); | 366 | if self.amp().is_some() { |
400 | if borrowed { | 367 | if self.amp_mut_kw().is_some() { |
401 | // check for a `mut` coming after the & -- `mut &self` != `&mut self` | ||
402 | if self | ||
403 | .syntax() | ||
404 | .children_with_tokens() | ||
405 | .skip_while(|n| n.kind() != T![&]) | ||
406 | .any(|n| n.kind() == T![mut]) | ||
407 | { | ||
408 | SelfParamKind::MutRef | 368 | SelfParamKind::MutRef |
409 | } else { | 369 | } else { |
410 | SelfParamKind::Ref | 370 | SelfParamKind::Ref |
@@ -413,32 +373,23 @@ impl ast::SelfParam { | |||
413 | SelfParamKind::Owned | 373 | SelfParamKind::Owned |
414 | } | 374 | } |
415 | } | 375 | } |
416 | } | ||
417 | 376 | ||
418 | impl ast::LifetimeParam { | 377 | /// the "mut" in "mut self", not the one in "&mut self" |
419 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | 378 | pub fn mut_kw(&self) -> Option<ast::MutKw> { |
420 | self.syntax() | 379 | self.syntax() |
421 | .children_with_tokens() | 380 | .children_with_tokens() |
422 | .filter_map(|it| it.into_token()) | 381 | .filter_map(|it| it.into_token()) |
423 | .find(|it| it.kind() == LIFETIME) | 382 | .take_while(|it| it.kind() != T![&]) |
383 | .find_map(ast::MutKw::cast) | ||
424 | } | 384 | } |
425 | } | ||
426 | 385 | ||
427 | impl ast::TypeParam { | 386 | /// the "mut" in "&mut self", not the one in "mut self" |
428 | pub fn colon_token(&self) -> Option<SyntaxToken> { | 387 | pub fn amp_mut_kw(&self) -> Option<ast::MutKw> { |
429 | self.syntax() | 388 | self.syntax() |
430 | .children_with_tokens() | 389 | .children_with_tokens() |
431 | .filter_map(|it| it.into_token()) | 390 | .filter_map(|it| it.into_token()) |
432 | .find(|it| it.kind() == T![:]) | 391 | .skip_while(|it| it.kind() != T![&]) |
433 | } | 392 | .find_map(ast::MutKw::cast) |
434 | } | ||
435 | |||
436 | impl ast::WherePred { | ||
437 | pub fn lifetime_token(&self) -> Option<SyntaxToken> { | ||
438 | self.syntax() | ||
439 | .children_with_tokens() | ||
440 | .filter_map(|it| it.into_token()) | ||
441 | .find(|it| it.kind() == LIFETIME) | ||
442 | } | 393 | } |
443 | } | 394 | } |
444 | 395 | ||
@@ -449,7 +400,7 @@ pub enum TypeBoundKind { | |||
449 | /// for<'a> ... | 400 | /// for<'a> ... |
450 | ForType(ast::ForType), | 401 | ForType(ast::ForType), |
451 | /// 'a | 402 | /// 'a |
452 | Lifetime(ast::SyntaxToken), | 403 | Lifetime(ast::Lifetime), |
453 | } | 404 | } |
454 | 405 | ||
455 | impl ast::TypeBound { | 406 | impl ast::TypeBound { |
@@ -465,21 +416,28 @@ impl ast::TypeBound { | |||
465 | } | 416 | } |
466 | } | 417 | } |
467 | 418 | ||
468 | fn lifetime(&self) -> Option<SyntaxToken> { | 419 | pub fn has_question_mark(&self) -> bool { |
469 | self.syntax() | 420 | self.question().is_some() |
470 | .children_with_tokens() | ||
471 | .filter_map(|it| it.into_token()) | ||
472 | .find(|it| it.kind() == LIFETIME) | ||
473 | } | 421 | } |
474 | 422 | ||
475 | pub fn question_mark_token(&self) -> Option<SyntaxToken> { | 423 | pub fn const_question(&self) -> Option<ast::Question> { |
476 | self.syntax() | 424 | self.syntax() |
477 | .children_with_tokens() | 425 | .children_with_tokens() |
478 | .filter_map(|it| it.into_token()) | 426 | .filter_map(|it| it.into_token()) |
479 | .find(|it| it.kind() == T![?]) | 427 | .take_while(|it| it.kind() != T![const]) |
428 | .find_map(ast::Question::cast) | ||
480 | } | 429 | } |
481 | pub fn has_question_mark(&self) -> bool { | 430 | |
482 | self.question_mark_token().is_some() | 431 | pub fn question(&self) -> Option<ast::Question> { |
432 | if self.const_kw().is_some() { | ||
433 | self.syntax() | ||
434 | .children_with_tokens() | ||
435 | .filter_map(|it| it.into_token()) | ||
436 | .skip_while(|it| it.kind() != T![const]) | ||
437 | .find_map(ast::Question::cast) | ||
438 | } else { | ||
439 | support::token(&self.syntax) | ||
440 | } | ||
483 | } | 441 | } |
484 | } | 442 | } |
485 | 443 | ||
@@ -493,6 +451,7 @@ pub enum VisibilityKind { | |||
493 | In(ast::Path), | 451 | In(ast::Path), |
494 | PubCrate, | 452 | PubCrate, |
495 | PubSuper, | 453 | PubSuper, |
454 | PubSelf, | ||
496 | Pub, | 455 | Pub, |
497 | } | 456 | } |
498 | 457 | ||
@@ -504,6 +463,8 @@ impl ast::Visibility { | |||
504 | VisibilityKind::PubCrate | 463 | VisibilityKind::PubCrate |
505 | } else if self.is_pub_super() { | 464 | } else if self.is_pub_super() { |
506 | VisibilityKind::PubSuper | 465 | VisibilityKind::PubSuper |
466 | } else if self.is_pub_self() { | ||
467 | VisibilityKind::PubSuper | ||
507 | } else { | 468 | } else { |
508 | VisibilityKind::Pub | 469 | VisibilityKind::Pub |
509 | } | 470 | } |
@@ -516,6 +477,10 @@ impl ast::Visibility { | |||
516 | fn is_pub_super(&self) -> bool { | 477 | fn is_pub_super(&self) -> bool { |
517 | self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) | 478 | self.syntax().children_with_tokens().any(|it| it.kind() == T![super]) |
518 | } | 479 | } |
480 | |||
481 | fn is_pub_self(&self) -> bool { | ||
482 | self.syntax().children_with_tokens().any(|it| it.kind() == T![self]) | ||
483 | } | ||
519 | } | 484 | } |
520 | 485 | ||
521 | impl ast::MacroCall { | 486 | impl ast::MacroCall { |
@@ -528,3 +493,41 @@ impl ast::MacroCall { | |||
528 | } | 493 | } |
529 | } | 494 | } |
530 | } | 495 | } |
496 | |||
497 | impl ast::LifetimeParam { | ||
498 | pub fn lifetime_bounds(&self) -> impl Iterator<Item = ast::Lifetime> { | ||
499 | self.syntax() | ||
500 | .children_with_tokens() | ||
501 | .filter_map(|it| it.into_token()) | ||
502 | .skip_while(|x| x.kind() != T![:]) | ||
503 | .filter_map(ast::Lifetime::cast) | ||
504 | } | ||
505 | } | ||
506 | |||
507 | impl ast::RangePat { | ||
508 | pub fn start(&self) -> Option<ast::Pat> { | ||
509 | self.syntax() | ||
510 | .children_with_tokens() | ||
511 | .take_while(|it| !ast::RangeSeparator::can_cast(it.kind())) | ||
512 | .filter_map(|it| it.into_node()) | ||
513 | .find_map(ast::Pat::cast) | ||
514 | } | ||
515 | |||
516 | pub fn end(&self) -> Option<ast::Pat> { | ||
517 | self.syntax() | ||
518 | .children_with_tokens() | ||
519 | .skip_while(|it| !ast::RangeSeparator::can_cast(it.kind())) | ||
520 | .filter_map(|it| it.into_node()) | ||
521 | .find_map(ast::Pat::cast) | ||
522 | } | ||
523 | } | ||
524 | |||
525 | impl ast::TokenTree { | ||
526 | pub fn left_delimiter(&self) -> Option<ast::LeftDelimiter> { | ||
527 | self.syntax().first_child_or_token()?.into_token().and_then(ast::LeftDelimiter::cast) | ||
528 | } | ||
529 | |||
530 | pub fn right_delimiter(&self) -> Option<ast::RightDelimiter> { | ||
531 | self.syntax().last_child_or_token()?.into_token().and_then(ast::RightDelimiter::cast) | ||
532 | } | ||
533 | } | ||