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 {
text(&self) -> TokenText<'_>18 pub fn text(&self) -> TokenText<'_> {
19 text_of_first_token(self.syntax())
20 }
21 }
22
23 impl ast::Name {
text(&self) -> TokenText<'_>24 pub fn text(&self) -> TokenText<'_> {
25 text_of_first_token(self.syntax())
26 }
27 }
28
29 impl ast::NameRef {
text(&self) -> TokenText<'_>30 pub fn text(&self) -> TokenText<'_> {
31 text_of_first_token(self.syntax())
32 }
33
as_tuple_field(&self) -> Option<usize>34 pub fn as_tuple_field(&self) -> Option<usize> {
35 self.text().parse().ok()
36 }
37
token_kind(&self) -> SyntaxKind38 pub fn token_kind(&self) -> SyntaxKind {
39 self.syntax().first_token().map_or(SyntaxKind::ERROR, |it| it.kind())
40 }
41 }
42
text_of_first_token(node: &SyntaxNode) -> TokenText<'_>43 fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
44 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
45 green_ref.children().next().and_then(NodeOrToken::into_token).unwrap()
46 }
47
48 match node.green() {
49 Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
50 Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
51 }
52 }
53
54 impl ast::HasModuleItem for ast::StmtList {}
55
56 impl ast::BlockExpr {
57 // FIXME: remove all these methods, they belong to ast::StmtList
statements(&self) -> impl Iterator<Item = ast::Stmt>58 pub fn statements(&self) -> impl Iterator<Item = ast::Stmt> {
59 self.stmt_list().into_iter().flat_map(|it| it.statements())
60 }
tail_expr(&self) -> Option<ast::Expr>61 pub fn tail_expr(&self) -> Option<ast::Expr> {
62 self.stmt_list()?.tail_expr()
63 }
64 }
65
66 #[derive(Debug, PartialEq, Eq, Clone)]
67 pub enum Macro {
68 MacroRules(ast::MacroRules),
69 MacroDef(ast::MacroDef),
70 }
71
72 impl From<ast::MacroRules> for Macro {
from(it: ast::MacroRules) -> Self73 fn from(it: ast::MacroRules) -> Self {
74 Macro::MacroRules(it)
75 }
76 }
77
78 impl From<ast::MacroDef> for Macro {
from(it: ast::MacroDef) -> Self79 fn from(it: ast::MacroDef) -> Self {
80 Macro::MacroDef(it)
81 }
82 }
83
84 impl AstNode for Macro {
can_cast(kind: SyntaxKind) -> bool85 fn can_cast(kind: SyntaxKind) -> bool {
86 matches!(kind, SyntaxKind::MACRO_RULES | SyntaxKind::MACRO_DEF)
87 }
cast(syntax: SyntaxNode) -> Option<Self>88 fn cast(syntax: SyntaxNode) -> Option<Self> {
89 let res = match syntax.kind() {
90 SyntaxKind::MACRO_RULES => Macro::MacroRules(ast::MacroRules { syntax }),
91 SyntaxKind::MACRO_DEF => Macro::MacroDef(ast::MacroDef { syntax }),
92 _ => return None,
93 };
94 Some(res)
95 }
syntax(&self) -> &SyntaxNode96 fn syntax(&self) -> &SyntaxNode {
97 match self {
98 Macro::MacroRules(it) => it.syntax(),
99 Macro::MacroDef(it) => it.syntax(),
100 }
101 }
102 }
103
104 impl HasName for Macro {
name(&self) -> Option<ast::Name>105 fn name(&self) -> Option<ast::Name> {
106 match self {
107 Macro::MacroRules(mac) => mac.name(),
108 Macro::MacroDef(mac) => mac.name(),
109 }
110 }
111 }
112
113 impl HasAttrs for Macro {}
114
115 impl From<ast::AssocItem> for ast::Item {
from(assoc: ast::AssocItem) -> Self116 fn from(assoc: ast::AssocItem) -> Self {
117 match assoc {
118 ast::AssocItem::Const(it) => ast::Item::Const(it),
119 ast::AssocItem::Fn(it) => ast::Item::Fn(it),
120 ast::AssocItem::MacroCall(it) => ast::Item::MacroCall(it),
121 ast::AssocItem::TypeAlias(it) => ast::Item::TypeAlias(it),
122 }
123 }
124 }
125
126 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
127 pub enum AttrKind {
128 Inner,
129 Outer,
130 }
131
132 impl AttrKind {
133 /// Returns `true` if the attr_kind is [`Inner`](Self::Inner).
is_inner(&self) -> bool134 pub fn is_inner(&self) -> bool {
135 matches!(self, Self::Inner)
136 }
137
138 /// Returns `true` if the attr_kind is [`Outer`](Self::Outer).
is_outer(&self) -> bool139 pub fn is_outer(&self) -> bool {
140 matches!(self, Self::Outer)
141 }
142 }
143
144 impl ast::Attr {
as_simple_atom(&self) -> Option<SmolStr>145 pub fn as_simple_atom(&self) -> Option<SmolStr> {
146 let meta = self.meta()?;
147 if meta.eq_token().is_some() || meta.token_tree().is_some() {
148 return None;
149 }
150 self.simple_name()
151 }
152
as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)>153 pub fn as_simple_call(&self) -> Option<(SmolStr, ast::TokenTree)> {
154 let tt = self.meta()?.token_tree()?;
155 Some((self.simple_name()?, tt))
156 }
157
simple_name(&self) -> Option<SmolStr>158 pub fn simple_name(&self) -> Option<SmolStr> {
159 let path = self.meta()?.path()?;
160 match (path.segment(), path.qualifier()) {
161 (Some(segment), None) => Some(segment.syntax().first_token()?.text().into()),
162 _ => None,
163 }
164 }
165
kind(&self) -> AttrKind166 pub fn kind(&self) -> AttrKind {
167 match self.excl_token() {
168 Some(_) => AttrKind::Inner,
169 None => AttrKind::Outer,
170 }
171 }
172
path(&self) -> Option<ast::Path>173 pub fn path(&self) -> Option<ast::Path> {
174 self.meta()?.path()
175 }
176
expr(&self) -> Option<ast::Expr>177 pub fn expr(&self) -> Option<ast::Expr> {
178 self.meta()?.expr()
179 }
180
token_tree(&self) -> Option<ast::TokenTree>181 pub fn token_tree(&self) -> Option<ast::TokenTree> {
182 self.meta()?.token_tree()
183 }
184 }
185
186 #[derive(Debug, Clone, PartialEq, Eq)]
187 pub enum PathSegmentKind {
188 Name(ast::NameRef),
189 Type { type_ref: Option<ast::Type>, trait_ref: Option<ast::PathType> },
190 SelfTypeKw,
191 SelfKw,
192 SuperKw,
193 CrateKw,
194 }
195
196 impl ast::PathSegment {
parent_path(&self) -> ast::Path197 pub fn parent_path(&self) -> ast::Path {
198 self.syntax()
199 .parent()
200 .and_then(ast::Path::cast)
201 .expect("segments are always nested in paths")
202 }
203
crate_token(&self) -> Option<SyntaxToken>204 pub fn crate_token(&self) -> Option<SyntaxToken> {
205 self.name_ref().and_then(|it| it.crate_token())
206 }
207
self_token(&self) -> Option<SyntaxToken>208 pub fn self_token(&self) -> Option<SyntaxToken> {
209 self.name_ref().and_then(|it| it.self_token())
210 }
211
self_type_token(&self) -> Option<SyntaxToken>212 pub fn self_type_token(&self) -> Option<SyntaxToken> {
213 self.name_ref().and_then(|it| it.Self_token())
214 }
215
super_token(&self) -> Option<SyntaxToken>216 pub fn super_token(&self) -> Option<SyntaxToken> {
217 self.name_ref().and_then(|it| it.super_token())
218 }
219
kind(&self) -> Option<PathSegmentKind>220 pub fn kind(&self) -> Option<PathSegmentKind> {
221 let res = if let Some(name_ref) = self.name_ref() {
222 match name_ref.token_kind() {
223 T![Self] => PathSegmentKind::SelfTypeKw,
224 T![self] => PathSegmentKind::SelfKw,
225 T![super] => PathSegmentKind::SuperKw,
226 T![crate] => PathSegmentKind::CrateKw,
227 _ => PathSegmentKind::Name(name_ref),
228 }
229 } else {
230 match self.syntax().first_child_or_token()?.kind() {
231 T![<] => {
232 // <T> or <T as Trait>
233 // T is any TypeRef, Trait has to be a PathType
234 let mut type_refs =
235 self.syntax().children().filter(|node| ast::Type::can_cast(node.kind()));
236 let type_ref = type_refs.next().and_then(ast::Type::cast);
237 let trait_ref = type_refs.next().and_then(ast::PathType::cast);
238 PathSegmentKind::Type { type_ref, trait_ref }
239 }
240 _ => return None,
241 }
242 };
243 Some(res)
244 }
245 }
246
247 impl ast::Path {
parent_path(&self) -> Option<ast::Path>248 pub fn parent_path(&self) -> Option<ast::Path> {
249 self.syntax().parent().and_then(ast::Path::cast)
250 }
251
as_single_segment(&self) -> Option<ast::PathSegment>252 pub fn as_single_segment(&self) -> Option<ast::PathSegment> {
253 match self.qualifier() {
254 Some(_) => None,
255 None => self.segment(),
256 }
257 }
258
as_single_name_ref(&self) -> Option<ast::NameRef>259 pub fn as_single_name_ref(&self) -> Option<ast::NameRef> {
260 match self.qualifier() {
261 Some(_) => None,
262 None => self.segment()?.name_ref(),
263 }
264 }
265
first_qualifier_or_self(&self) -> ast::Path266 pub fn first_qualifier_or_self(&self) -> ast::Path {
267 successors(Some(self.clone()), ast::Path::qualifier).last().unwrap()
268 }
269
first_segment(&self) -> Option<ast::PathSegment>270 pub fn first_segment(&self) -> Option<ast::PathSegment> {
271 self.first_qualifier_or_self().segment()
272 }
273
segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone274 pub fn segments(&self) -> impl Iterator<Item = ast::PathSegment> + Clone {
275 successors(self.first_segment(), |p| {
276 p.parent_path().parent_path().and_then(|p| p.segment())
277 })
278 }
279
qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone280 pub fn qualifiers(&self) -> impl Iterator<Item = ast::Path> + Clone {
281 successors(self.qualifier(), |p| p.qualifier())
282 }
283
top_path(&self) -> ast::Path284 pub fn top_path(&self) -> ast::Path {
285 let mut this = self.clone();
286 while let Some(path) = this.parent_path() {
287 this = path;
288 }
289 this
290 }
291 }
292
293 impl ast::Use {
is_simple_glob(&self) -> bool294 pub fn is_simple_glob(&self) -> bool {
295 self.use_tree().map_or(false, |use_tree| {
296 use_tree.use_tree_list().is_none() && use_tree.star_token().is_some()
297 })
298 }
299 }
300
301 impl ast::UseTree {
is_simple_path(&self) -> bool302 pub fn is_simple_path(&self) -> bool {
303 self.use_tree_list().is_none() && self.star_token().is_none()
304 }
305 }
306
307 impl ast::UseTreeList {
parent_use_tree(&self) -> ast::UseTree308 pub fn parent_use_tree(&self) -> ast::UseTree {
309 self.syntax()
310 .parent()
311 .and_then(ast::UseTree::cast)
312 .expect("UseTreeLists are always nested in UseTrees")
313 }
314
has_inner_comment(&self) -> bool315 pub fn has_inner_comment(&self) -> bool {
316 self.syntax()
317 .children_with_tokens()
318 .filter_map(|it| it.into_token())
319 .find_map(ast::Comment::cast)
320 .is_some()
321 }
322 }
323
324 impl ast::Impl {
self_ty(&self) -> Option<ast::Type>325 pub fn self_ty(&self) -> Option<ast::Type> {
326 match self.target() {
327 (Some(t), None) | (_, Some(t)) => Some(t),
328 _ => None,
329 }
330 }
331
trait_(&self) -> Option<ast::Type>332 pub fn trait_(&self) -> Option<ast::Type> {
333 match self.target() {
334 (Some(t), Some(_)) => Some(t),
335 _ => None,
336 }
337 }
338
target(&self) -> (Option<ast::Type>, Option<ast::Type>)339 fn target(&self) -> (Option<ast::Type>, Option<ast::Type>) {
340 let mut types = support::children(self.syntax());
341 let first = types.next();
342 let second = types.next();
343 (first, second)
344 }
345
for_trait_name_ref(name_ref: &ast::NameRef) -> Option<ast::Impl>346 pub fn for_trait_name_ref(name_ref: &ast::NameRef) -> Option<ast::Impl> {
347 let this = name_ref.syntax().ancestors().find_map(ast::Impl::cast)?;
348 if this.trait_()?.syntax().text_range().start() == name_ref.syntax().text_range().start() {
349 Some(this)
350 } else {
351 None
352 }
353 }
354 }
355
356 #[derive(Debug, Clone, PartialEq, Eq)]
357 pub enum StructKind {
358 Record(ast::RecordFieldList),
359 Tuple(ast::TupleFieldList),
360 Unit,
361 }
362
363 impl StructKind {
from_node<N: AstNode>(node: &N) -> StructKind364 fn from_node<N: AstNode>(node: &N) -> StructKind {
365 if let Some(nfdl) = support::child::<ast::RecordFieldList>(node.syntax()) {
366 StructKind::Record(nfdl)
367 } else if let Some(pfl) = support::child::<ast::TupleFieldList>(node.syntax()) {
368 StructKind::Tuple(pfl)
369 } else {
370 StructKind::Unit
371 }
372 }
373 }
374
375 impl ast::Struct {
kind(&self) -> StructKind376 pub fn kind(&self) -> StructKind {
377 StructKind::from_node(self)
378 }
379 }
380
381 impl ast::RecordExprField {
for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField>382 pub fn for_field_name(field_name: &ast::NameRef) -> Option<ast::RecordExprField> {
383 let candidate = Self::for_name_ref(field_name)?;
384 if candidate.field_name().as_ref() == Some(field_name) {
385 Some(candidate)
386 } else {
387 None
388 }
389 }
390
for_name_ref(name_ref: &ast::NameRef) -> Option<ast::RecordExprField>391 pub fn for_name_ref(name_ref: &ast::NameRef) -> Option<ast::RecordExprField> {
392 let syn = name_ref.syntax();
393 syn.parent()
394 .and_then(ast::RecordExprField::cast)
395 .or_else(|| syn.ancestors().nth(4).and_then(ast::RecordExprField::cast))
396 }
397
398 /// Deals with field init shorthand
field_name(&self) -> Option<ast::NameRef>399 pub fn field_name(&self) -> Option<ast::NameRef> {
400 if let Some(name_ref) = self.name_ref() {
401 return Some(name_ref);
402 }
403 if let ast::Expr::PathExpr(expr) = self.expr()? {
404 let path = expr.path()?;
405 let segment = path.segment()?;
406 let name_ref = segment.name_ref()?;
407 if path.qualifier().is_none() {
408 return Some(name_ref);
409 }
410 }
411 None
412 }
413 }
414
415 #[derive(Debug, Clone)]
416 pub enum NameLike {
417 NameRef(ast::NameRef),
418 Name(ast::Name),
419 Lifetime(ast::Lifetime),
420 }
421
422 impl NameLike {
as_name_ref(&self) -> Option<&ast::NameRef>423 pub fn as_name_ref(&self) -> Option<&ast::NameRef> {
424 match self {
425 NameLike::NameRef(name_ref) => Some(name_ref),
426 _ => None,
427 }
428 }
as_lifetime(&self) -> Option<&ast::Lifetime>429 pub fn as_lifetime(&self) -> Option<&ast::Lifetime> {
430 match self {
431 NameLike::Lifetime(lifetime) => Some(lifetime),
432 _ => None,
433 }
434 }
text(&self) -> TokenText<'_>435 pub fn text(&self) -> TokenText<'_> {
436 match self {
437 NameLike::NameRef(name_ref) => name_ref.text(),
438 NameLike::Name(name) => name.text(),
439 NameLike::Lifetime(lifetime) => lifetime.text(),
440 }
441 }
442 }
443
444 impl ast::AstNode for NameLike {
can_cast(kind: SyntaxKind) -> bool445 fn can_cast(kind: SyntaxKind) -> bool {
446 matches!(kind, SyntaxKind::NAME | SyntaxKind::NAME_REF | SyntaxKind::LIFETIME)
447 }
cast(syntax: SyntaxNode) -> Option<Self>448 fn cast(syntax: SyntaxNode) -> Option<Self> {
449 let res = match syntax.kind() {
450 SyntaxKind::NAME => NameLike::Name(ast::Name { syntax }),
451 SyntaxKind::NAME_REF => NameLike::NameRef(ast::NameRef { syntax }),
452 SyntaxKind::LIFETIME => NameLike::Lifetime(ast::Lifetime { syntax }),
453 _ => return None,
454 };
455 Some(res)
456 }
syntax(&self) -> &SyntaxNode457 fn syntax(&self) -> &SyntaxNode {
458 match self {
459 NameLike::NameRef(it) => it.syntax(),
460 NameLike::Name(it) => it.syntax(),
461 NameLike::Lifetime(it) => it.syntax(),
462 }
463 }
464 }
465
466 const _: () = {
467 use ast::{Lifetime, Name, NameRef};
468 stdx::impl_from!(NameRef, Name, Lifetime for NameLike);
469 };
470
471 #[derive(Debug, Clone, PartialEq)]
472 pub enum NameOrNameRef {
473 Name(ast::Name),
474 NameRef(ast::NameRef),
475 }
476
477 impl fmt::Display for NameOrNameRef {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result478 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
479 match self {
480 NameOrNameRef::Name(it) => fmt::Display::fmt(it, f),
481 NameOrNameRef::NameRef(it) => fmt::Display::fmt(it, f),
482 }
483 }
484 }
485
486 impl NameOrNameRef {
text(&self) -> TokenText<'_>487 pub fn text(&self) -> TokenText<'_> {
488 match self {
489 NameOrNameRef::Name(name) => name.text(),
490 NameOrNameRef::NameRef(name_ref) => name_ref.text(),
491 }
492 }
493 }
494
495 impl ast::RecordPatField {
for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField>496 pub fn for_field_name_ref(field_name: &ast::NameRef) -> Option<ast::RecordPatField> {
497 let candidate = field_name.syntax().parent().and_then(ast::RecordPatField::cast)?;
498 match candidate.field_name()? {
499 NameOrNameRef::NameRef(name_ref) if name_ref == *field_name => Some(candidate),
500 _ => None,
501 }
502 }
503
for_field_name(field_name: &ast::Name) -> Option<ast::RecordPatField>504 pub fn for_field_name(field_name: &ast::Name) -> Option<ast::RecordPatField> {
505 let candidate =
506 field_name.syntax().ancestors().nth(2).and_then(ast::RecordPatField::cast)?;
507 match candidate.field_name()? {
508 NameOrNameRef::Name(name) if name == *field_name => Some(candidate),
509 _ => None,
510 }
511 }
512
parent_record_pat(&self) -> ast::RecordPat513 pub fn parent_record_pat(&self) -> ast::RecordPat {
514 self.syntax().ancestors().find_map(ast::RecordPat::cast).unwrap()
515 }
516
517 /// Deals with field init shorthand
field_name(&self) -> Option<NameOrNameRef>518 pub fn field_name(&self) -> Option<NameOrNameRef> {
519 if let Some(name_ref) = self.name_ref() {
520 return Some(NameOrNameRef::NameRef(name_ref));
521 }
522 match self.pat() {
523 Some(ast::Pat::IdentPat(pat)) => {
524 let name = pat.name()?;
525 Some(NameOrNameRef::Name(name))
526 }
527 Some(ast::Pat::BoxPat(pat)) => match pat.pat() {
528 Some(ast::Pat::IdentPat(pat)) => {
529 let name = pat.name()?;
530 Some(NameOrNameRef::Name(name))
531 }
532 _ => None,
533 },
534 _ => None,
535 }
536 }
537 }
538
539 impl ast::Variant {
parent_enum(&self) -> ast::Enum540 pub fn parent_enum(&self) -> ast::Enum {
541 self.syntax()
542 .parent()
543 .and_then(|it| it.parent())
544 .and_then(ast::Enum::cast)
545 .expect("EnumVariants are always nested in Enums")
546 }
kind(&self) -> StructKind547 pub fn kind(&self) -> StructKind {
548 StructKind::from_node(self)
549 }
550 }
551
552 impl ast::Item {
generic_param_list(&self) -> Option<ast::GenericParamList>553 pub fn generic_param_list(&self) -> Option<ast::GenericParamList> {
554 ast::AnyHasGenericParams::cast(self.syntax().clone())?.generic_param_list()
555 }
556 }
557
558 #[derive(Debug, Clone, PartialEq, Eq)]
559 pub enum FieldKind {
560 Name(ast::NameRef),
561 Index(SyntaxToken),
562 }
563
564 impl ast::FieldExpr {
index_token(&self) -> Option<SyntaxToken>565 pub fn index_token(&self) -> Option<SyntaxToken> {
566 self.syntax
567 .children_with_tokens()
568 // FIXME: Accepting floats here to reject them in validation later
569 .find(|c| c.kind() == SyntaxKind::INT_NUMBER || c.kind() == SyntaxKind::FLOAT_NUMBER)
570 .as_ref()
571 .and_then(SyntaxElement::as_token)
572 .cloned()
573 }
574
field_access(&self) -> Option<FieldKind>575 pub fn field_access(&self) -> Option<FieldKind> {
576 match self.name_ref() {
577 Some(nr) => Some(FieldKind::Name(nr)),
578 None => self.index_token().map(FieldKind::Index),
579 }
580 }
581 }
582
583 pub struct SlicePatComponents {
584 pub prefix: Vec<ast::Pat>,
585 pub slice: Option<ast::Pat>,
586 pub suffix: Vec<ast::Pat>,
587 }
588
589 impl ast::SlicePat {
components(&self) -> SlicePatComponents590 pub fn components(&self) -> SlicePatComponents {
591 let mut args = self.pats().peekable();
592 let prefix = args
593 .peeking_take_while(|p| match p {
594 ast::Pat::RestPat(_) => false,
595 ast::Pat::IdentPat(bp) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
596 ast::Pat::RefPat(rp) => match rp.pat() {
597 Some(ast::Pat::RestPat(_)) => false,
598 Some(ast::Pat::IdentPat(bp)) => !matches!(bp.pat(), Some(ast::Pat::RestPat(_))),
599 _ => true,
600 },
601 _ => true,
602 })
603 .collect();
604 let slice = args.next();
605 let suffix = args.collect();
606
607 SlicePatComponents { prefix, slice, suffix }
608 }
609 }
610
611 impl ast::IdentPat {
is_simple_ident(&self) -> bool612 pub fn is_simple_ident(&self) -> bool {
613 self.at_token().is_none()
614 && self.mut_token().is_none()
615 && self.ref_token().is_none()
616 && self.pat().is_none()
617 }
618 }
619
620 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
621 pub enum SelfParamKind {
622 /// self
623 Owned,
624 /// &self
625 Ref,
626 /// &mut self
627 MutRef,
628 }
629
630 impl ast::SelfParam {
kind(&self) -> SelfParamKind631 pub fn kind(&self) -> SelfParamKind {
632 if self.amp_token().is_some() {
633 if self.mut_token().is_some() {
634 SelfParamKind::MutRef
635 } else {
636 SelfParamKind::Ref
637 }
638 } else {
639 SelfParamKind::Owned
640 }
641 }
642 }
643
644 #[derive(Clone, Debug, PartialEq, Eq, Hash)]
645 pub enum TypeBoundKind {
646 /// Trait
647 PathType(ast::PathType),
648 /// for<'a> ...
649 ForType(ast::ForType),
650 /// 'a
651 Lifetime(ast::Lifetime),
652 }
653
654 impl ast::TypeBound {
kind(&self) -> TypeBoundKind655 pub fn kind(&self) -> TypeBoundKind {
656 if let Some(path_type) = support::children(self.syntax()).next() {
657 TypeBoundKind::PathType(path_type)
658 } else if let Some(for_type) = support::children(self.syntax()).next() {
659 TypeBoundKind::ForType(for_type)
660 } else if let Some(lifetime) = self.lifetime() {
661 TypeBoundKind::Lifetime(lifetime)
662 } else {
663 unreachable!()
664 }
665 }
666 }
667
668 #[derive(Debug, Clone)]
669 pub enum TypeOrConstParam {
670 Type(ast::TypeParam),
671 Const(ast::ConstParam),
672 }
673
674 impl TypeOrConstParam {
name(&self) -> Option<ast::Name>675 pub fn name(&self) -> Option<ast::Name> {
676 match self {
677 TypeOrConstParam::Type(x) => x.name(),
678 TypeOrConstParam::Const(x) => x.name(),
679 }
680 }
681 }
682
683 impl AstNode for TypeOrConstParam {
can_cast(kind: SyntaxKind) -> bool where Self: Sized,684 fn can_cast(kind: SyntaxKind) -> bool
685 where
686 Self: Sized,
687 {
688 matches!(kind, SyntaxKind::TYPE_PARAM | SyntaxKind::CONST_PARAM)
689 }
690
cast(syntax: SyntaxNode) -> Option<Self> where Self: Sized,691 fn cast(syntax: SyntaxNode) -> Option<Self>
692 where
693 Self: Sized,
694 {
695 let res = match syntax.kind() {
696 SyntaxKind::TYPE_PARAM => TypeOrConstParam::Type(ast::TypeParam { syntax }),
697 SyntaxKind::CONST_PARAM => TypeOrConstParam::Const(ast::ConstParam { syntax }),
698 _ => return None,
699 };
700 Some(res)
701 }
702
syntax(&self) -> &SyntaxNode703 fn syntax(&self) -> &SyntaxNode {
704 match self {
705 TypeOrConstParam::Type(it) => it.syntax(),
706 TypeOrConstParam::Const(it) => it.syntax(),
707 }
708 }
709 }
710
711 impl HasAttrs for TypeOrConstParam {}
712
713 #[derive(Debug, Clone)]
714 pub enum TraitOrAlias {
715 Trait(ast::Trait),
716 TraitAlias(ast::TraitAlias),
717 }
718
719 impl TraitOrAlias {
name(&self) -> Option<ast::Name>720 pub fn name(&self) -> Option<ast::Name> {
721 match self {
722 TraitOrAlias::Trait(x) => x.name(),
723 TraitOrAlias::TraitAlias(x) => x.name(),
724 }
725 }
726 }
727
728 impl AstNode for TraitOrAlias {
can_cast(kind: SyntaxKind) -> bool where Self: Sized,729 fn can_cast(kind: SyntaxKind) -> bool
730 where
731 Self: Sized,
732 {
733 matches!(kind, SyntaxKind::TRAIT | SyntaxKind::TRAIT_ALIAS)
734 }
735
cast(syntax: SyntaxNode) -> Option<Self> where Self: Sized,736 fn cast(syntax: SyntaxNode) -> Option<Self>
737 where
738 Self: Sized,
739 {
740 let res = match syntax.kind() {
741 SyntaxKind::TRAIT => TraitOrAlias::Trait(ast::Trait { syntax }),
742 SyntaxKind::TRAIT_ALIAS => TraitOrAlias::TraitAlias(ast::TraitAlias { syntax }),
743 _ => return None,
744 };
745 Some(res)
746 }
747
syntax(&self) -> &SyntaxNode748 fn syntax(&self) -> &SyntaxNode {
749 match self {
750 TraitOrAlias::Trait(it) => it.syntax(),
751 TraitOrAlias::TraitAlias(it) => it.syntax(),
752 }
753 }
754 }
755
756 impl HasAttrs for TraitOrAlias {}
757
758 pub enum VisibilityKind {
759 In(ast::Path),
760 PubCrate,
761 PubSuper,
762 PubSelf,
763 Pub,
764 }
765
766 impl ast::Visibility {
kind(&self) -> VisibilityKind767 pub fn kind(&self) -> VisibilityKind {
768 match self.path() {
769 Some(path) => {
770 if let Some(segment) =
771 path.as_single_segment().filter(|it| it.coloncolon_token().is_none())
772 {
773 if segment.crate_token().is_some() {
774 return VisibilityKind::PubCrate;
775 } else if segment.super_token().is_some() {
776 return VisibilityKind::PubSuper;
777 } else if segment.self_token().is_some() {
778 return VisibilityKind::PubSelf;
779 }
780 }
781 VisibilityKind::In(path)
782 }
783 None => VisibilityKind::Pub,
784 }
785 }
786 }
787
788 impl ast::LifetimeParam {
lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken>789 pub fn lifetime_bounds(&self) -> impl Iterator<Item = SyntaxToken> {
790 self.syntax()
791 .children_with_tokens()
792 .filter_map(|it| it.into_token())
793 .skip_while(|x| x.kind() != T![:])
794 .filter(|it| it.kind() == T![lifetime_ident])
795 }
796 }
797
798 impl ast::Module {
799 /// Returns the parent ast::Module, this is different than the semantic parent in that this only
800 /// considers parent declarations in the AST
parent(&self) -> Option<ast::Module>801 pub fn parent(&self) -> Option<ast::Module> {
802 self.syntax().ancestors().nth(2).and_then(ast::Module::cast)
803 }
804 }
805
806 impl ast::RangePat {
start(&self) -> Option<ast::Pat>807 pub fn start(&self) -> Option<ast::Pat> {
808 self.syntax()
809 .children_with_tokens()
810 .take_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
811 .filter_map(|it| it.into_node())
812 .find_map(ast::Pat::cast)
813 }
814
end(&self) -> Option<ast::Pat>815 pub fn end(&self) -> Option<ast::Pat> {
816 self.syntax()
817 .children_with_tokens()
818 .skip_while(|it| !(it.kind() == T![..] || it.kind() == T![..=]))
819 .filter_map(|it| it.into_node())
820 .find_map(ast::Pat::cast)
821 }
822 }
823
824 impl ast::TokenTree {
token_trees_and_tokens( &self, ) -> impl Iterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>>825 pub fn token_trees_and_tokens(
826 &self,
827 ) -> impl Iterator<Item = NodeOrToken<ast::TokenTree, SyntaxToken>> {
828 self.syntax().children_with_tokens().filter_map(|not| match not {
829 NodeOrToken::Node(node) => ast::TokenTree::cast(node).map(NodeOrToken::Node),
830 NodeOrToken::Token(t) => Some(NodeOrToken::Token(t)),
831 })
832 }
833
left_delimiter_token(&self) -> Option<SyntaxToken>834 pub fn left_delimiter_token(&self) -> Option<SyntaxToken> {
835 self.syntax()
836 .first_child_or_token()?
837 .into_token()
838 .filter(|it| matches!(it.kind(), T!['{'] | T!['('] | T!['[']))
839 }
840
right_delimiter_token(&self) -> Option<SyntaxToken>841 pub fn right_delimiter_token(&self) -> Option<SyntaxToken> {
842 self.syntax()
843 .last_child_or_token()?
844 .into_token()
845 .filter(|it| matches!(it.kind(), T!['}'] | T![')'] | T![']']))
846 }
847
parent_meta(&self) -> Option<ast::Meta>848 pub fn parent_meta(&self) -> Option<ast::Meta> {
849 self.syntax().parent().and_then(ast::Meta::cast)
850 }
851 }
852
853 impl ast::Meta {
parent_attr(&self) -> Option<ast::Attr>854 pub fn parent_attr(&self) -> Option<ast::Attr> {
855 self.syntax().parent().and_then(ast::Attr::cast)
856 }
857 }
858
859 impl ast::GenericArgList {
lifetime_args(&self) -> impl Iterator<Item = ast::LifetimeArg>860 pub fn lifetime_args(&self) -> impl Iterator<Item = ast::LifetimeArg> {
861 self.generic_args().filter_map(|arg| match arg {
862 ast::GenericArg::LifetimeArg(it) => Some(it),
863 _ => None,
864 })
865 }
866 }
867
868 impl ast::GenericParamList {
lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam>869 pub fn lifetime_params(&self) -> impl Iterator<Item = ast::LifetimeParam> {
870 self.generic_params().filter_map(|param| match param {
871 ast::GenericParam::LifetimeParam(it) => Some(it),
872 ast::GenericParam::TypeParam(_) | ast::GenericParam::ConstParam(_) => None,
873 })
874 }
type_or_const_params(&self) -> impl Iterator<Item = ast::TypeOrConstParam>875 pub fn type_or_const_params(&self) -> impl Iterator<Item = ast::TypeOrConstParam> {
876 self.generic_params().filter_map(|param| match param {
877 ast::GenericParam::TypeParam(it) => Some(ast::TypeOrConstParam::Type(it)),
878 ast::GenericParam::LifetimeParam(_) => None,
879 ast::GenericParam::ConstParam(it) => Some(ast::TypeOrConstParam::Const(it)),
880 })
881 }
882 }
883
884 impl ast::ForExpr {
iterable(&self) -> Option<ast::Expr>885 pub fn iterable(&self) -> Option<ast::Expr> {
886 // If the iterable is a BlockExpr, check if the body is missing.
887 // If it is assume the iterable is the expression that is missing instead.
888 let mut exprs = support::children(self.syntax());
889 let first = exprs.next();
890 match first {
891 Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
892 first => first,
893 }
894 }
895 }
896
897 impl ast::HasLoopBody for ast::ForExpr {
loop_body(&self) -> Option<ast::BlockExpr>898 fn loop_body(&self) -> Option<ast::BlockExpr> {
899 let mut exprs = support::children(self.syntax());
900 let first = exprs.next();
901 let second = exprs.next();
902 second.or(first)
903 }
904 }
905
906 impl ast::WhileExpr {
condition(&self) -> Option<ast::Expr>907 pub fn condition(&self) -> Option<ast::Expr> {
908 // If the condition is a BlockExpr, check if the body is missing.
909 // If it is assume the condition is the expression that is missing instead.
910 let mut exprs = support::children(self.syntax());
911 let first = exprs.next();
912 match first {
913 Some(ast::Expr::BlockExpr(_)) => exprs.next().and(first),
914 first => first,
915 }
916 }
917 }
918
919 impl ast::HasLoopBody for ast::WhileExpr {
loop_body(&self) -> Option<ast::BlockExpr>920 fn loop_body(&self) -> Option<ast::BlockExpr> {
921 let mut exprs = support::children(self.syntax());
922 let first = exprs.next();
923 let second = exprs.next();
924 second.or(first)
925 }
926 }
927
928 impl ast::HasAttrs for ast::AnyHasDocComments {}
929
930 impl From<ast::Adt> for ast::Item {
from(it: ast::Adt) -> Self931 fn from(it: ast::Adt) -> Self {
932 match it {
933 ast::Adt::Enum(it) => ast::Item::Enum(it),
934 ast::Adt::Struct(it) => ast::Item::Struct(it),
935 ast::Adt::Union(it) => ast::Item::Union(it),
936 }
937 }
938 }
939
940 impl ast::MatchGuard {
condition(&self) -> Option<ast::Expr>941 pub fn condition(&self) -> Option<ast::Expr> {
942 support::child(&self.syntax)
943 }
944 }
945
946 impl From<ast::Item> for ast::AnyHasAttrs {
from(node: ast::Item) -> Self947 fn from(node: ast::Item) -> Self {
948 Self::new(node)
949 }
950 }
951
952 impl From<ast::AssocItem> for ast::AnyHasAttrs {
from(node: ast::AssocItem) -> Self953 fn from(node: ast::AssocItem) -> Self {
954 Self::new(node)
955 }
956 }
957
958 impl From<ast::Variant> for ast::AnyHasAttrs {
from(node: ast::Variant) -> Self959 fn from(node: ast::Variant) -> Self {
960 Self::new(node)
961 }
962 }
963
964 impl From<ast::RecordField> for ast::AnyHasAttrs {
from(node: ast::RecordField) -> Self965 fn from(node: ast::RecordField) -> Self {
966 Self::new(node)
967 }
968 }
969
970 impl From<ast::TupleField> for ast::AnyHasAttrs {
from(node: ast::TupleField) -> Self971 fn from(node: ast::TupleField) -> Self {
972 Self::new(node)
973 }
974 }
975