1use paste::paste;
2use rue_parser::{SyntaxElement, SyntaxKind, SyntaxNode, SyntaxToken, T};
3
4pub trait AstNode {
5 fn cast(node: SyntaxNode) -> Option<Self>
6 where
7 Self: Sized;
8
9 fn syntax(&self) -> &SyntaxNode;
10}
11
12macro_rules! ast_nodes {
13 ($( $kind:ident),+ $(,)?) => { paste! { $(
14 #[derive(Debug, Clone)]
15 pub struct [< Ast $kind >](SyntaxNode);
16
17 impl AstNode for [< Ast $kind >] {
18 fn cast(node: SyntaxNode) -> Option<Self> {
19 match node.kind() {
20 SyntaxKind::$kind => Some(Self(node)),
21 _ => None,
22 }
23 }
24
25 fn syntax(&self) -> &SyntaxNode {
26 &self.0
27 }
28 }
29 )+ } };
30}
31
32macro_rules! ast_enum {
33 ($name:ident, $( $kind:ident ),+ $(,)? ) => { paste! {
34 #[derive(Debug, Clone)]
35 pub enum [< Ast $name >] {
36 $( $kind([< Ast $kind >]), )+
37 }
38
39 impl AstNode for [< Ast $name >] {
40 fn cast(node: SyntaxNode) -> Option<Self> {
41 $( if let Some(node) = [< Ast $kind >]::cast(node.clone()) {
42 return Some(Self::$kind(node));
43 } )+
44 None
45 }
46
47 fn syntax(&self) -> &SyntaxNode {
48 match self {
49 $( Self::$kind(node) => node.syntax(), )+
50 }
51 }
52 }
53 } };
54}
55
56ast_nodes!(
57 Document,
58 ModuleItem,
59 FunctionItem,
60 FunctionParameter,
61 ConstantItem,
62 TypeAliasItem,
63 StructItem,
64 StructField,
65 ImportItem,
66 ImportPath,
67 ImportPathSegment,
68 GenericParameters,
69 GenericArguments,
70 LiteralType,
71 PathType,
72 UnionType,
73 GroupType,
74 PairType,
75 ListType,
76 ListTypeItem,
77 LambdaType,
78 LambdaParameter,
79 Block,
80 LetStmt,
81 ExprStmt,
82 IfStmt,
83 ReturnStmt,
84 AssertStmt,
85 RaiseStmt,
86 DebugStmt,
87 PathExpr,
88 PathSegment,
89 StructInitializerExpr,
90 StructInitializerField,
91 LiteralExpr,
92 GroupExpr,
93 PairExpr,
94 ListExpr,
95 ListItem,
96 PrefixExpr,
97 BinaryExpr,
98 FunctionCallExpr,
99 IfExpr,
100 GuardExpr,
101 CastExpr,
102 FieldAccessExpr,
103 LambdaExpr,
104 NamedBinding,
105 PairBinding,
106 ListBinding,
107 ListBindingItem,
108 StructBinding,
109 StructFieldBinding,
110);
111
112ast_enum!(Item, TypeItem, SymbolItem, ImportItem);
113ast_enum!(TypeItem, TypeAliasItem, StructItem);
114ast_enum!(SymbolItem, ModuleItem, FunctionItem, ConstantItem);
115ast_enum!(
116 Stmt, LetStmt, ExprStmt, IfStmt, ReturnStmt, AssertStmt, RaiseStmt, DebugStmt
117);
118ast_enum!(StmtOrExpr, Stmt, Expr);
119ast_enum!(
120 Expr,
121 PathExpr,
122 StructInitializerExpr,
123 LiteralExpr,
124 GroupExpr,
125 PairExpr,
126 ListExpr,
127 PrefixExpr,
128 BinaryExpr,
129 FunctionCallExpr,
130 Block,
131 IfExpr,
132 GuardExpr,
133 CastExpr,
134 FieldAccessExpr,
135 LambdaExpr,
136);
137ast_enum!(
138 Type,
139 LiteralType,
140 PathType,
141 UnionType,
142 GroupType,
143 PairType,
144 ListType,
145 LambdaType,
146);
147ast_enum!(
148 Binding,
149 NamedBinding,
150 PairBinding,
151 ListBinding,
152 StructBinding,
153);
154
155impl AstDocument {
156 pub fn items(&self) -> impl Iterator<Item = AstItem> {
157 self.syntax().children().filter_map(AstItem::cast)
158 }
159}
160
161impl AstModuleItem {
162 pub fn export(&self) -> Option<SyntaxToken> {
163 self.syntax()
164 .children_with_tokens()
165 .filter_map(SyntaxElement::into_token)
166 .find(|token| token.kind() == T![export])
167 }
168
169 pub fn name(&self) -> Option<SyntaxToken> {
170 self.syntax()
171 .children_with_tokens()
172 .filter_map(SyntaxElement::into_token)
173 .find(|token| token.kind() == SyntaxKind::Ident)
174 }
175
176 pub fn items(&self) -> impl Iterator<Item = AstItem> {
177 self.syntax().children().filter_map(AstItem::cast)
178 }
179}
180
181impl AstFunctionItem {
182 pub fn export(&self) -> Option<SyntaxToken> {
183 self.syntax()
184 .children_with_tokens()
185 .filter_map(SyntaxElement::into_token)
186 .find(|token| token.kind() == T![export])
187 }
188
189 pub fn extern_kw(&self) -> Option<SyntaxToken> {
190 self.syntax()
191 .children_with_tokens()
192 .filter_map(SyntaxElement::into_token)
193 .find(|token| token.kind() == T![extern])
194 }
195
196 pub fn inline(&self) -> Option<SyntaxToken> {
197 self.syntax()
198 .children_with_tokens()
199 .filter_map(SyntaxElement::into_token)
200 .find(|token| token.kind() == T![inline])
201 }
202
203 pub fn test(&self) -> Option<SyntaxToken> {
204 self.syntax()
205 .children_with_tokens()
206 .filter_map(SyntaxElement::into_token)
207 .find(|token| token.kind() == T![test])
208 }
209
210 pub fn name(&self) -> Option<SyntaxToken> {
211 self.syntax()
212 .children_with_tokens()
213 .filter_map(SyntaxElement::into_token)
214 .find(|token| token.kind() == SyntaxKind::Ident)
215 }
216
217 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
218 self.syntax()
219 .children()
220 .find_map(AstGenericParameters::cast)
221 }
222
223 pub fn parameters(&self) -> impl Iterator<Item = AstFunctionParameter> {
224 self.syntax()
225 .children()
226 .filter_map(AstFunctionParameter::cast)
227 }
228
229 pub fn return_type(&self) -> Option<AstType> {
230 self.syntax().children().find_map(AstType::cast)
231 }
232
233 pub fn body(&self) -> Option<AstBlock> {
234 self.syntax().children().find_map(AstBlock::cast)
235 }
236}
237
238impl AstConstantItem {
239 pub fn export(&self) -> Option<SyntaxToken> {
240 self.syntax()
241 .children_with_tokens()
242 .filter_map(SyntaxElement::into_token)
243 .find(|token| token.kind() == T![export])
244 }
245
246 pub fn inline(&self) -> Option<SyntaxToken> {
247 self.syntax()
248 .children_with_tokens()
249 .filter_map(SyntaxElement::into_token)
250 .find(|token| token.kind() == T![inline])
251 }
252
253 pub fn name(&self) -> Option<SyntaxToken> {
254 self.syntax()
255 .children_with_tokens()
256 .filter_map(SyntaxElement::into_token)
257 .find(|token| token.kind() == SyntaxKind::Ident)
258 }
259
260 pub fn ty(&self) -> Option<AstType> {
261 self.syntax().children().find_map(AstType::cast)
262 }
263
264 pub fn value(&self) -> Option<AstExpr> {
265 self.syntax().children().find_map(AstExpr::cast)
266 }
267}
268
269impl AstTypeAliasItem {
270 pub fn export(&self) -> Option<SyntaxToken> {
271 self.syntax()
272 .children_with_tokens()
273 .filter_map(SyntaxElement::into_token)
274 .find(|token| token.kind() == T![export])
275 }
276
277 pub fn name(&self) -> Option<SyntaxToken> {
278 self.syntax()
279 .children_with_tokens()
280 .filter_map(SyntaxElement::into_token)
281 .find(|token| token.kind() == SyntaxKind::Ident)
282 }
283
284 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
285 self.syntax()
286 .children()
287 .find_map(AstGenericParameters::cast)
288 }
289
290 pub fn ty(&self) -> Option<AstType> {
291 self.syntax().children().find_map(AstType::cast)
292 }
293}
294
295impl AstStructItem {
296 pub fn export(&self) -> Option<SyntaxToken> {
297 self.syntax()
298 .children_with_tokens()
299 .filter_map(SyntaxElement::into_token)
300 .find(|token| token.kind() == T![export])
301 }
302
303 pub fn name(&self) -> Option<SyntaxToken> {
304 self.syntax()
305 .children_with_tokens()
306 .filter_map(SyntaxElement::into_token)
307 .find(|token| token.kind() == SyntaxKind::Ident)
308 }
309
310 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
311 self.syntax()
312 .children()
313 .find_map(AstGenericParameters::cast)
314 }
315
316 pub fn fields(&self) -> impl Iterator<Item = AstStructField> {
317 self.syntax().children().filter_map(AstStructField::cast)
318 }
319}
320
321impl AstStructField {
322 pub fn spread(&self) -> Option<SyntaxToken> {
323 self.syntax()
324 .children_with_tokens()
325 .filter_map(SyntaxElement::into_token)
326 .find(|token| token.kind() == T![...])
327 }
328
329 pub fn name(&self) -> Option<SyntaxToken> {
330 self.syntax()
331 .children_with_tokens()
332 .filter_map(SyntaxElement::into_token)
333 .find(|token| token.kind() == SyntaxKind::Ident)
334 }
335
336 pub fn ty(&self) -> Option<AstType> {
337 self.syntax().children().find_map(AstType::cast)
338 }
339
340 pub fn expr(&self) -> Option<AstExpr> {
341 self.syntax().children().find_map(AstExpr::cast)
342 }
343}
344
345impl AstImportItem {
346 pub fn export(&self) -> Option<SyntaxToken> {
347 self.syntax()
348 .children_with_tokens()
349 .filter_map(SyntaxElement::into_token)
350 .find(|token| token.kind() == T![export])
351 }
352
353 pub fn path(&self) -> Option<AstImportPath> {
354 self.syntax().children().find_map(AstImportPath::cast)
355 }
356}
357
358impl AstImportPath {
359 pub fn segments(&self) -> impl Iterator<Item = AstImportPathSegment> {
360 self.syntax()
361 .children()
362 .filter_map(AstImportPathSegment::cast)
363 }
364}
365
366impl AstImportPathSegment {
367 pub fn separator(&self) -> Option<SyntaxToken> {
368 self.syntax()
369 .children_with_tokens()
370 .filter_map(SyntaxElement::into_token)
371 .find(|token| token.kind() == T![::])
372 }
373
374 pub fn name(&self) -> Option<SyntaxToken> {
375 self.syntax()
376 .children_with_tokens()
377 .filter_map(SyntaxElement::into_token)
378 .find(|token| token.kind() == SyntaxKind::Ident || token.kind() == T![super])
379 }
380
381 pub fn star(&self) -> Option<SyntaxToken> {
382 self.syntax()
383 .children_with_tokens()
384 .filter_map(SyntaxElement::into_token)
385 .find(|token| token.kind() == T![*])
386 }
387
388 pub fn items(&self) -> impl Iterator<Item = AstImportPath> {
389 self.syntax().children().filter_map(AstImportPath::cast)
390 }
391}
392
393impl AstFunctionParameter {
394 pub fn spread(&self) -> Option<SyntaxToken> {
395 self.syntax()
396 .children_with_tokens()
397 .filter_map(SyntaxElement::into_token)
398 .find(|token| token.kind() == T![...])
399 }
400
401 pub fn binding(&self) -> Option<AstBinding> {
402 self.syntax().children().find_map(AstBinding::cast)
403 }
404
405 pub fn ty(&self) -> Option<AstType> {
406 self.syntax().children().find_map(AstType::cast)
407 }
408}
409
410impl AstGenericParameters {
411 pub fn names(&self) -> impl Iterator<Item = SyntaxToken> {
412 self.syntax()
413 .children_with_tokens()
414 .filter_map(SyntaxElement::into_token)
415 .filter(|token| token.kind() == SyntaxKind::Ident)
416 }
417}
418
419impl AstGenericArguments {
420 pub fn types(&self) -> impl Iterator<Item = AstType> {
421 self.syntax().children().filter_map(AstType::cast)
422 }
423}
424
425impl AstBlock {
426 pub fn items(&self) -> impl Iterator<Item = AstStmtOrExpr> {
427 self.syntax().children().filter_map(AstStmtOrExpr::cast)
428 }
429}
430
431impl AstLetStmt {
432 pub fn inline(&self) -> Option<SyntaxToken> {
433 self.syntax()
434 .children_with_tokens()
435 .filter_map(SyntaxElement::into_token)
436 .find(|token| token.kind() == T![inline])
437 }
438
439 pub fn binding(&self) -> Option<AstBinding> {
440 self.syntax().children().find_map(AstBinding::cast)
441 }
442
443 pub fn ty(&self) -> Option<AstType> {
444 self.syntax().children().find_map(AstType::cast)
445 }
446
447 pub fn value(&self) -> Option<AstExpr> {
448 self.syntax().children().find_map(AstExpr::cast)
449 }
450}
451
452impl AstExprStmt {
453 pub fn expr(&self) -> Option<AstExpr> {
454 self.syntax().children().find_map(AstExpr::cast)
455 }
456}
457
458impl AstIfStmt {
459 pub fn inline(&self) -> Option<SyntaxToken> {
460 self.syntax()
461 .children_with_tokens()
462 .filter_map(SyntaxElement::into_token)
463 .find(|token| token.kind() == T![inline])
464 }
465
466 pub fn condition(&self) -> Option<AstExpr> {
467 self.syntax().children().find_map(AstExpr::cast)
468 }
469
470 pub fn then_block(&self) -> Option<AstBlock> {
471 self.syntax()
472 .children()
473 .filter(|node| AstExpr::cast(node.clone()).is_some())
474 .nth(1)
475 .and_then(AstBlock::cast)
476 }
477}
478
479impl AstReturnStmt {
480 pub fn expr(&self) -> Option<AstExpr> {
481 self.syntax().children().find_map(AstExpr::cast)
482 }
483}
484
485impl AstAssertStmt {
486 pub fn expr(&self) -> Option<AstExpr> {
487 self.syntax().children().find_map(AstExpr::cast)
488 }
489}
490
491impl AstRaiseStmt {
492 pub fn expr(&self) -> Option<AstExpr> {
493 self.syntax().children().find_map(AstExpr::cast)
494 }
495}
496
497impl AstDebugStmt {
498 pub fn expr(&self) -> Option<AstExpr> {
499 self.syntax().children().find_map(AstExpr::cast)
500 }
501}
502
503impl AstPathExpr {
504 pub fn segments(&self) -> impl Iterator<Item = AstPathSegment> {
505 self.syntax().children().filter_map(AstPathSegment::cast)
506 }
507}
508
509impl AstPathSegment {
510 pub fn separator(&self) -> Option<SyntaxToken> {
511 self.syntax()
512 .children_with_tokens()
513 .filter_map(SyntaxElement::into_token)
514 .find(|token| token.kind() == T![::])
515 .filter(|token| {
516 let Some(name) = self.name() else {
517 return true;
518 };
519 token.text_range().start() < name.text_range().start()
520 })
521 }
522
523 pub fn name(&self) -> Option<SyntaxToken> {
524 self.syntax()
525 .children_with_tokens()
526 .filter_map(SyntaxElement::into_token)
527 .find(|token| token.kind() == SyntaxKind::Ident || token.kind() == T![super])
528 }
529
530 pub fn generic_arguments(&self) -> Option<AstGenericArguments> {
531 self.syntax().children().find_map(AstGenericArguments::cast)
532 }
533}
534
535impl AstStructInitializerExpr {
536 pub fn path(&self) -> Option<AstPathExpr> {
537 self.syntax().children().find_map(AstPathExpr::cast)
538 }
539
540 pub fn fields(&self) -> impl Iterator<Item = AstStructInitializerField> {
541 self.syntax()
542 .children()
543 .filter_map(AstStructInitializerField::cast)
544 }
545}
546
547impl AstStructInitializerField {
548 pub fn name(&self) -> Option<SyntaxToken> {
549 self.syntax()
550 .children_with_tokens()
551 .filter_map(SyntaxElement::into_token)
552 .find(|token| token.kind() == SyntaxKind::Ident)
553 }
554
555 pub fn expr(&self) -> Option<AstExpr> {
556 self.syntax().children().find_map(AstExpr::cast)
557 }
558}
559
560impl AstLiteralExpr {
561 pub fn value(&self) -> Option<SyntaxToken> {
562 self.syntax()
563 .children_with_tokens()
564 .filter_map(SyntaxElement::into_token)
565 .find(|token| SyntaxKind::LITERAL.contains(&token.kind()))
566 }
567}
568
569impl AstGroupExpr {
570 pub fn expr(&self) -> Option<AstExpr> {
571 self.syntax().children().find_map(AstExpr::cast)
572 }
573}
574
575impl AstPairExpr {
576 pub fn first(&self) -> Option<AstExpr> {
577 self.syntax().children().find_map(AstExpr::cast)
578 }
579
580 pub fn rest(&self) -> Option<AstExpr> {
581 self.syntax().children().filter_map(AstExpr::cast).nth(1)
582 }
583}
584
585impl AstListExpr {
586 pub fn items(&self) -> impl Iterator<Item = AstListItem> {
587 self.syntax().children().filter_map(AstListItem::cast)
588 }
589}
590
591impl AstListItem {
592 pub fn spread(&self) -> Option<SyntaxToken> {
593 self.syntax()
594 .children_with_tokens()
595 .filter_map(SyntaxElement::into_token)
596 .find(|token| token.kind() == T![...])
597 }
598
599 pub fn expr(&self) -> Option<AstExpr> {
600 self.syntax().children().find_map(AstExpr::cast)
601 }
602}
603
604impl AstPrefixExpr {
605 pub fn op(&self) -> Option<SyntaxToken> {
606 self.syntax()
607 .children_with_tokens()
608 .filter_map(SyntaxElement::into_token)
609 .find(|token| SyntaxKind::PREFIX_OPS.contains(&token.kind()))
610 }
611
612 pub fn expr(&self) -> Option<AstExpr> {
613 self.syntax().children().find_map(AstExpr::cast)
614 }
615}
616
617impl AstBinaryExpr {
618 pub fn op(&self) -> Option<SyntaxToken> {
619 self.syntax()
620 .children_with_tokens()
621 .filter_map(SyntaxElement::into_token)
622 .find(|token| SyntaxKind::BINARY_OPS.contains(&token.kind()))
623 }
624
625 pub fn left(&self) -> Option<AstExpr> {
626 self.syntax().children().find_map(AstExpr::cast)
627 }
628
629 pub fn right(&self) -> Option<AstExpr> {
630 self.syntax().children().filter_map(AstExpr::cast).nth(1)
631 }
632}
633
634impl AstFunctionCallExpr {
635 pub fn expr(&self) -> Option<AstExpr> {
636 self.syntax().children().find_map(AstExpr::cast)
637 }
638
639 pub fn args(&self) -> impl Iterator<Item = AstListItem> {
640 self.syntax().children().filter_map(AstListItem::cast)
641 }
642}
643
644impl AstIfExpr {
645 pub fn inline(&self) -> Option<SyntaxToken> {
646 self.syntax()
647 .children_with_tokens()
648 .filter_map(SyntaxElement::into_token)
649 .find(|token| token.kind() == T![inline])
650 }
651
652 pub fn condition(&self) -> Option<AstExpr> {
653 self.syntax().children().find_map(AstExpr::cast)
654 }
655
656 pub fn then_expr(&self) -> Option<AstExpr> {
657 self.syntax().children().filter_map(AstExpr::cast).nth(1)
658 }
659
660 pub fn else_expr(&self) -> Option<AstExpr> {
661 self.syntax().children().filter_map(AstExpr::cast).nth(2)
662 }
663}
664
665impl AstGuardExpr {
666 pub fn expr(&self) -> Option<AstExpr> {
667 self.syntax().children().find_map(AstExpr::cast)
668 }
669
670 pub fn ty(&self) -> Option<AstType> {
671 self.syntax().children().find_map(AstType::cast)
672 }
673}
674
675impl AstCastExpr {
676 pub fn expr(&self) -> Option<AstExpr> {
677 self.syntax().children().find_map(AstExpr::cast)
678 }
679
680 pub fn ty(&self) -> Option<AstType> {
681 self.syntax().children().find_map(AstType::cast)
682 }
683}
684
685impl AstFieldAccessExpr {
686 pub fn expr(&self) -> Option<AstExpr> {
687 self.syntax().children().find_map(AstExpr::cast)
688 }
689
690 pub fn dot(&self) -> Option<SyntaxToken> {
691 self.syntax()
692 .children_with_tokens()
693 .filter_map(SyntaxElement::into_token)
694 .find(|token| token.kind() == T![.])
695 }
696
697 pub fn field(&self) -> Option<SyntaxToken> {
698 self.syntax()
699 .children_with_tokens()
700 .filter_map(SyntaxElement::into_token)
701 .find(|token| token.kind() == SyntaxKind::Ident)
702 }
703}
704
705impl AstLambdaExpr {
706 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
707 self.syntax()
708 .children()
709 .find_map(AstGenericParameters::cast)
710 }
711
712 pub fn parameters(&self) -> impl Iterator<Item = AstFunctionParameter> {
713 self.syntax()
714 .children()
715 .filter_map(AstFunctionParameter::cast)
716 }
717
718 pub fn ty(&self) -> Option<AstType> {
719 self.syntax().children().find_map(AstType::cast)
720 }
721
722 pub fn body(&self) -> Option<AstExpr> {
723 self.syntax().children().find_map(AstExpr::cast)
724 }
725}
726
727impl AstLiteralType {
728 pub fn value(&self) -> Option<SyntaxToken> {
729 self.syntax()
730 .children_with_tokens()
731 .filter_map(SyntaxElement::into_token)
732 .find(|token| SyntaxKind::LITERAL.contains(&token.kind()))
733 }
734}
735
736impl AstPathType {
737 pub fn segments(&self) -> impl Iterator<Item = AstPathSegment> {
738 self.syntax().children().filter_map(AstPathSegment::cast)
739 }
740}
741
742impl AstUnionType {
743 pub fn types(&self) -> impl Iterator<Item = AstType> {
744 self.syntax().children().filter_map(AstType::cast)
745 }
746}
747
748impl AstGroupType {
749 pub fn ty(&self) -> Option<AstType> {
750 self.syntax().children().find_map(AstType::cast)
751 }
752}
753
754impl AstPairType {
755 pub fn first(&self) -> Option<AstType> {
756 self.syntax().children().find_map(AstType::cast)
757 }
758
759 pub fn rest(&self) -> Option<AstType> {
760 self.syntax().children().filter_map(AstType::cast).nth(1)
761 }
762}
763
764impl AstListType {
765 pub fn items(&self) -> impl Iterator<Item = AstListTypeItem> {
766 self.syntax().children().filter_map(AstListTypeItem::cast)
767 }
768}
769
770impl AstListTypeItem {
771 pub fn spread(&self) -> Option<SyntaxToken> {
772 self.syntax()
773 .children_with_tokens()
774 .filter_map(SyntaxElement::into_token)
775 .find(|token| token.kind() == T![...])
776 }
777
778 pub fn ty(&self) -> Option<AstType> {
779 self.syntax().children().find_map(AstType::cast)
780 }
781}
782
783impl AstLambdaType {
784 pub fn generic_parameters(&self) -> Option<AstGenericParameters> {
785 self.syntax()
786 .children()
787 .find_map(AstGenericParameters::cast)
788 }
789
790 pub fn parameters(&self) -> impl Iterator<Item = AstLambdaParameter> {
791 self.syntax()
792 .children()
793 .filter_map(AstLambdaParameter::cast)
794 }
795
796 pub fn return_type(&self) -> Option<AstType> {
797 self.syntax().children().find_map(AstType::cast)
798 }
799}
800
801impl AstLambdaParameter {
802 pub fn spread(&self) -> Option<SyntaxToken> {
803 self.syntax()
804 .children_with_tokens()
805 .filter_map(SyntaxElement::into_token)
806 .find(|token| token.kind() == T![...])
807 }
808
809 pub fn name(&self) -> Option<SyntaxToken> {
810 self.syntax()
811 .children_with_tokens()
812 .filter_map(SyntaxElement::into_token)
813 .find(|token| token.kind() == SyntaxKind::Ident)
814 }
815
816 pub fn ty(&self) -> Option<AstType> {
817 self.syntax().children().find_map(AstType::cast)
818 }
819}
820
821impl AstNamedBinding {
822 pub fn name(&self) -> Option<SyntaxToken> {
823 self.syntax()
824 .children_with_tokens()
825 .filter_map(SyntaxElement::into_token)
826 .find(|token| token.kind() == SyntaxKind::Ident)
827 }
828}
829
830impl AstPairBinding {
831 pub fn first(&self) -> Option<AstBinding> {
832 self.syntax().children().find_map(AstBinding::cast)
833 }
834
835 pub fn rest(&self) -> Option<AstBinding> {
836 self.syntax().children().filter_map(AstBinding::cast).nth(1)
837 }
838}
839
840impl AstListBinding {
841 pub fn items(&self) -> impl Iterator<Item = AstListBindingItem> {
842 self.syntax()
843 .children()
844 .filter_map(AstListBindingItem::cast)
845 }
846}
847
848impl AstListBindingItem {
849 pub fn spread(&self) -> Option<SyntaxToken> {
850 self.syntax()
851 .children_with_tokens()
852 .filter_map(SyntaxElement::into_token)
853 .find(|token| token.kind() == T![...])
854 }
855
856 pub fn binding(&self) -> Option<AstBinding> {
857 self.syntax().children().find_map(AstBinding::cast)
858 }
859}
860
861impl AstStructBinding {
862 pub fn fields(&self) -> impl Iterator<Item = AstStructFieldBinding> {
863 self.syntax()
864 .children()
865 .filter_map(AstStructFieldBinding::cast)
866 }
867}
868
869impl AstStructFieldBinding {
870 pub fn name(&self) -> Option<SyntaxToken> {
871 self.syntax()
872 .children_with_tokens()
873 .filter_map(SyntaxElement::into_token)
874 .find(|token| token.kind() == SyntaxKind::Ident)
875 }
876
877 pub fn binding(&self) -> Option<AstBinding> {
878 self.syntax().children().find_map(AstBinding::cast)
879 }
880}