]> git.lizzy.rs Git - rust.git/blob - crates/syntax/src/ast/node_ext.rs
parameters.split_last()
[rust.git] / crates / syntax / src / 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
6 use std::{borrow::Cow, fmt, iter::successors};
7
8 use itertools::Itertools;
9 use parser::SyntaxKind;
10 use rowan::{GreenNodeData, GreenTokenData};
11
12 use crate::{
13     ast::{self, support, AstNode, AstToken, HasAttrs, HasGenericParams, HasName, SyntaxNode},
14     NodeOrToken, SmolStr, SyntaxElement, SyntaxToken, TokenText, T,
15 };
16
17 impl ast::Lifetime {
18     pub fn text(&self) -> TokenText<'_> {
19         text_of_first_token(self.syntax())
20     }
21 }
22
23 impl ast::Name {
24     pub fn text(&self) -> TokenText<'_> {
25         text_of_first_token(self.syntax())
26     }
27 }
28
29 impl ast::NameRef {
30     pub fn text(&self) -> TokenText<'_> {
31         text_of_first_token(self.syntax())
32     }
33
34     pub fn as_tuple_field(&self) -> Option<usize> {
35         self.text().parse().ok()
36     }
37 }
38
39 fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
40     fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
41         green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
42     }
43
44     match node.green() {
45         Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
46         Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
47     }
48 }
49
50 impl ast::HasModuleItem for ast::StmtList {}
51
52 impl ast::BlockExpr {
53     // FIXME: remove all these methods, they belong to ast::StmtList
54     pub fn statements(&self) -> impl Iterator<Item = ast::Stmt> {
55         self.stmt_list().into_iter().flat_map(|it| it.statements())
56     }
57     pub fn tail_expr(&self) -> Option<ast::Expr> {
58         self.stmt_list()?.tail_expr()
59     }
60 }
61
62 #[derive(Debug, PartialEq, Eq, Clone)]
63 pub enum Macro {
64     MacroRules(ast::MacroRules),
65     MacroDef(ast::MacroDef),
66 }
67
68 impl From<ast::MacroRules> for Macro {
69     fn from(it: ast::MacroRules) -> Self {
70         Macro::MacroRules(it)
71     }
72 }
73
74 impl From<ast::MacroDef> for Macro {
75     fn from(it: ast::MacroDef) -> Self {
76         Macro::MacroDef(it)
77     }
78 }
79
80 impl AstNode for Macro {
81     fn can_cast(kind: SyntaxKind) -> bool {
82         matches!(kind, SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF)
83     }
84     fn cast(syntax: SyntaxNode) -> Option<Self> {
85         let res = match syntax.kind() {
86             SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }),
87             SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }),
88             _ => return None,
89         };
90         Some(res)
91     }
92     fn syntax(&self) -> &SyntaxNode {
93         match self {
94             Macro::MacroRules(it) => it.syntax(),
95             Macro::MacroDef(it) => it.syntax(),
96         }
97     }
98 }
99
100 impl HasName for Macro {
101     fn name(&self) -> Option<ast::Name> {
102         match self {
103             Macro::MacroRules(mac) => mac.name(),
104             Macro::MacroDef(mac) => mac.name(),
105         }
106     }
107 }
108
109 impl HasAttrs for Macro {}
110
111 impl From<ast::AssocItem> for ast::Item {
112     fn from(assoc: ast::AssocItem) -> Self {
113         match assoc {
114             ast::AssocItem::Const(it) => ast::Item::Const(it),
115             ast::AssocItem::Fn(it) => ast::Item::Fn(it),
116             ast::AssocItem::MacroCall(it) => ast::Item::MacroCall(it),
117             ast::AssocItem::TypeAlias(it) => ast::Item::TypeAlias(it),
118         }
119     }
120 }
121
122 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
123 pub enum AttrKind {
124     Inner,
125     Outer,
126 }
127
128 impl AttrKind {
129     /// Returns `true` if the attr_kind is [`Inner`](Self::Inner).
130     pub fn is_inner(&self) -> bool {
131         matches!(self, Self::Inner)
132     }
133
134     /// Returns `true` if the attr_kind is [`Outer`](Self::Outer).
135     pub fn is_outer(&self) -> bool {
136         matches!(self, Self::Outer)
137     }
138 }
139
140 impl ast::Attr {
141     pub fn as_simple_atom(&self) -> Option<SmolStr> {
142         let meta = self.meta()?;
143         if meta.eq_token().is_some() || meta.token_tree().is_some() {
144             return None;
145         }
146         self.simple_name()
147     }
148
149     pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
150         let tt = self.meta()?.token_tree()?;
151         Some((self.simple_name()?, tt))
152     }
153
154     pub fn simple_name(&self) -> Option<SmolStr> {
155         let path = self.meta()?.path()?;
156         match (path.segment(), path.qualifier()) {
157             (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()),
158             _ => None,
159         }
160     }
161
162     pub fn kind(&self) -> AttrKind {
163         match self.excl_token() {
164             Some(_) => AttrKind::Inner,
165             None => AttrKind::Outer,
166         }
167     }
168
169     pub fn path(&self) -> Option<ast::Path> {
170         self.meta()?.path()
171     }
172
173     pub fn expr(&self) -> Option<ast::Expr> {
174         self.meta()?.expr()
175     }
176
177     pub fn token_tree(&self) -> Option<ast::TokenTree> {
178         self.meta()?.token_tree()
179     }
180 }
181
182 #[derive(Debug, Clone, PartialEq, Eq)]
183 pub enum PathSegmentKind {
184     Name(ast::NameRef),
185     Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
186     SelfKw,
187     SuperKw,
188     CrateKw,
189 }
190
191 impl ast::PathSegment {
192     pub fn parent_path(&self) -> ast::Path {
193         self.syntax()
194             .parent()
195             .and_then(ast::Path::cast)
196             .expect("segments are always nested in paths")
197     }
198
199     pub fn crate_token(&self) -> Option<SyntaxToken> {
200         self.name_ref().and_then(|it| it.crate_token())
201     }
202
203     pub fn self_token(&self) -> Option<SyntaxToken> {
204         self.name_ref().and_then(|it| it.self_token())
205     }
206
207     pub fn super_token(&self) -> Option<SyntaxToken> {
208         self.name_ref().and_then(|it| it.super_token())
209     }
210
211     pub fn kind(&self) -> Option<PathSegmentKind> {
212         let res = if let Some(name_ref) = self.name_ref() {
213             match name_ref.syntax().first_token().map(|it| it.kind()) {
214                 Some(T![self]) => PathSegmentKind::SelfKw,
215                 Some(T![super]) => PathSegmentKind::SuperKw,
216                 Some(T![crate]) => PathSegmentKind::CrateKw,
217                 _ => PathSegmentKind::Name(name_ref),
218             }
219         } else {
220             match self.syntax().first_child_or_token()?.kind() {
221                 T![<] => {
222                     // <T> or <T as Trait>
223                     // T is any TypeRef, Trait has to be a PathType
224                     let mut type_refs =
225                         self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
226                     let type_ref = type_refs.next().and_then(ast::Type::cast);
227                     let trait_ref = type_refs.next().and_then(ast::PathType::cast);
228                     PathSegmentKind::Type { type_ref, trait_ref }
229                 }
230                 _ => return None,
231             }
232         };
233         Some(res)
234     }
235 }
236
237 impl ast::Path {
238     pub fn parent_path(&self) -> Option<ast::Path> {
239         self.syntax().parent().and_then(ast::Path::cast)
240     }
241
242     pub fn as_single_segment(&self) -> Option<ast::PathSegment> {
243         match self.qualifier() {
244             Some(_) => None,
245             None => self.segment(),
246         }
247     }
248
249     pub fn as_single_name_ref(&self) -> Option<ast::NameRef> {
250         match self.qualifier() {
251             Some(_) => None,
252             None => self.segment()?.name_ref(),
253         }
254     }
255
256     pub fn first_qualifier_or_self(&self) -> ast::Path {
257         successors(Some(self.clone()), ast::Path::qualifier).last().unwrap()
258     }
259
260     pub fn first_segment(&self) -> Option<ast::PathSegment> {
261         self.first_qualifier_or_self().segment()
262     }
263
264     pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
265         successors(self.first_segment(), |p| {
266             p.parent_path().parent_path().and_then(|p| p.segment())
267         })
268     }
269
270     pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
271         successors(self.qualifier(), |p| p.qualifier())
272     }
273
274     pub fn top_path(&self) -> ast::Path {
275         let mut this = self.clone();
276         while let Some(path) = this.parent_path() {
277             this = path;
278         }
279         this
280     }
281 }
282
283 impl ast::Use {
284     pub fn is_simple_glob(&self) -> bool {
285         self.use_tree().map_or(false, |use_tree| {
286             use_tree.use_tree_list().is_none() && use_tree.star_token().is_some()
287         })
288     }
289 }
290
291 impl ast::UseTree {
292     pub fn is_simple_path(&self) -> bool {
293         self.use_tree_list().is_none() && self.star_token().is_none()
294     }
295 }
296
297 impl ast::UseTreeList {
298     pub fn parent_use_tree(&self) -> ast::UseTree {
299         self.syntax()
300             .parent()
301             .and_then(ast::UseTree::cast)
302             .expect("UseTreeLists are always nested in UseTrees")
303     }
304
305     pub fn has_inner_comment(&self) -> bool {
306         self.syntax()
307             .children_with_tokens()
308             .filter_map(|it| it.into_token())
309             .find_map(ast::Comment::cast)
310             .is_some()
311     }
312 }
313
314 impl ast::Impl {
315     pub fn self_ty(&self) -> Option<ast::Type> {
316         match self.target() {
317             (Some(t), None) | (_, Some(t)) => Some(t),
318             _ => None,
319         }
320     }
321
322     pub fn trait_(&self) -> Option<ast::Type> {
323         match self.target() {
324             (Some(t), Some(_)) => Some(t),
325             _ => None,
326         }
327     }
328
329     fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
330         let mut types = support::children(self.syntax());
331         let first = types.next();
332         let second = types.next();
333         (first, second)
334     }
335
336     pub fn for_trait_name_ref(name_ref: &ast::NameRef) -> Option<ast::Impl> {
337         let this = name_ref.syntax().ancestors().find_map(ast::Impl::cast)?;
338         if this.trait_()?.syntax().text_range().start() == name_ref.syntax().text_range().start() {
339             Some(this)
340         } else {
341             None
342         }
343     }
344 }
345
346 #[derive(Debug, Clone, PartialEq, Eq)]
347 pub enum StructKind {
348     Record(ast::RecordFieldList),
349     Tuple(ast::TupleFieldList),
350     Unit,
351 }
352
353 impl StructKind {
354     fn from_node<N: AstNode>(node: &N) -> StructKind {
355         if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
356             StructKind::Record(nfdl)
357         } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
358             StructKind::Tuple(pfl)
359         } else {
360             StructKind::Unit
361         }
362     }
363 }
364
365 impl ast::Struct {
366     pub fn kind(&self) -> StructKind {
367         StructKind::from_node(self)
368     }
369 }
370
371 impl ast::RecordExprField {
372     pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
373         let candidate = Self::for_name_ref(field_name)?;
374         if candidate.field_name().as_ref() == Some(field_name) {
375             Some(candidate)
376         } else {
377             None
378         }
379     }
380
381     pub fn for_name_ref(name_ref: &ast::NameRef) -> Option<ast::RecordExprField> {
382         let syn = name_ref.syntax();
383         syn.parent()
384             .and_then(ast::RecordExprField::cast)
385             .or_else(|| syn.ancestors().nth(4).and_then(ast::RecordExprField::cast))
386     }
387
388     /// Deals with field init shorthand
389     pub fn field_name(&self) -> Option<ast::NameRef> {
390         if let Some(name_ref) = self.name_ref() {
391             return Some(name_ref);
392         }
393         if let ast::Expr::PathExpr(expr) = self.expr()? {
394             let path = expr.path()?;
395             let segment = path.segment()?;
396             let name_ref = segment.name_ref()?;
397             if path.qualifier().is_none() {
398                 return Some(name_ref);
399             }
400         }
401         None
402     }
403 }
404
405 #[derive(Debug, Clone)]
406 pub enum NameLike {
407     NameRef(ast::NameRef),
408     Name(ast::Name),
409     Lifetime(ast::Lifetime),
410 }
411
412 impl NameLike {
413     pub fn as_name_ref(&self) -> Option<&ast::NameRef> {
414         match self {
415             NameLike::NameRef(name_ref) => Some(name_ref),
416             _ => None,
417         }
418     }
419 }
420
421 impl ast::AstNode for NameLike {
422     fn can_cast(kind: SyntaxKind) -> bool {
423         matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF | SyntaxKind::LIFETIME)
424     }
425     fn cast(syntax: SyntaxNode) -> Option<Self> {
426         let res = match syntax.kind() {
427             SyntaxKind::NAME => NameLike::Name(ast::Name { syntax }),
428             SyntaxKind::NAME_REF => NameLike::NameRef(ast::NameRef { syntax }),
429             SyntaxKind::LIFETIME => NameLike::Lifetime(ast::Lifetime { syntax }),
430             _ => return None,
431         };
432         Some(res)
433     }
434     fn syntax(&self) -> &SyntaxNode {
435         match self {
436             NameLike::NameRef(it) => it.syntax(),
437             NameLike::Name(it) => it.syntax(),
438             NameLike::Lifetime(it) => it.syntax(),
439         }
440     }
441 }
442
443 const _: () = {
444     use ast::{Lifetime, Name, NameRef};
445     stdx::impl_from!(NameRef, Name, Lifetime for NameLike);
446 };
447
448 #[derive(Debug, Clone, PartialEq)]
449 pub enum NameOrNameRef {
450     Name(ast::Name),
451     NameRef(ast::NameRef),
452 }
453
454 impl fmt::Display for NameOrNameRef {
455     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
456         match self {
457             NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
458             NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
459         }
460     }
461 }
462
463 impl NameOrNameRef {
464     pub fn text(&self) -> TokenText<'_> {
465         match self {
466             NameOrNameRef::Name(name) => name.text(),
467             NameOrNameRef::NameRef(name_ref) => name_ref.text(),
468         }
469     }
470 }
471
472 impl ast::RecordPatField {
473     pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
474         let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
475         match candidate.field_name()? {
476             NameOrNameRef::NameRef(name_ref) if name_ref == *field_name => Some(candidate),
477             _ => None,
478         }
479     }
480
481     pub fn for_field_name(field_name: &ast::Name) -> Option<ast::RecordPatField> {
482         let candidate =
483             field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?;
484         match candidate.field_name()? {
485             NameOrNameRef::Name(name) if name == *field_name => Some(candidate),
486             _ => None,
487         }
488     }
489
490     /// Deals with field init shorthand
491     pub fn field_name(&self) -> Option<NameOrNameRef> {
492         if let Some(name_ref) = self.name_ref() {
493             return Some(NameOrNameRef::NameRef(name_ref));
494         }
495         match self.pat() {
496             Some(ast::Pat::IdentPat(pat)) => {
497                 let name = pat.name()?;
498                 Some(NameOrNameRef::Name(name))
499             }
500             Some(ast::Pat::BoxPat(pat)) => match pat.pat() {
501                 Some(ast::Pat::IdentPat(pat)) => {
502                     let name = pat.name()?;
503                     Some(NameOrNameRef::Name(name))
504                 }
505                 _ => None,
506             },
507             _ => None,
508         }
509     }
510 }
511
512 impl ast::Variant {
513     pub fn parent_enum(&self) -> ast::Enum {
514         self.syntax()
515             .parent()
516             .and_then(|it| it.parent())
517             .and_then(ast::Enum::cast)
518             .expect("EnumVariants are always nested in Enums")
519     }
520     pub fn kind(&self) -> StructKind {
521         StructKind::from_node(self)
522     }
523 }
524
525 impl ast::Item {
526     pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {
527         ast::AnyHasGenericParams::cast(self.syntax().clone())?.generic_param_list()
528     }
529 }
530
531 impl ast::Condition {
532     pub fn is_pattern_cond(&self) -> bool {
533         self.let_token().is_some()
534     }
535 }
536
537 #[derive(Debug, Clone, PartialEq, Eq)]
538 pub enum FieldKind {
539     Name(ast::NameRef),
540     Index(SyntaxToken),
541 }
542
543 impl ast::FieldExpr {
544     pub fn index_token(&self) -> Option<SyntaxToken> {
545         self.syntax
546             .children_with_tokens()
547             // FIXME: Accepting floats here to reject them in validation later
548             .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
549             .as_ref()
550             .and_then(SyntaxElement::as_token)
551             .cloned()
552     }
553
554     pub fn field_access(&self) -> Option<FieldKind> {
555         match self.name_ref() {
556             Some(nr) => Some(FieldKind::Name(nr)),
557             None => self.index_token().map(FieldKind::Index),
558         }
559     }
560 }
561
562 pub struct SlicePatComponents {
563     pub prefix: Vec<ast::Pat>,
564     pub slice: Option<ast::Pat>,
565     pub suffix: Vec<ast::Pat>,
566 }
567
568 impl ast::SlicePat {
569     pub fn components(&self) -> SlicePatComponents {
570         let mut args = self.pats().peekable();
571         let prefix = args
572             .peeking_take_while(|p| match p {
573                 ast::Pat::RestPat(_) => false,
574                 ast::Pat::IdentPat(bp) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
575                 ast::Pat::RefPat(rp) => match rp.pat() {
576                     Some(ast::Pat::RestPat(_)) => false,
577                     Some(ast::Pat::IdentPat(bp)) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
578                     _ => true,
579                 },
580                 _ => true,
581             })
582             .collect();
583         let slice = args.next();
584         let suffix = args.collect();
585
586         SlicePatComponents { prefix, slice, suffix }
587     }
588 }
589
590 impl ast::IdentPat {
591     pub fn is_simple_ident(&self) -> bool {
592         self.at_token().is_none()
593             && self.mut_token().is_none()
594             && self.ref_token().is_none()
595             && self.pat().is_none()
596     }
597 }
598
599 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
600 pub enum SelfParamKind {
601     /// self
602     Owned,
603     /// &self
604     Ref,
605     /// &mut self
606     MutRef,
607 }
608
609 impl ast::SelfParam {
610     pub fn kind(&self) -> SelfParamKind {
611         if self.amp_token().is_some() {
612             if self.mut_token().is_some() {
613                 SelfParamKind::MutRef
614             } else {
615                 SelfParamKind::Ref
616             }
617         } else {
618             SelfParamKind::Owned
619         }
620     }
621 }
622
623 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
624 pub enum TypeBoundKind {
625     /// Trait
626     PathType(ast::PathType),
627     /// for<'a> ...
628     ForType(ast::ForType),
629     /// 'a
630     Lifetime(ast::Lifetime),
631 }
632
633 impl ast::TypeBound {
634     pub fn kind(&self) -> TypeBoundKind {
635         if let Some(path_type) = support::children(self.syntax()).next() {
636             TypeBoundKind::PathType(path_type)
637         } else if let Some(for_type) = support::children(self.syntax()).next() {
638             TypeBoundKind::ForType(for_type)
639         } else if let Some(lifetime) = self.lifetime() {
640             TypeBoundKind::Lifetime(lifetime)
641         } else {
642             unreachable!()
643         }
644     }
645 }
646
647 pub enum VisibilityKind {
648     In(ast::Path),
649     PubCrate,
650     PubSuper,
651     PubSelf,
652     Pub,
653 }
654
655 impl ast::Visibility {
656     pub fn kind(&self) -> VisibilityKind {
657         match self.path() {
658             Some(path) => {
659                 if let Some(segment) =
660                     path.as_single_segment().filter(|it| it.coloncolon_token().is_none())
661                 {
662                     if segment.crate_token().is_some() {
663                         return VisibilityKind::PubCrate;
664                     } else if segment.super_token().is_some() {
665                         return VisibilityKind::PubSuper;
666                     } else if segment.self_token().is_some() {
667                         return VisibilityKind::PubSelf;
668                     }
669                 }
670                 VisibilityKind::In(path)
671             }
672             None => VisibilityKind::Pub,
673         }
674     }
675 }
676
677 impl ast::LifetimeParam {
678     pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
679         self.syntax()
680             .children_with_tokens()
681             .filter_map(|it| it.into_token())
682             .skip_while(|x| x.kind() != T![:])
683             .filter(|it| it.kind() == T![lifetime_ident])
684     }
685 }
686
687 impl ast::Module {
688     /// Returns the parent ast::Module, this is different than the semantic parent in that this only
689     /// considers parent declarations in the AST
690     pub fn parent(&self) -> Option<ast::Module> {
691         self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
692     }
693 }
694
695 impl ast::RangePat {
696     pub fn start(&self) -> Option<ast::Pat> {
697         self.syntax()
698             .children_with_tokens()
699             .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
700             .filter_map(|it| it.into_node())
701             .find_map(ast::Pat::cast)
702     }
703
704     pub fn end(&self) -> Option<ast::Pat> {
705         self.syntax()
706             .children_with_tokens()
707             .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
708             .filter_map(|it| it.into_node())
709             .find_map(ast::Pat::cast)
710     }
711 }
712
713 impl ast::TokenTree {
714     pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
715         self.syntax()
716             .first_child_or_token()?
717             .into_token()
718             .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
719     }
720
721     pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
722         self.syntax()
723             .last_child_or_token()?
724             .into_token()
725             .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
726     }
727
728     pub fn parent_meta(&self) -> Option<ast::Meta> {
729         self.syntax().parent().and_then(ast::Meta::cast)
730     }
731 }
732
733 impl ast::Meta {
734     pub fn parent_attr(&self) -> Option<ast::Attr> {
735         self.syntax().parent().and_then(ast::Attr::cast)
736     }
737 }
738
739 impl ast::GenericParamList {
740     pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
741         self.generic_params().filter_map(|param| match param {
742             ast::GenericParam::LifetimeParam(it) => Some(it),
743             ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
744         })
745     }
746     pub fn type_params(&self) -> impl Iterator<Item = ast::TypeParam> {
747         self.generic_params().filter_map(|param| match param {
748             ast::GenericParam::TypeParam(it) => Some(it),
749             ast::GenericParam::LifetimeParam(_) | ast::GenericParam::ConstParam(_) => None,
750         })
751     }
752     pub fn const_params(&self) -> impl Iterator<Item = ast::ConstParam> {
753         self.generic_params().filter_map(|param| match param {
754             ast::GenericParam::ConstParam(it) => Some(it),
755             ast::GenericParam::TypeParam(_) | ast::GenericParam::LifetimeParam(_) => None,
756         })
757     }
758 }
759
760 impl ast::HasLoopBody for ast::ForExpr {
761     fn loop_body(&self) -> Option<ast::BlockExpr> {
762         let mut exprs = support::children(self.syntax());
763         let first = exprs.next();
764         let second = exprs.next();
765         second.or(first)
766     }
767 }
768
769 impl ast::HasAttrs for ast::AnyHasDocComments {}
770
771 impl From<ast::Adt> for ast::Item {
772     fn from(it: ast::Adt) -> Self {
773         match it {
774             ast::Adt::Enum(it) => ast::Item::Enum(it),
775             ast::Adt::Struct(it) => ast::Item::Struct(it),
776             ast::Adt::Union(it) => ast::Item::Union(it),
777         }
778     }
779 }