squawk_syntax/ast/
node_ext.rs1use std::borrow::Cow;
28
29use rowan::{GreenNodeData, GreenTokenData, NodeOrToken};
30
31use crate::ast;
32use crate::ast::AstNode;
33use crate::{SyntaxNode, TokenText};
34
35use super::support;
36
37impl ast::Constraint {
38 #[inline]
39 pub fn name(&self) -> Option<ast::Name> {
40 support::child(self.syntax())
41 }
42}
43
44impl ast::BinExpr {
45 #[inline]
46 pub fn lhs(&self) -> Option<ast::Expr> {
47 support::children(self.syntax()).next()
48 }
49
50 #[inline]
51 pub fn rhs(&self) -> Option<ast::Expr> {
52 support::children(self.syntax()).nth(1)
53 }
54}
55
56impl ast::FieldExpr {
57 #[inline]
61 pub fn base(&self) -> Option<ast::Expr> {
62 support::children(self.syntax()).next()
63 }
64 #[inline]
65 pub fn field(&self) -> Option<ast::NameRef> {
66 support::children(self.syntax()).last()
67 }
68}
69
70impl ast::IndexExpr {
71 #[inline]
72 pub fn base(&self) -> Option<ast::Expr> {
73 support::children(&self.syntax).next()
74 }
75 #[inline]
76 pub fn index(&self) -> Option<ast::Expr> {
77 support::children(&self.syntax).nth(1)
78 }
79}
80
81impl ast::SliceExpr {
82 #[inline]
83 pub fn base(&self) -> Option<ast::Expr> {
84 support::children(&self.syntax).next()
85 }
86
87 #[inline]
88 pub fn start(&self) -> Option<ast::Expr> {
89 let colon = self.colon_token()?;
94 support::children(&self.syntax)
95 .skip(1)
96 .find(|expr: &ast::Expr| expr.syntax().text_range().end() <= colon.text_range().start())
97 }
98
99 #[inline]
100 pub fn end(&self) -> Option<ast::Expr> {
101 let colon = self.colon_token()?;
104 support::children(&self.syntax)
105 .find(|expr: &ast::Expr| expr.syntax().text_range().start() >= colon.text_range().end())
106 }
107}
108
109impl ast::RenameColumn {
110 #[inline]
111 pub fn from(&self) -> Option<ast::NameRef> {
112 support::children(&self.syntax).nth(0)
113 }
114 #[inline]
115 pub fn to(&self) -> Option<ast::NameRef> {
116 support::children(&self.syntax).nth(1)
117 }
118}
119
120impl ast::ForeignKeyConstraint {
121 #[inline]
122 pub fn from_columns(&self) -> Option<ast::ColumnList> {
123 support::children(&self.syntax).nth(0)
124 }
125 #[inline]
126 pub fn to_columns(&self) -> Option<ast::ColumnList> {
127 support::children(&self.syntax).nth(1)
128 }
129}
130
131impl ast::BetweenExpr {
132 #[inline]
133 pub fn target(&self) -> Option<ast::Expr> {
134 support::children(&self.syntax).nth(0)
135 }
136 #[inline]
137 pub fn start(&self) -> Option<ast::Expr> {
138 support::children(&self.syntax).nth(1)
139 }
140 #[inline]
141 pub fn end(&self) -> Option<ast::Expr> {
142 support::children(&self.syntax).nth(2)
143 }
144}
145
146impl ast::WhenClause {
147 #[inline]
148 pub fn condition(&self) -> Option<ast::Expr> {
149 support::children(&self.syntax).next()
150 }
151 #[inline]
152 pub fn then(&self) -> Option<ast::Expr> {
153 support::children(&self.syntax).nth(1)
154 }
155}
156
157impl ast::CompoundSelect {
158 #[inline]
159 pub fn lhs(&self) -> Option<ast::SelectVariant> {
160 support::children(&self.syntax).next()
161 }
162 #[inline]
163 pub fn rhs(&self) -> Option<ast::SelectVariant> {
164 support::children(&self.syntax).nth(1)
165 }
166}
167
168impl ast::NameRef {
169 #[inline]
170 pub fn text(&self) -> TokenText<'_> {
171 text_of_first_token(self.syntax())
172 }
173}
174
175impl ast::Name {
176 #[inline]
177 pub fn text(&self) -> TokenText<'_> {
178 text_of_first_token(self.syntax())
179 }
180}
181
182impl ast::CharType {
183 #[inline]
184 pub fn text(&self) -> TokenText<'_> {
185 text_of_first_token(self.syntax())
186 }
187}
188
189pub(crate) fn text_of_first_token(node: &SyntaxNode) -> TokenText<'_> {
190 fn first_token(green_ref: &GreenNodeData) -> &GreenTokenData {
191 green_ref
192 .children()
193 .next()
194 .and_then(NodeOrToken::into_token)
195 .unwrap()
196 }
197
198 match node.green() {
199 Cow::Borrowed(green_ref) => TokenText::borrowed(first_token(green_ref).text()),
200 Cow::Owned(green) => TokenText::owned(first_token(&green).to_owned()),
201 }
202}