1use std::{borrow::Cow, fmt, iter::successors};
7
8use itertools::Itertools;
9use parser::SyntaxKind;
10use rowan::{GreenNodeData, GreenTokenData};
11
12use crate::{
13 NodeOrToken, SmolStr, SyntaxElement, SyntaxElementChildren, SyntaxToken, T, TokenText,
14 ast::{
15 self, AstNode, AstToken, HasAttrs, HasGenericArgs, HasGenericParams, HasName,
16 HasTypeBounds, SyntaxNode, support,
17 },
18 ted,
19};
20
21use super::{GenericParam, RangeItem, RangeOp};
22
23impl ast::Lifetime {
24 pub fn text(&self) -> TokenText<'_> {
25 text_of_first_token(self.syntax())
26 }
27}
28
29impl ast::Name {
30 pub fn text(&self) -> TokenText<'_> {
31 text_of_first_token(self.syntax())
32 }
33 pub fn text_non_mutable(&self) -> &str {
34 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
35 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
36 }
37
38 match self.syntax().green() {
39 Cow::Borrowed(green_ref) => first_token(green_ref).text(),
40 Cow::Owned(_) => unreachable!(),
41 }
42 }
43}
44
45impl ast::NameRef {
46 pub fn text(&self) -> TokenText<'_> {
47 text_of_first_token(self.syntax())
48 }
49 pub fn text_non_mutable(&self) -> &str {
50 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
51 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
52 }
53
54 match self.syntax().green() {
55 Cow::Borrowed(green_ref) => first_token(green_ref).text(),
56 Cow::Owned(_) => unreachable!(),
57 }
58 }
59
60 pub fn as_tuple_field(&self) -> Option<usize> {
61 self.text().parse().ok()
62 }
63
64 pub fn token_kind(&self) -> SyntaxKind {
65 self.syntax().first_token().map_or(SyntaxKind::ERROR, |it| it.kind())
66 }
67}
68
69fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
70 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
71 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
72 }
73
74 match node.green() {
75 Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
76 Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
77 }
78}
79
80impl ast::Abi {
81 pub fn abi_string(&self) -> Option<ast::String> {
82 support::token(&self.syntax, SyntaxKind::STRING).and_then(ast::String::cast)
83 }
84}
85
86impl ast::HasModuleItem for ast::StmtList {}
87
88impl ast::BlockExpr {
89 pub fn statements(&self) -> impl Iterator<Item = ast::Stmt> {
91 self.stmt_list().into_iter().flat_map(|it| it.statements())
92 }
93 pub fn tail_expr(&self) -> Option<ast::Expr> {
94 self.stmt_list()?.tail_expr()
95 }
96 pub fn may_carry_attributes(&self) -> bool {
99 matches!(
100 self.syntax().parent().map(|it| it.kind()),
101 Some(SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT)
102 )
103 }
104}
105
106#[derive(Debug, PartialEq, Eq, Clone)]
107pub enum Macro {
108 MacroRules(ast::MacroRules),
109 MacroDef(ast::MacroDef),
110}
111
112impl From<ast::MacroRules> for Macro {
113 fn from(it: ast::MacroRules) -> Self {
114 Macro::MacroRules(it)
115 }
116}
117
118impl From<ast::MacroDef> for Macro {
119 fn from(it: ast::MacroDef) -> Self {
120 Macro::MacroDef(it)
121 }
122}
123
124impl AstNode for Macro {
125 fn can_cast(kind: SyntaxKind) -> bool {
126 matches!(kind, SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF)
127 }
128 fn cast(syntax: SyntaxNode) -> Option<Self> {
129 let res = match syntax.kind() {
130 SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }),
131 SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }),
132 _ => return None,
133 };
134 Some(res)
135 }
136 fn syntax(&self) -> &SyntaxNode {
137 match self {
138 Macro::MacroRules(it) => it.syntax(),
139 Macro::MacroDef(it) => it.syntax(),
140 }
141 }
142}
143
144impl HasName for Macro {
145 fn name(&self) -> Option<ast::Name> {
146 match self {
147 Macro::MacroRules(mac) => mac.name(),
148 Macro::MacroDef(mac) => mac.name(),
149 }
150 }
151}
152
153impl HasAttrs for Macro {}
154
155impl From<ast::AssocItem> for ast::Item {
156 fn from(assoc: ast::AssocItem) -> Self {
157 match assoc {
158 ast::AssocItem::Const(it) => ast::Item::Const(it),
159 ast::AssocItem::Fn(it) => ast::Item::Fn(it),
160 ast::AssocItem::MacroCall(it) => ast::Item::MacroCall(it),
161 ast::AssocItem::TypeAlias(it) => ast::Item::TypeAlias(it),
162 }
163 }
164}
165
166impl From<ast::ExternItem> for ast::Item {
167 fn from(extern_item: ast::ExternItem) -> Self {
168 match extern_item {
169 ast::ExternItem::Static(it) => ast::Item::Static(it),
170 ast::ExternItem::Fn(it) => ast::Item::Fn(it),
171 ast::ExternItem::MacroCall(it) => ast::Item::MacroCall(it),
172 ast::ExternItem::TypeAlias(it) => ast::Item::TypeAlias(it),
173 }
174 }
175}
176
177#[derive(Debug, Copy, Clone, PartialEq, Eq)]
178pub enum AttrKind {
179 Inner,
180 Outer,
181}
182
183impl AttrKind {
184 pub fn is_inner(&self) -> bool {
186 matches!(self, Self::Inner)
187 }
188
189 pub fn is_outer(&self) -> bool {
191 matches!(self, Self::Outer)
192 }
193}
194
195impl ast::Attr {
196 pub fn as_simple_atom(&self) -> Option<SmolStr> {
197 let meta = self.meta()?;
198 if meta.eq_token().is_some() || meta.token_tree().is_some() {
199 return None;
200 }
201 self.simple_name()
202 }
203
204 pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
205 let tt = self.meta()?.token_tree()?;
206 Some((self.simple_name()?, tt))
207 }
208
209 pub fn as_simple_path(&self) -> Option<ast::Path> {
210 let meta = self.meta()?;
211 if meta.eq_token().is_some() || meta.token_tree().is_some() {
212 return None;
213 }
214 self.path()
215 }
216
217 pub fn simple_name(&self) -> Option<SmolStr> {
218 let path = self.meta()?.path()?;
219 match (path.segment(), path.qualifier()) {
220 (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()),
221 _ => None,
222 }
223 }
224
225 pub fn kind(&self) -> AttrKind {
226 match self.excl_token() {
227 Some(_) => AttrKind::Inner,
228 None => AttrKind::Outer,
229 }
230 }
231
232 pub fn path(&self) -> Option<ast::Path> {
233 self.meta()?.path()
234 }
235
236 pub fn expr(&self) -> Option<ast::Expr> {
237 self.meta()?.expr()
238 }
239
240 pub fn token_tree(&self) -> Option<ast::TokenTree> {
241 self.meta()?.token_tree()
242 }
243}
244
245#[derive(Debug, Clone, PartialEq, Eq)]
246pub enum PathSegmentKind {
247 Name(ast::NameRef),
248 Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
249 SelfTypeKw,
250 SelfKw,
251 SuperKw,
252 CrateKw,
253}
254
255impl ast::PathSegment {
256 pub fn parent_path(&self) -> ast::Path {
257 self.syntax()
258 .parent()
259 .and_then(ast::Path::cast)
260 .expect("segments are always nested in paths")
261 }
262
263 pub fn crate_token(&self) -> Option<SyntaxToken> {
264 self.name_ref().and_then(|it| it.crate_token())
265 }
266
267 pub fn self_token(&self) -> Option<SyntaxToken> {
268 self.name_ref().and_then(|it| it.self_token())
269 }
270
271 pub fn self_type_token(&self) -> Option<SyntaxToken> {
272 self.name_ref().and_then(|it| it.Self_token())
273 }
274
275 pub fn super_token(&self) -> Option<SyntaxToken> {
276 self.name_ref().and_then(|it| it.super_token())
277 }
278
279 pub fn kind(&self) -> Option<PathSegmentKind> {
280 let res = if let Some(name_ref) = self.name_ref() {
281 match name_ref.token_kind() {
282 T![Self] => PathSegmentKind::SelfTypeKw,
283 T![self] => PathSegmentKind::SelfKw,
284 T![super] => PathSegmentKind::SuperKw,
285 T![crate] => PathSegmentKind::CrateKw,
286 _ => PathSegmentKind::Name(name_ref),
287 }
288 } else {
289 let anchor = self.type_anchor()?;
290 let mut type_refs =
294 anchor.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
295 let type_ref = type_refs.next().and_then(ast::Type::cast);
296 let trait_ref = type_refs.next().and_then(ast::PathType::cast);
297 PathSegmentKind::Type { type_ref, trait_ref }
298 };
299 Some(res)
300 }
301}
302
303impl ast::Path {
304 pub fn parent_path(&self) -> Option<ast::Path> {
305 self.syntax().parent().and_then(ast::Path::cast)
306 }
307
308 pub fn as_single_segment(&self) -> Option<ast::PathSegment> {
309 match self.qualifier() {
310 Some(_) => None,
311 None => self.segment(),
312 }
313 }
314
315 pub fn as_single_name_ref(&self) -> Option<ast::NameRef> {
316 match self.qualifier() {
317 Some(_) => None,
318 None => self.segment()?.name_ref(),
319 }
320 }
321
322 pub fn first_qualifier_or_self(&self) -> ast::Path {
323 successors(Some(self.clone()), ast::Path::qualifier).last().unwrap()
324 }
325
326 pub fn first_qualifier(&self) -> Option<ast::Path> {
327 successors(self.qualifier(), ast::Path::qualifier).last()
328 }
329
330 pub fn first_segment(&self) -> Option<ast::PathSegment> {
331 self.first_qualifier_or_self().segment()
332 }
333
334 pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
335 let path_range = self.syntax().text_range();
336 successors(self.first_segment(), move |p| {
337 p.parent_path().parent_path().and_then(|p| {
338 if path_range.contains_range(p.syntax().text_range()) { p.segment() } else { None }
339 })
340 })
341 }
342
343 pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
344 successors(self.qualifier(), |p| p.qualifier())
345 }
346
347 pub fn top_path(&self) -> ast::Path {
348 let mut this = self.clone();
349 while let Some(path) = this.parent_path() {
350 this = path;
351 }
352 this
353 }
354}
355
356impl ast::Use {
357 pub fn is_simple_glob(&self) -> bool {
358 self.use_tree().is_some_and(|use_tree| {
359 use_tree.use_tree_list().is_none() && use_tree.star_token().is_some()
360 })
361 }
362}
363
364impl ast::UseTree {
365 pub fn is_simple_path(&self) -> bool {
366 self.use_tree_list().is_none() && self.star_token().is_none()
367 }
368
369 pub fn parent_use_tree_list(&self) -> Option<ast::UseTreeList> {
370 self.syntax().parent().and_then(ast::UseTreeList::cast)
371 }
372
373 pub fn top_use_tree(&self) -> ast::UseTree {
374 let mut this = self.clone();
375 while let Some(use_tree_list) = this.parent_use_tree_list() {
376 this = use_tree_list.parent_use_tree();
377 }
378 this
379 }
380}
381
382impl ast::UseTreeList {
383 pub fn parent_use_tree(&self) -> ast::UseTree {
384 self.syntax()
385 .parent()
386 .and_then(ast::UseTree::cast)
387 .expect("UseTreeLists are always nested in UseTrees")
388 }
389
390 pub fn has_inner_comment(&self) -> bool {
391 self.syntax()
392 .children_with_tokens()
393 .filter_map(|it| it.into_token())
394 .find_map(ast::Comment::cast)
395 .is_some()
396 }
397
398 pub fn comma(&self) -> impl Iterator<Item = SyntaxToken> {
399 self.syntax()
400 .children_with_tokens()
401 .filter_map(|it| it.into_token().filter(|it| it.kind() == T![,]))
402 }
403
404 pub fn remove_unnecessary_braces(mut self) {
406 let has_single_subtree_that_is_not_self = |u: &ast::UseTreeList| {
409 if let Some((single_subtree,)) = u.use_trees().collect_tuple() {
410 let is_self = single_subtree.path().as_ref().is_some_and(|path| {
413 path.segment().and_then(|seg| seg.self_token()).is_some()
414 && path.qualifier().is_none()
415 });
416
417 !is_self
418 } else {
419 false
421 }
422 };
423
424 let remove_brace_in_use_tree_list = |u: &ast::UseTreeList| {
425 if has_single_subtree_that_is_not_self(u) {
426 if let Some(a) = u.l_curly_token() {
427 ted::remove(a)
428 }
429 if let Some(a) = u.r_curly_token() {
430 ted::remove(a)
431 }
432 u.comma().for_each(ted::remove);
433 }
434 };
435
436 remove_brace_in_use_tree_list(&self);
439
440 while let Some(parent_use_tree_list) = self.parent_use_tree().parent_use_tree_list() {
442 remove_brace_in_use_tree_list(&parent_use_tree_list);
443 self = parent_use_tree_list;
444 }
445 }
446}
447
448impl ast::Impl {
449 pub fn self_ty(&self) -> Option<ast::Type> {
450 match self.target() {
451 (Some(t), None) | (_, Some(t)) => Some(t),
452 _ => None,
453 }
454 }
455
456 pub fn trait_(&self) -> Option<ast::Type> {
457 match self.target() {
458 (Some(t), Some(_)) => Some(t),
459 _ => None,
460 }
461 }
462
463 fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
464 let mut types = support::children(self.syntax());
465 let first = types.next();
466 let second = types.next();
467 (first, second)
468 }
469
470 pub fn for_trait_name_ref(name_ref: &ast::NameRef) -> Option<ast::Impl> {
471 let this = name_ref.syntax().ancestors().find_map(ast::Impl::cast)?;
472 if this.trait_()?.syntax().text_range().start() == name_ref.syntax().text_range().start() {
473 Some(this)
474 } else {
475 None
476 }
477 }
478}
479
480impl ast::PathSegment {
482 pub fn qualifying_trait(&self) -> Option<ast::PathType> {
483 let mut path_types = support::children(self.type_anchor()?.syntax());
484 let first = path_types.next()?;
485 path_types.next().or(Some(first))
486 }
487}
488
489#[derive(Debug, Clone, PartialEq, Eq)]
490pub enum StructKind {
491 Record(ast::RecordFieldList),
492 Tuple(ast::TupleFieldList),
493 Unit,
494}
495
496impl StructKind {
497 fn from_node<N: AstNode>(node: &N) -> StructKind {
498 if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
499 StructKind::Record(nfdl)
500 } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
501 StructKind::Tuple(pfl)
502 } else {
503 StructKind::Unit
504 }
505 }
506}
507
508impl ast::Struct {
509 pub fn kind(&self) -> StructKind {
510 StructKind::from_node(self)
511 }
512}
513
514impl ast::Union {
515 pub fn kind(&self) -> StructKind {
516 StructKind::from_node(self)
517 }
518}
519
520impl ast::RecordExprField {
521 pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
522 let candidate = Self::for_name_ref(field_name)?;
523 if candidate.field_name().as_ref() == Some(field_name) { Some(candidate) } else { None }
524 }
525
526 pub fn for_name_ref(name_ref: &ast::NameRef) -> Option<ast::RecordExprField> {
527 let syn = name_ref.syntax();
528 syn.parent()
529 .and_then(ast::RecordExprField::cast)
530 .or_else(|| syn.ancestors().nth(4).and_then(ast::RecordExprField::cast))
531 }
532
533 pub fn field_name(&self) -> Option<ast::NameRef> {
535 if let Some(name_ref) = self.name_ref() {
536 return Some(name_ref);
537 }
538 if let ast::Expr::PathExpr(expr) = self.expr()? {
539 let path = expr.path()?;
540 let segment = path.segment()?;
541 let name_ref = segment.name_ref()?;
542 if path.qualifier().is_none() {
543 return Some(name_ref);
544 }
545 }
546 None
547 }
548}
549
550#[derive(Debug, Clone)]
551pub enum NameLike {
552 NameRef(ast::NameRef),
553 Name(ast::Name),
554 Lifetime(ast::Lifetime),
555}
556
557impl NameLike {
558 pub fn as_name_ref(&self) -> Option<&ast::NameRef> {
559 match self {
560 NameLike::NameRef(name_ref) => Some(name_ref),
561 _ => None,
562 }
563 }
564 pub fn as_lifetime(&self) -> Option<&ast::Lifetime> {
565 match self {
566 NameLike::Lifetime(lifetime) => Some(lifetime),
567 _ => None,
568 }
569 }
570 pub fn text(&self) -> TokenText<'_> {
571 match self {
572 NameLike::NameRef(name_ref) => name_ref.text(),
573 NameLike::Name(name) => name.text(),
574 NameLike::Lifetime(lifetime) => lifetime.text(),
575 }
576 }
577}
578
579impl ast::AstNode for NameLike {
580 fn can_cast(kind: SyntaxKind) -> bool {
581 matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF | SyntaxKind::LIFETIME)
582 }
583 fn cast(syntax: SyntaxNode) -> Option<Self> {
584 let res = match syntax.kind() {
585 SyntaxKind::NAME => NameLike::Name(ast::Name { syntax }),
586 SyntaxKind::NAME_REF => NameLike::NameRef(ast::NameRef { syntax }),
587 SyntaxKind::LIFETIME => NameLike::Lifetime(ast::Lifetime { syntax }),
588 _ => return None,
589 };
590 Some(res)
591 }
592 fn syntax(&self) -> &SyntaxNode {
593 match self {
594 NameLike::NameRef(it) => it.syntax(),
595 NameLike::Name(it) => it.syntax(),
596 NameLike::Lifetime(it) => it.syntax(),
597 }
598 }
599}
600
601const _: () = {
602 use ast::{Lifetime, Name, NameRef};
603 stdx::impl_from!(NameRef, Name, Lifetime for NameLike);
604};
605
606#[derive(Debug, Clone, PartialEq)]
607pub enum NameOrNameRef {
608 Name(ast::Name),
609 NameRef(ast::NameRef),
610}
611
612impl fmt::Display for NameOrNameRef {
613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
614 match self {
615 NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
616 NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
617 }
618 }
619}
620
621impl ast::AstNode for NameOrNameRef {
622 fn can_cast(kind: SyntaxKind) -> bool {
623 matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF)
624 }
625 fn cast(syntax: SyntaxNode) -> Option<Self> {
626 let res = match syntax.kind() {
627 SyntaxKind::NAME => NameOrNameRef::Name(ast::Name { syntax }),
628 SyntaxKind::NAME_REF => NameOrNameRef::NameRef(ast::NameRef { syntax }),
629 _ => return None,
630 };
631 Some(res)
632 }
633 fn syntax(&self) -> &SyntaxNode {
634 match self {
635 NameOrNameRef::NameRef(it) => it.syntax(),
636 NameOrNameRef::Name(it) => it.syntax(),
637 }
638 }
639}
640
641impl NameOrNameRef {
642 pub fn text(&self) -> TokenText<'_> {
643 match self {
644 NameOrNameRef::Name(name) => name.text(),
645 NameOrNameRef::NameRef(name_ref) => name_ref.text(),
646 }
647 }
648}
649
650impl ast::RecordPatField {
651 pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
652 let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
653 match candidate.field_name()? {
654 NameOrNameRef::NameRef(name_ref) if name_ref == *field_name => Some(candidate),
655 _ => None,
656 }
657 }
658
659 pub fn for_field_name(field_name: &ast::Name) -> Option<ast::RecordPatField> {
660 let candidate =
661 field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?;
662 match candidate.field_name()? {
663 NameOrNameRef::Name(name) if name == *field_name => Some(candidate),
664 _ => None,
665 }
666 }
667
668 pub fn parent_record_pat(&self) -> ast::RecordPat {
669 self.syntax().ancestors().find_map(ast::RecordPat::cast).unwrap()
670 }
671
672 pub fn field_name(&self) -> Option<NameOrNameRef> {
674 if let Some(name_ref) = self.name_ref() {
675 return Some(NameOrNameRef::NameRef(name_ref));
676 }
677 match self.pat() {
678 Some(ast::Pat::IdentPat(pat)) => {
679 let name = pat.name()?;
680 Some(NameOrNameRef::Name(name))
681 }
682 Some(ast::Pat::BoxPat(pat)) => match pat.pat() {
683 Some(ast::Pat::IdentPat(pat)) => {
684 let name = pat.name()?;
685 Some(NameOrNameRef::Name(name))
686 }
687 _ => None,
688 },
689 _ => None,
690 }
691 }
692}
693
694impl ast::Variant {
695 pub fn parent_enum(&self) -> ast::Enum {
696 self.syntax()
697 .parent()
698 .and_then(|it| it.parent())
699 .and_then(ast::Enum::cast)
700 .expect("EnumVariants are always nested in Enums")
701 }
702 pub fn kind(&self) -> StructKind {
703 StructKind::from_node(self)
704 }
705}
706
707impl ast::Item {
708 pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {
709 ast::AnyHasGenericParams::cast(self.syntax().clone())?.generic_param_list()
710 }
711}
712
713impl ast::Type {
714 pub fn generic_arg_list(&self) -> Option<ast::GenericArgList> {
715 if let ast::Type::PathType(path_type) = self {
716 path_type.path()?.segment()?.generic_arg_list()
717 } else {
718 None
719 }
720 }
721}
722
723#[derive(Debug, Clone, PartialEq, Eq)]
724pub enum FieldKind {
725 Name(ast::NameRef),
726 Index(SyntaxToken),
727}
728
729impl ast::FieldExpr {
730 pub fn index_token(&self) -> Option<SyntaxToken> {
731 self.syntax
732 .children_with_tokens()
733 .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
735 .as_ref()
736 .and_then(SyntaxElement::as_token)
737 .cloned()
738 }
739
740 pub fn field_access(&self) -> Option<FieldKind> {
741 match self.name_ref() {
742 Some(nr) => Some(FieldKind::Name(nr)),
743 None => self.index_token().map(FieldKind::Index),
744 }
745 }
746}
747
748pub struct SlicePatComponents {
749 pub prefix: Vec<ast::Pat>,
750 pub slice: Option<ast::Pat>,
751 pub suffix: Vec<ast::Pat>,
752}
753
754impl ast::SlicePat {
755 pub fn components(&self) -> SlicePatComponents {
756 let mut args = self.pats().peekable();
757 let prefix = args
758 .peeking_take_while(|p| match p {
759 ast::Pat::RestPat(_) => false,
760 ast::Pat::IdentPat(bp) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
761 ast::Pat::RefPat(rp) => match rp.pat() {
762 Some(ast::Pat::RestPat(_)) => false,
763 Some(ast::Pat::IdentPat(bp)) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
764 _ => true,
765 },
766 _ => true,
767 })
768 .collect();
769 let slice = args.next();
770 let suffix = args.collect();
771
772 SlicePatComponents { prefix, slice, suffix }
773 }
774}
775
776impl ast::IdentPat {
777 pub fn is_simple_ident(&self) -> bool {
778 self.at_token().is_none()
779 && self.mut_token().is_none()
780 && self.ref_token().is_none()
781 && self.pat().is_none()
782 }
783}
784
785#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
786pub enum SelfParamKind {
787 Owned,
789 Ref,
791 MutRef,
793}
794
795impl ast::SelfParam {
796 pub fn kind(&self) -> SelfParamKind {
797 if self.amp_token().is_some() {
798 if self.mut_token().is_some() { SelfParamKind::MutRef } else { SelfParamKind::Ref }
799 } else {
800 SelfParamKind::Owned
801 }
802 }
803}
804
805#[derive(Clone, Debug, PartialEq, Eq, Hash)]
806pub enum TypeBoundKind {
807 PathType(Option<ast::ForBinder>, ast::PathType),
809 Use(ast::UseBoundGenericArgs),
811 Lifetime(ast::Lifetime),
813}
814
815impl ast::TypeBound {
816 pub fn kind(&self) -> Option<TypeBoundKind> {
817 if let Some(path_type) = support::children(self.syntax()).next() {
818 Some(TypeBoundKind::PathType(self.for_binder(), path_type))
819 } else if let Some(for_binder) = support::children::<ast::ForType>(&self.syntax).next() {
820 let Some(ast::Type::PathType(path_type)) = for_binder.ty() else { return None };
821 Some(TypeBoundKind::PathType(for_binder.for_binder(), path_type))
822 } else if let Some(args) = self.use_bound_generic_args() {
823 Some(TypeBoundKind::Use(args))
824 } else if let Some(lifetime) = self.lifetime() {
825 Some(TypeBoundKind::Lifetime(lifetime))
826 } else {
827 unreachable!()
828 }
829 }
830}
831
832#[derive(Debug, Clone)]
833pub enum TypeOrConstParam {
834 Type(ast::TypeParam),
835 Const(ast::ConstParam),
836}
837
838impl From<TypeOrConstParam> for GenericParam {
839 fn from(value: TypeOrConstParam) -> Self {
840 match value {
841 TypeOrConstParam::Type(it) => GenericParam::TypeParam(it),
842 TypeOrConstParam::Const(it) => GenericParam::ConstParam(it),
843 }
844 }
845}
846
847impl TypeOrConstParam {
848 pub fn name(&self) -> Option<ast::Name> {
849 match self {
850 TypeOrConstParam::Type(x) => x.name(),
851 TypeOrConstParam::Const(x) => x.name(),
852 }
853 }
854}
855
856impl AstNode for TypeOrConstParam {
857 fn can_cast(kind: SyntaxKind) -> bool
858 where
859 Self: Sized,
860 {
861 matches!(kind, SyntaxKind::TYPE_PARAM | SyntaxKind::CONST_PARAM)
862 }
863
864 fn cast(syntax: SyntaxNode) -> Option<Self>
865 where
866 Self: Sized,
867 {
868 let res = match syntax.kind() {
869 SyntaxKind::TYPE_PARAM => TypeOrConstParam::Type(ast::TypeParam { syntax }),
870 SyntaxKind::CONST_PARAM => TypeOrConstParam::Const(ast::ConstParam { syntax }),
871 _ => return None,
872 };
873 Some(res)
874 }
875
876 fn syntax(&self) -> &SyntaxNode {
877 match self {
878 TypeOrConstParam::Type(it) => it.syntax(),
879 TypeOrConstParam::Const(it) => it.syntax(),
880 }
881 }
882}
883
884impl HasAttrs for TypeOrConstParam {}
885
886pub enum VisibilityKind {
887 In(ast::Path),
888 PubCrate,
889 PubSuper,
890 PubSelf,
891 Pub,
892}
893
894impl ast::Visibility {
895 pub fn kind(&self) -> VisibilityKind {
896 match self.path() {
897 Some(path) => {
898 if let Some(segment) =
899 path.as_single_segment().filter(|it| it.coloncolon_token().is_none())
900 {
901 if segment.crate_token().is_some() {
902 return VisibilityKind::PubCrate;
903 } else if segment.super_token().is_some() {
904 return VisibilityKind::PubSuper;
905 } else if segment.self_token().is_some() {
906 return VisibilityKind::PubSelf;
907 }
908 }
909 VisibilityKind::In(path)
910 }
911 None => VisibilityKind::Pub,
912 }
913 }
914}
915
916impl ast::LifetimeParam {
917 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
918 self.type_bound_list()
919 .into_iter()
920 .flat_map(|it| it.bounds())
921 .filter_map(|it| it.lifetime()?.lifetime_ident_token())
922 }
923}
924
925impl ast::Module {
926 pub fn parent(&self) -> Option<ast::Module> {
929 self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
930 }
931}
932
933impl RangeItem for ast::RangePat {
934 type Bound = ast::Pat;
935
936 fn start(&self) -> Option<ast::Pat> {
937 self.syntax()
938 .children_with_tokens()
939 .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
940 .filter_map(|it| it.into_node())
941 .find_map(ast::Pat::cast)
942 }
943
944 fn end(&self) -> Option<ast::Pat> {
945 self.syntax()
946 .children_with_tokens()
947 .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
948 .filter_map(|it| it.into_node())
949 .find_map(ast::Pat::cast)
950 }
951
952 fn op_token(&self) -> Option<SyntaxToken> {
953 self.syntax().children_with_tokens().find_map(|it| {
954 let token = it.into_token()?;
955
956 match token.kind() {
957 T![..] => Some(token),
958 T![..=] => Some(token),
959 _ => None,
960 }
961 })
962 }
963
964 fn op_kind(&self) -> Option<RangeOp> {
965 self.syntax().children_with_tokens().find_map(|it| {
966 let token = it.into_token()?;
967
968 match token.kind() {
969 T![..] => Some(RangeOp::Exclusive),
970 T![..=] => Some(RangeOp::Inclusive),
971 _ => None,
972 }
973 })
974 }
975}
976
977impl ast::TokenTree {
978 pub fn token_trees_and_tokens(
979 &self,
980 ) -> impl Iterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>> {
981 self.syntax().children_with_tokens().filter_map(|not| match not {
982 NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
983 NodeOrToken::Token(t) => Some(NodeOrToken::Token(t)),
984 })
985 }
986
987 pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
988 self.syntax()
989 .first_child_or_token()?
990 .into_token()
991 .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
992 }
993
994 pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
995 self.syntax()
996 .last_child_or_token()?
997 .into_token()
998 .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
999 }
1000
1001 pub fn parent_meta(&self) -> Option<ast::Meta> {
1002 self.syntax().parent().and_then(ast::Meta::cast)
1003 }
1004}
1005
1006impl ast::Meta {
1007 pub fn parent_attr(&self) -> Option<ast::Attr> {
1008 self.syntax().parent().and_then(ast::Attr::cast)
1009 }
1010}
1011
1012impl ast::GenericArgList {
1013 pub fn lifetime_args(&self) -> impl Iterator<Item = ast::LifetimeArg> {
1014 self.generic_args().filter_map(|arg| match arg {
1015 ast::GenericArg::LifetimeArg(it) => Some(it),
1016 _ => None,
1017 })
1018 }
1019}
1020
1021impl ast::GenericParamList {
1022 pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
1023 self.generic_params().filter_map(|param| match param {
1024 ast::GenericParam::LifetimeParam(it) => Some(it),
1025 ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
1026 })
1027 }
1028 pub fn type_or_const_params(&self) -> impl Iterator<Item = ast::TypeOrConstParam> + use<> {
1029 self.generic_params().filter_map(|param| match param {
1030 ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)),
1031 ast::GenericParam::LifetimeParam(_) => None,
1032 ast::GenericParam::ConstParam(it) => Some(ast::TypeOrConstParam::Const(it)),
1033 })
1034 }
1035}
1036
1037impl ast::ForExpr {
1038 pub fn iterable(&self) -> Option<ast::Expr> {
1039 let mut exprs = support::children(self.syntax());
1042 let first = exprs.next();
1043 match first {
1044 Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
1045 first => first,
1046 }
1047 }
1048}
1049
1050impl ast::HasLoopBody for ast::ForExpr {
1051 fn loop_body(&self) -> Option<ast::BlockExpr> {
1052 let mut exprs = support::children(self.syntax());
1053 let first = exprs.next();
1054 let second = exprs.next();
1055 second.or(first)
1056 }
1057}
1058
1059impl ast::WhileExpr {
1060 pub fn condition(&self) -> Option<ast::Expr> {
1061 let mut exprs = support::children(self.syntax());
1064 let first = exprs.next();
1065 match first {
1066 Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
1067 first => first,
1068 }
1069 }
1070}
1071
1072impl ast::HasLoopBody for ast::WhileExpr {
1073 fn loop_body(&self) -> Option<ast::BlockExpr> {
1074 let mut exprs = support::children(self.syntax());
1075 let first = exprs.next();
1076 let second = exprs.next();
1077 second.or(first)
1078 }
1079}
1080
1081impl ast::HasAttrs for ast::AnyHasDocComments {}
1082
1083impl From<ast::Adt> for ast::Item {
1084 fn from(it: ast::Adt) -> Self {
1085 match it {
1086 ast::Adt::Enum(it) => ast::Item::Enum(it),
1087 ast::Adt::Struct(it) => ast::Item::Struct(it),
1088 ast::Adt::Union(it) => ast::Item::Union(it),
1089 }
1090 }
1091}
1092
1093impl ast::MatchGuard {
1094 pub fn condition(&self) -> Option<ast::Expr> {
1095 support::child(&self.syntax)
1096 }
1097}
1098
1099impl From<ast::Item> for ast::AnyHasAttrs {
1100 fn from(node: ast::Item) -> Self {
1101 Self::new(node)
1102 }
1103}
1104
1105impl From<ast::AssocItem> for ast::AnyHasAttrs {
1106 fn from(node: ast::AssocItem) -> Self {
1107 Self::new(node)
1108 }
1109}
1110
1111impl ast::OrPat {
1112 pub fn leading_pipe(&self) -> Option<SyntaxToken> {
1113 self.syntax
1114 .children_with_tokens()
1115 .find(|it| !it.kind().is_trivia())
1116 .and_then(NodeOrToken::into_token)
1117 .filter(|it| it.kind() == T![|])
1118 }
1119}
1120
1121#[derive(Clone)]
1125pub struct TokenTreeChildren {
1126 iter: SyntaxElementChildren,
1127}
1128
1129impl TokenTreeChildren {
1130 #[inline]
1131 pub fn new(tt: &ast::TokenTree) -> Self {
1132 let mut iter = tt.syntax.children_with_tokens();
1133 iter.next(); Self { iter }
1135 }
1136}
1137
1138impl Iterator for TokenTreeChildren {
1139 type Item = NodeOrToken<ast::TokenTree, SyntaxToken>;
1140
1141 #[inline]
1142 fn next(&mut self) -> Option<Self::Item> {
1143 self.iter.find_map(|item| match item {
1144 NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
1145 NodeOrToken::Token(token) => {
1146 let kind = token.kind();
1147 (!matches!(
1148 kind,
1149 SyntaxKind::WHITESPACE | SyntaxKind::COMMENT | T![')'] | T![']'] | T!['}']
1150 ))
1151 .then_some(NodeOrToken::Token(token))
1152 }
1153 })
1154 }
1155}