bytebraise_syntax/syntax/ast/
mod.rs1use crate::syntax::syntax_kind::SyntaxKind;
5use std::marker::PhantomData;
6
7use crate::syntax::syntax_node::{SyntaxNode, SyntaxNodeChildren, SyntaxToken};
8
9pub mod nodes;
10pub mod quoted_value;
11pub mod tokens;
12
13pub trait AstNode {
18 fn can_cast(kind: SyntaxKind) -> bool
19 where
20 Self: Sized;
21
22 fn cast(syntax: SyntaxNode) -> Option<Self>
23 where
24 Self: Sized;
25
26 fn syntax(&self) -> &SyntaxNode;
27
28 fn clone_for_update(&self) -> Self
29 where
30 Self: Sized,
31 {
32 Self::cast(self.syntax().clone_for_update()).unwrap()
33 }
34
35 fn clone_subtree(&self) -> Self
36 where
37 Self: Sized,
38 {
39 Self::cast(self.syntax().clone_subtree()).unwrap()
40 }
41}
42
43pub trait AstToken {
45 fn can_cast(token: SyntaxKind) -> bool
46 where
47 Self: Sized;
48
49 fn cast(syntax: SyntaxToken) -> Option<Self>
50 where
51 Self: Sized;
52
53 fn syntax(&self) -> &SyntaxToken;
54
55 fn text(&self) -> &str {
56 self.syntax().text()
57 }
58}
59
60#[macro_export]
61macro_rules! ast_node {
62 ($ast:ident, $kind:ident) => {
63 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
64 #[repr(transparent)]
65 pub struct $ast {
66 pub(crate) syntax: SyntaxNode,
67 }
68 impl $crate::syntax::ast::AstNode for $ast {
69 #[allow(unused)]
70 fn cast(node: SyntaxNode) -> Option<Self> {
71 if node.kind() == SyntaxKind::$kind {
72 Some(Self { syntax: node })
73 } else {
74 None
75 }
76 }
77
78 #[allow(unused)]
79 fn can_cast(kind: SyntaxKind) -> bool {
80 kind == SyntaxKind::$kind
81 }
82
83 #[allow(unused)]
84 fn syntax(&self) -> &SyntaxNode {
85 &self.syntax
86 }
87 }
88 };
89}
90
91#[macro_export]
92macro_rules! ast_token {
93 ($ast:ident, $kind:ident) => {
94 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
95 #[repr(transparent)]
96 pub struct $ast {
97 pub(crate) syntax: SyntaxToken,
98 }
99 impl $crate::syntax::ast::AstToken for $ast {
100 #[allow(unused)]
101 fn cast(token: SyntaxToken) -> Option<Self> {
102 if token.kind() == SyntaxKind::$kind {
103 Some(Self { syntax: token })
104 } else {
105 None
106 }
107 }
108
109 #[allow(unused)]
110 fn can_cast(kind: SyntaxKind) -> bool {
111 kind == SyntaxKind::$kind
112 }
113
114 #[allow(unused)]
115 fn syntax(&self) -> &SyntaxToken {
116 &self.syntax
117 }
118 }
119 };
120}
121
122#[derive(Debug, Clone)]
124pub struct AstChildren<N> {
125 inner: SyntaxNodeChildren,
126 ph: PhantomData<N>,
127}
128
129impl<N> AstChildren<N> {
130 fn new(parent: &SyntaxNode) -> Self {
131 AstChildren {
132 inner: parent.children(),
133 ph: PhantomData,
134 }
135 }
136}
137
138impl<N: AstNode> Iterator for AstChildren<N> {
139 type Item = N;
140 fn next(&mut self) -> Option<N> {
141 self.inner.find_map(N::cast)
142 }
143}
144
145pub mod support {
146 use super::{AstChildren, AstNode, SyntaxNode};
147 use crate::syntax::ast::AstToken;
148
149 pub(crate) fn child<N: AstNode>(parent: &SyntaxNode) -> Option<N> {
150 parent.children().find_map(N::cast)
151 }
152
153 pub(crate) fn children<N: AstNode>(parent: &SyntaxNode) -> AstChildren<N> {
154 AstChildren::new(parent)
155 }
156
157 pub(crate) fn token<N: AstToken>(parent: &SyntaxNode) -> Option<N> {
158 parent
159 .children_with_tokens()
160 .filter_map(|it| it.into_token())
161 .find_map(N::cast)
162 }
163}
164
165