ra_ap_syntax/ast/
node_ext.rs

1//! Various extension methods to ast Nodes, which are hard to code-generate.
2//! Extensions for various expressions live in a sibling `expr_extensions` module.
3//!
4//! These methods should only do simple, shallow tasks related to the syntax of the node itself.
5
6use 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    // FIXME: remove all these methods, they belong to ast::StmtList
69    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    /// Block expressions accept outer and inner attributes, but only when they are the outer
76    /// expression of an expression statement or the final expression of another block expression.
77    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    /// Returns `true` if the attr_kind is [`Inner`](Self::Inner).
164    pub fn is_inner(&self) -> bool {
165        matches!(self, Self::Inner)
166    }
167
168    /// Returns `true` if the attr_kind is [`Outer`](Self::Outer).
169    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                    // <T> or <T as Trait>
271                    // T is any TypeRef, Trait has to be a PathType
272                    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    /// Remove the unnecessary braces in current `UseTreeList`
391    pub fn remove_unnecessary_braces(mut self) {
392        // Returns true iff there is a single subtree and it is not the self keyword. The braces in
393        // `use x::{self};` are necessary and so we should not remove them.
394        let has_single_subtree_that_is_not_self = |u: &ast::UseTreeList| {
395            if let Some((single_subtree,)) = u.use_trees().collect_tuple() {
396                // We have a single subtree, check whether it is self.
397
398                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                // Not a single subtree
406                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        // take `use crate::{{{{A}}}}` for example
423        // the below remove the innermost {}, got `use crate::{{{A}}}`
424        remove_brace_in_use_tree_list(&self);
425
426        // the below remove other unnecessary {}, got `use crate::A`
427        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
466// [#15778](https://github.com/rust-lang/rust-analyzer/issues/15778)
467impl 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    /// Deals with field init shorthand
524    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    /// Deals with field init shorthand
663    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            // FIXME: Accepting floats here to reject them in validation later
724            .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    /// self
778    Owned,
779    /// &self
780    Ref,
781    /// &mut self
782    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    /// Trait
802    PathType(ast::PathType),
803    /// for<'a> ...
804    ForType(ast::ForType),
805    /// use
806    Use(ast::UseBoundGenericArgs),
807    /// 'a
808    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    /// Returns the parent ast::Module, this is different than the semantic parent in that this only
968    /// considers parent declarations in the AST
969    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        // If the iterable is a BlockExpr, check if the body is missing.
1081        // If it is assume the iterable is the expression that is missing instead.
1082        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        // If the condition is a BlockExpr, check if the body is missing.
1103        // If it is assume the condition is the expression that is missing instead.
1104        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}