aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_syntax/src/ast.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_syntax/src/ast.rs')
-rw-r--r--crates/ra_syntax/src/ast.rs246
1 files changed, 161 insertions, 85 deletions
diff --git a/crates/ra_syntax/src/ast.rs b/crates/ra_syntax/src/ast.rs
index fd7e63f84..9a44afc67 100644
--- a/crates/ra_syntax/src/ast.rs
+++ b/crates/ra_syntax/src/ast.rs
@@ -7,7 +7,7 @@ use itertools::Itertools;
7 7
8pub use self::generated::*; 8pub use self::generated::*;
9use crate::{ 9use crate::{
10 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes}, 10 syntax_node::{SyntaxNode, SyntaxNodeChildren, TreeArc, RaTypes, SyntaxToken, SyntaxElement, SyntaxElementChildren},
11 SmolStr, 11 SmolStr,
12 SyntaxKind::*, 12 SyntaxKind::*,
13}; 13};
@@ -27,7 +27,8 @@ pub trait AstNode:
27 27
28pub trait AstToken: AstNode { 28pub trait AstToken: AstNode {
29 fn text(&self) -> &SmolStr { 29 fn text(&self) -> &SmolStr {
30 self.syntax().leaf_text().unwrap() 30 // self.syntax().leaf_text().unwrap()
31 unimplemented!()
31 } 32 }
32} 33}
33 34
@@ -126,8 +127,8 @@ pub trait AttrsOwner: AstNode {
126} 127}
127 128
128pub trait DocCommentsOwner: AstNode { 129pub trait DocCommentsOwner: AstNode {
129 fn doc_comments(&self) -> AstChildren<Comment> { 130 fn doc_comments(&self) -> CommentIter {
130 children(self) 131 CommentIter { iter: self.syntax().children_with_tokens() }
131 } 132 }
132 133
133 /// Returns the textual content of a doc comment block as a single string. 134 /// Returns the textual content of a doc comment block as a single string.
@@ -179,9 +180,9 @@ impl Attr {
179 180
180 pub fn as_atom(&self) -> Option<SmolStr> { 181 pub fn as_atom(&self) -> Option<SmolStr> {
181 let tt = self.value()?; 182 let tt = self.value()?;
182 let (_bra, attr, _ket) = tt.syntax().children().collect_tuple()?; 183 let (_bra, attr, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
183 if attr.kind() == IDENT { 184 if attr.kind() == IDENT {
184 Some(attr.leaf_text().unwrap().clone()) 185 Some(attr.as_token()?.text().clone())
185 } else { 186 } else {
186 None 187 None
187 } 188 }
@@ -189,10 +190,10 @@ impl Attr {
189 190
190 pub fn as_call(&self) -> Option<(SmolStr, &TokenTree)> { 191 pub fn as_call(&self) -> Option<(SmolStr, &TokenTree)> {
191 let tt = self.value()?; 192 let tt = self.value()?;
192 let (_bra, attr, args, _ket) = tt.syntax().children().collect_tuple()?; 193 let (_bra, attr, args, _ket) = tt.syntax().children_with_tokens().collect_tuple()?;
193 let args = TokenTree::cast(args)?; 194 let args = TokenTree::cast(args.as_node()?)?;
194 if attr.kind() == IDENT { 195 if attr.kind() == IDENT {
195 Some((attr.leaf_text().unwrap().clone(), args)) 196 Some((attr.as_token()?.text().clone(), args))
196 } else { 197 } else {
197 None 198 None
198 } 199 }
@@ -200,16 +201,35 @@ impl Attr {
200 201
201 pub fn as_named(&self) -> Option<SmolStr> { 202 pub fn as_named(&self) -> Option<SmolStr> {
202 let tt = self.value()?; 203 let tt = self.value()?;
203 let attr = tt.syntax().children().nth(1)?; 204 let attr = tt.syntax().children_with_tokens().nth(1)?;
204 if attr.kind() == IDENT { 205 if attr.kind() == IDENT {
205 Some(attr.leaf_text().unwrap().clone()) 206 Some(attr.as_token()?.text().clone())
206 } else { 207 } else {
207 None 208 None
208 } 209 }
209 } 210 }
210} 211}
211 212
212impl Comment { 213#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
214pub struct Comment<'a>(SyntaxToken<'a>);
215
216impl<'a> Comment<'a> {
217 pub fn cast(token: SyntaxToken<'a>) -> Option<Self> {
218 if token.kind() == COMMENT {
219 Some(Comment(token))
220 } else {
221 None
222 }
223 }
224
225 pub fn syntax(&self) -> SyntaxToken<'a> {
226 self.0
227 }
228
229 pub fn text(&self) -> &'a SmolStr {
230 self.0.text()
231 }
232
213 pub fn flavor(&self) -> CommentFlavor { 233 pub fn flavor(&self) -> CommentFlavor {
214 let text = self.text(); 234 let text = self.text();
215 if text.starts_with("///") { 235 if text.starts_with("///") {
@@ -230,13 +250,16 @@ impl Comment {
230 pub fn prefix(&self) -> &'static str { 250 pub fn prefix(&self) -> &'static str {
231 self.flavor().prefix() 251 self.flavor().prefix()
232 } 252 }
253}
233 254
234 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { 255pub struct CommentIter<'a> {
235 self.text().chars().filter(|&c| c == '\n').map(|_| &()) 256 iter: SyntaxElementChildren<'a>,
236 } 257}
237 258
238 pub fn has_newlines(&self) -> bool { 259impl<'a> Iterator for CommentIter<'a> {
239 self.count_newlines_lazy().count() > 0 260 type Item = Comment<'a>;
261 fn next(&mut self) -> Option<Comment<'a>> {
262 self.iter.by_ref().find_map(|el| el.as_token().and_then(Comment::cast))
240 } 263 }
241} 264}
242 265
@@ -267,27 +290,42 @@ impl CommentFlavor {
267 } 290 }
268} 291}
269 292
270impl Whitespace { 293pub struct Whitespace<'a>(SyntaxToken<'a>);
271 pub fn count_newlines_lazy(&self) -> impl Iterator<Item = &()> { 294
272 self.text().chars().filter(|&c| c == '\n').map(|_| &()) 295impl<'a> Whitespace<'a> {
296 pub fn cast(token: SyntaxToken<'a>) -> Option<Self> {
297 if token.kind() == WHITESPACE {
298 Some(Whitespace(token))
299 } else {
300 None
301 }
302 }
303
304 pub fn syntax(&self) -> SyntaxToken<'a> {
305 self.0
273 } 306 }
274 307
275 pub fn has_newlines(&self) -> bool { 308 pub fn text(&self) -> &'a SmolStr {
276 self.text().contains('\n') 309 self.0.text()
310 }
311
312 pub fn spans_multiple_lines(&self) -> bool {
313 let text = self.text();
314 text.find('\n').map_or(false, |idx| text[idx + 1..].contains('\n'))
277 } 315 }
278} 316}
279 317
280impl Name { 318impl Name {
281 pub fn text(&self) -> &SmolStr { 319 pub fn text(&self) -> &SmolStr {
282 let ident = self.syntax().first_child().unwrap(); 320 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
283 ident.leaf_text().unwrap() 321 ident.text()
284 } 322 }
285} 323}
286 324
287impl NameRef { 325impl NameRef {
288 pub fn text(&self) -> &SmolStr { 326 pub fn text(&self) -> &SmolStr {
289 let ident = self.syntax().first_child().unwrap(); 327 let ident = self.syntax().first_child_or_token().unwrap().as_token().unwrap();
290 ident.leaf_text().unwrap() 328 ident.text()
291 } 329 }
292} 330}
293 331
@@ -316,7 +354,7 @@ impl ImplBlock {
316 354
317impl Module { 355impl Module {
318 pub fn has_semi(&self) -> bool { 356 pub fn has_semi(&self) -> bool {
319 match self.syntax().last_child() { 357 match self.syntax().last_child_or_token() {
320 None => false, 358 None => false,
321 Some(node) => node.kind() == SEMI, 359 Some(node) => node.kind() == SEMI,
322 } 360 }
@@ -325,7 +363,7 @@ impl Module {
325 363
326impl LetStmt { 364impl LetStmt {
327 pub fn has_semi(&self) -> bool { 365 pub fn has_semi(&self) -> bool {
328 match self.syntax().last_child() { 366 match self.syntax().last_child_or_token() {
329 None => false, 367 None => false,
330 Some(node) => node.kind() == SEMI, 368 Some(node) => node.kind() == SEMI,
331 } 369 }
@@ -360,7 +398,7 @@ impl IfExpr {
360 398
361impl ExprStmt { 399impl ExprStmt {
362 pub fn has_semi(&self) -> bool { 400 pub fn has_semi(&self) -> bool {
363 match self.syntax().last_child() { 401 match self.syntax().last_child_or_token() {
364 None => false, 402 None => false,
365 Some(node) => node.kind() == SEMI, 403 Some(node) => node.kind() == SEMI,
366 } 404 }
@@ -384,7 +422,7 @@ impl PathSegment {
384 let res = if let Some(name_ref) = self.name_ref() { 422 let res = if let Some(name_ref) = self.name_ref() {
385 PathSegmentKind::Name(name_ref) 423 PathSegmentKind::Name(name_ref)
386 } else { 424 } else {
387 match self.syntax().first_child()?.kind() { 425 match self.syntax().first_child_or_token()?.kind() {
388 SELF_KW => PathSegmentKind::SelfKw, 426 SELF_KW => PathSegmentKind::SelfKw,
389 SUPER_KW => PathSegmentKind::SuperKw, 427 SUPER_KW => PathSegmentKind::SuperKw,
390 CRATE_KW => PathSegmentKind::CrateKw, 428 CRATE_KW => PathSegmentKind::CrateKw,
@@ -395,7 +433,7 @@ impl PathSegment {
395 } 433 }
396 434
397 pub fn has_colon_colon(&self) -> bool { 435 pub fn has_colon_colon(&self) -> bool {
398 match self.syntax.first_child().map(|s| s.kind()) { 436 match self.syntax.first_child_or_token().map(|s| s.kind()) {
399 Some(COLONCOLON) => true, 437 Some(COLONCOLON) => true,
400 _ => false, 438 _ => false,
401 } 439 }
@@ -410,7 +448,7 @@ impl Path {
410 448
411impl UseTree { 449impl UseTree {
412 pub fn has_star(&self) -> bool { 450 pub fn has_star(&self) -> bool {
413 self.syntax().children().any(|it| it.kind() == STAR) 451 self.syntax().children_with_tokens().any(|it| it.kind() == STAR)
414 } 452 }
415} 453}
416 454
@@ -425,7 +463,7 @@ impl UseTreeList {
425 463
426impl RefPat { 464impl RefPat {
427 pub fn is_mut(&self) -> bool { 465 pub fn is_mut(&self) -> bool {
428 self.syntax().children().any(|n| n.kind() == MUT_KW) 466 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
429 } 467 }
430} 468}
431 469
@@ -500,19 +538,19 @@ impl EnumVariant {
500 538
501impl PointerType { 539impl PointerType {
502 pub fn is_mut(&self) -> bool { 540 pub fn is_mut(&self) -> bool {
503 self.syntax().children().any(|n| n.kind() == MUT_KW) 541 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
504 } 542 }
505} 543}
506 544
507impl ReferenceType { 545impl ReferenceType {
508 pub fn is_mut(&self) -> bool { 546 pub fn is_mut(&self) -> bool {
509 self.syntax().children().any(|n| n.kind() == MUT_KW) 547 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
510 } 548 }
511} 549}
512 550
513impl RefExpr { 551impl RefExpr {
514 pub fn is_mut(&self) -> bool { 552 pub fn is_mut(&self) -> bool {
515 self.syntax().children().any(|n| n.kind() == MUT_KW) 553 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
516 } 554 }
517} 555}
518 556
@@ -528,7 +566,7 @@ pub enum PrefixOp {
528 566
529impl PrefixExpr { 567impl PrefixExpr {
530 pub fn op_kind(&self) -> Option<PrefixOp> { 568 pub fn op_kind(&self) -> Option<PrefixOp> {
531 match self.syntax().first_child()?.kind() { 569 match self.op_token()?.kind() {
532 STAR => Some(PrefixOp::Deref), 570 STAR => Some(PrefixOp::Deref),
533 EXCL => Some(PrefixOp::Not), 571 EXCL => Some(PrefixOp::Not),
534 MINUS => Some(PrefixOp::Neg), 572 MINUS => Some(PrefixOp::Neg),
@@ -536,8 +574,8 @@ impl PrefixExpr {
536 } 574 }
537 } 575 }
538 576
539 pub fn op(&self) -> Option<&SyntaxNode> { 577 pub fn op_token(&self) -> Option<SyntaxToken> {
540 self.syntax().first_child() 578 self.syntax().first_child_or_token()?.as_token()
541 } 579 }
542} 580}
543 581
@@ -608,40 +646,42 @@ pub enum BinOp {
608} 646}
609 647
610impl BinExpr { 648impl BinExpr {
611 fn op_details(&self) -> Option<(&SyntaxNode, BinOp)> { 649 fn op_details(&self) -> Option<(SyntaxToken, BinOp)> {
612 self.syntax().children().find_map(|c| match c.kind() { 650 self.syntax().children_with_tokens().filter_map(|it| it.as_token()).find_map(|c| {
613 PIPEPIPE => Some((c, BinOp::BooleanOr)), 651 match c.kind() {
614 AMPAMP => Some((c, BinOp::BooleanAnd)), 652 PIPEPIPE => Some((c, BinOp::BooleanOr)),
615 EQEQ => Some((c, BinOp::EqualityTest)), 653 AMPAMP => Some((c, BinOp::BooleanAnd)),
616 NEQ => Some((c, BinOp::NegatedEqualityTest)), 654 EQEQ => Some((c, BinOp::EqualityTest)),
617 LTEQ => Some((c, BinOp::LesserEqualTest)), 655 NEQ => Some((c, BinOp::NegatedEqualityTest)),
618 GTEQ => Some((c, BinOp::GreaterEqualTest)), 656 LTEQ => Some((c, BinOp::LesserEqualTest)),
619 L_ANGLE => Some((c, BinOp::LesserTest)), 657 GTEQ => Some((c, BinOp::GreaterEqualTest)),
620 R_ANGLE => Some((c, BinOp::GreaterTest)), 658 L_ANGLE => Some((c, BinOp::LesserTest)),
621 PLUS => Some((c, BinOp::Addition)), 659 R_ANGLE => Some((c, BinOp::GreaterTest)),
622 STAR => Some((c, BinOp::Multiplication)), 660 PLUS => Some((c, BinOp::Addition)),
623 MINUS => Some((c, BinOp::Subtraction)), 661 STAR => Some((c, BinOp::Multiplication)),
624 SLASH => Some((c, BinOp::Division)), 662 MINUS => Some((c, BinOp::Subtraction)),
625 PERCENT => Some((c, BinOp::Remainder)), 663 SLASH => Some((c, BinOp::Division)),
626 SHL => Some((c, BinOp::LeftShift)), 664 PERCENT => Some((c, BinOp::Remainder)),
627 SHR => Some((c, BinOp::RightShift)), 665 SHL => Some((c, BinOp::LeftShift)),
628 CARET => Some((c, BinOp::BitwiseXor)), 666 SHR => Some((c, BinOp::RightShift)),
629 PIPE => Some((c, BinOp::BitwiseOr)), 667 CARET => Some((c, BinOp::BitwiseXor)),
630 AMP => Some((c, BinOp::BitwiseAnd)), 668 PIPE => Some((c, BinOp::BitwiseOr)),
631 DOTDOT => Some((c, BinOp::RangeRightOpen)), 669 AMP => Some((c, BinOp::BitwiseAnd)),
632 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)), 670 DOTDOT => Some((c, BinOp::RangeRightOpen)),
633 EQ => Some((c, BinOp::Assignment)), 671 DOTDOTEQ => Some((c, BinOp::RangeRightClosed)),
634 PLUSEQ => Some((c, BinOp::AddAssign)), 672 EQ => Some((c, BinOp::Assignment)),
635 SLASHEQ => Some((c, BinOp::DivAssign)), 673 PLUSEQ => Some((c, BinOp::AddAssign)),
636 STAREQ => Some((c, BinOp::MulAssign)), 674 SLASHEQ => Some((c, BinOp::DivAssign)),
637 PERCENTEQ => Some((c, BinOp::RemAssign)), 675 STAREQ => Some((c, BinOp::MulAssign)),
638 SHREQ => Some((c, BinOp::ShrAssign)), 676 PERCENTEQ => Some((c, BinOp::RemAssign)),
639 SHLEQ => Some((c, BinOp::ShlAssign)), 677 SHREQ => Some((c, BinOp::ShrAssign)),
640 MINUSEQ => Some((c, BinOp::SubAssign)), 678 SHLEQ => Some((c, BinOp::ShlAssign)),
641 PIPEEQ => Some((c, BinOp::BitOrAssign)), 679 MINUSEQ => Some((c, BinOp::SubAssign)),
642 AMPEQ => Some((c, BinOp::BitAndAssign)), 680 PIPEEQ => Some((c, BinOp::BitOrAssign)),
643 CARETEQ => Some((c, BinOp::BitXorAssign)), 681 AMPEQ => Some((c, BinOp::BitAndAssign)),
644 _ => None, 682 CARETEQ => Some((c, BinOp::BitXorAssign)),
683 _ => None,
684 }
645 }) 685 })
646 } 686 }
647 687
@@ -649,7 +689,7 @@ impl BinExpr {
649 self.op_details().map(|t| t.1) 689 self.op_details().map(|t| t.1)
650 } 690 }
651 691
652 pub fn op(&self) -> Option<&SyntaxNode> { 692 pub fn op_token(&self) -> Option<SyntaxToken> {
653 self.op_details().map(|t| t.0) 693 self.op_details().map(|t| t.0)
654 } 694 }
655 695
@@ -680,11 +720,23 @@ pub enum SelfParamFlavor {
680} 720}
681 721
682impl SelfParam { 722impl SelfParam {
723 pub fn self_kw_token(&self) -> SyntaxToken {
724 self.syntax()
725 .children_with_tokens()
726 .filter_map(|it| it.as_token())
727 .find(|it| it.kind() == SELF_KW)
728 .expect("invalid tree: self param must have self")
729 }
730
683 pub fn flavor(&self) -> SelfParamFlavor { 731 pub fn flavor(&self) -> SelfParamFlavor {
684 let borrowed = self.syntax().children().any(|n| n.kind() == AMP); 732 let borrowed = self.syntax().children_with_tokens().any(|n| n.kind() == AMP);
685 if borrowed { 733 if borrowed {
686 // check for a `mut` coming after the & -- `mut &self` != `&mut self` 734 // check for a `mut` coming after the & -- `mut &self` != `&mut self`
687 if self.syntax().children().skip_while(|n| n.kind() != AMP).any(|n| n.kind() == MUT_KW) 735 if self
736 .syntax()
737 .children_with_tokens()
738 .skip_while(|n| n.kind() != AMP)
739 .any(|n| n.kind() == MUT_KW)
688 { 740 {
689 SelfParamFlavor::MutRef 741 SelfParamFlavor::MutRef
690 } else { 742 } else {
@@ -707,25 +759,31 @@ pub enum LiteralFlavor {
707 Bool, 759 Bool,
708} 760}
709 761
710impl LiteralExpr { 762impl Literal {
763 pub fn token(&self) -> SyntaxToken {
764 match self.syntax().first_child_or_token().unwrap() {
765 SyntaxElement::Token(token) => token,
766 _ => unreachable!(),
767 }
768 }
769
711 pub fn flavor(&self) -> LiteralFlavor { 770 pub fn flavor(&self) -> LiteralFlavor {
712 let syntax = self.syntax(); 771 match self.token().kind() {
713 match syntax.kind() {
714 INT_NUMBER => { 772 INT_NUMBER => {
715 let allowed_suffix_list = [ 773 let allowed_suffix_list = [
716 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32", 774 "isize", "i128", "i64", "i32", "i16", "i8", "usize", "u128", "u64", "u32",
717 "u16", "u8", 775 "u16", "u8",
718 ]; 776 ];
719 let text = syntax.text().to_string(); 777 let text = self.token().text().to_string();
720 let suffix = allowed_suffix_list 778 let suffix = allowed_suffix_list
721 .iter() 779 .iter()
722 .find(|&s| text.ends_with(s)) 780 .find(|&s| text.ends_with(s))
723 .map(|&suf| SmolStr::new(suf)); 781 .map(|&suf| SmolStr::new(suf));
724 LiteralFlavor::IntNumber { suffix: suffix } 782 LiteralFlavor::IntNumber { suffix }
725 } 783 }
726 FLOAT_NUMBER => { 784 FLOAT_NUMBER => {
727 let allowed_suffix_list = ["f64", "f32"]; 785 let allowed_suffix_list = ["f64", "f32"];
728 let text = syntax.text().to_string(); 786 let text = self.token().text().to_string();
729 let suffix = allowed_suffix_list 787 let suffix = allowed_suffix_list
730 .iter() 788 .iter()
731 .find(|&s| text.ends_with(s)) 789 .find(|&s| text.ends_with(s))
@@ -750,11 +808,29 @@ impl NamedField {
750 808
751impl BindPat { 809impl BindPat {
752 pub fn is_mutable(&self) -> bool { 810 pub fn is_mutable(&self) -> bool {
753 self.syntax().children().any(|n| n.kind() == MUT_KW) 811 self.syntax().children_with_tokens().any(|n| n.kind() == MUT_KW)
754 } 812 }
755 813
756 pub fn is_ref(&self) -> bool { 814 pub fn is_ref(&self) -> bool {
757 self.syntax().children().any(|n| n.kind() == REF_KW) 815 self.syntax().children_with_tokens().any(|n| n.kind() == REF_KW)
816 }
817}
818
819impl LifetimeParam {
820 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
821 self.syntax()
822 .children_with_tokens()
823 .filter_map(|it| it.as_token())
824 .find(|it| it.kind() == LIFETIME)
825 }
826}
827
828impl WherePred {
829 pub fn lifetime_token(&self) -> Option<SyntaxToken> {
830 self.syntax()
831 .children_with_tokens()
832 .filter_map(|it| it.as_token())
833 .find(|it| it.kind() == LIFETIME)
758 } 834 }
759} 835}
760 836
@@ -835,7 +911,7 @@ where
835 let pred = predicates.next().unwrap(); 911 let pred = predicates.next().unwrap();
836 let mut bounds = pred.type_bound_list().unwrap().bounds(); 912 let mut bounds = pred.type_bound_list().unwrap().bounds();
837 913
838 assert_eq!("'a", pred.lifetime().unwrap().syntax().text().to_string()); 914 assert_eq!("'a", pred.lifetime_token().unwrap().text());
839 915
840 assert_bound("'b", bounds.next()); 916 assert_bound("'b", bounds.next());
841 assert_bound("'c", bounds.next()); 917 assert_bound("'c", bounds.next());