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