aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast/extensions.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast/extensions.rs')
-rw-r--r--crates/ra_syntax/src/ast/extensions.rs147
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 @@
4use itertools::Itertools; 4use itertools::Itertools;
5 5
6use crate::{ 6use 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
142impl ast::Path { 137impl ast::Path {
@@ -154,12 +149,6 @@ impl ast::Module {
154 } 149 }
155} 150}
156 151
157impl ast::UseTree {
158 pub fn has_star(&self) -> bool {
159 self.syntax().children_with_tokens().any(|it| it.kind() == T![*])
160 }
161}
162
163impl ast::UseTreeList { 152impl 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
186impl ast::ImplDef { 161impl ast::ImplDef {
@@ -387,24 +362,9 @@ pub enum SelfParamKind {
387} 362}
388 363
389impl ast::SelfParam { 364impl 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
418impl 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
427impl 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
436impl 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
455impl ast::TypeBound { 406impl 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
521impl ast::MacroCall { 486impl ast::MacroCall {
@@ -528,3 +493,41 @@ impl ast::MacroCall {
528 } 493 }
529 } 494 }
530} 495}
496
497impl 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
507impl 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
525impl 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}