1use crate::{ast::*, language::RustLanguage, lexer::RustTokenType, parser::RustElementType};
2use core::range::Range;
3use oak_core::{BuilderCache, RedNode, RedTree, SourceText};
4
5impl<'config> super::RustBuilder<'config> {
6 pub fn build_generics_and_where(&self, node: RedNode<RustLanguage>, source: &SourceText) -> Result<Option<Generics>, oak_core::OakError> {
8 let mut params = Vec::new();
9 let mut where_clause = None;
10 let mut generics_span: Option<Range<usize>> = None;
11
12 let children: Vec<_> = node.children().collect();
13 let mut i = 0;
14 while i < children.len() {
15 match &children[i] {
16 RedTree::Leaf(t) if t.kind == RustTokenType::Lt => {
17 let start = t.span.start;
18 let mut j = i + 1;
19 while j < children.len() {
20 if let RedTree::Leaf(t_end) = &children[j] {
21 if t_end.kind == RustTokenType::Gt {
22 generics_span = Some(Range { start, end: t_end.span.end });
23 params = self.parse_generic_params(&children[i + 1..j], source)?;
25 i = j;
26 break;
27 }
28 }
29 j += 1;
30 }
31 }
32 RedTree::Leaf(t) if t.kind == RustTokenType::Where => {
33 let start = t.span.start;
34 let mut j = i + 1;
36 while j < children.len() {
37 match &children[j] {
38 RedTree::Leaf(t_end) if t_end.kind == RustTokenType::LeftBrace || t_end.kind == RustTokenType::Semicolon => {
39 let end = t_end.span.start;
40 where_clause = Some(self.parse_where_clause(&children[i + 1..j], Range { start, end }, source)?);
41 i = j - 1;
42 break;
43 }
44 _ => j += 1,
45 }
46 }
47 }
48 _ => {}
49 }
50 i += 1;
51 }
52
53 if params.is_empty() && where_clause.is_none() {
54 Ok(None)
55 }
56 else {
57 let span = match (generics_span, &where_clause) {
58 (Some(g), Some(w)) => Range { start: g.start, end: w.span.end },
59 (Some(g), None) => g,
60 (None, Some(w)) => w.span.clone(),
61 (None, None) => Range { start: 0, end: 0 },
62 };
63 Ok(Some(Generics { params, where_clause, span }))
64 }
65 }
66
67 fn parse_generic_params(&self, children: &[RedTree<RustLanguage>], source: &SourceText) -> Result<Vec<GenericParam>, oak_core::OakError> {
68 let mut params = Vec::new();
69 let mut current_start = 0;
70
71 while current_start < children.len() {
72 let mut current_end = current_start;
74 while current_end < children.len() {
75 if let RedTree::Leaf(t) = &children[current_end] {
76 if t.kind == RustTokenType::Comma {
77 break;
78 }
79 }
80 current_end += 1;
81 }
82
83 if current_start < current_end {
84 params.push(self.parse_single_generic_param(&children[current_start..current_end], source)?);
85 }
86
87 current_start = current_end + 1;
88 }
89
90 Ok(params)
91 }
92
93 fn parse_single_generic_param(&self, children: &[RedTree<RustLanguage>], source: &SourceText) -> Result<GenericParam, oak_core::OakError> {
94 if children.is_empty() {
95 return Err(oak_core::OakError::syntax_error("Empty generic parameter".to_string(), 0, None));
96 }
97
98 let mut i = 0;
100 while i < children.len() {
101 if let RedTree::Leaf(t) = &children[i] {
102 if t.kind == RustTokenType::Hash {
103 let mut j = i + 1;
105 let mut bracket_count = 0;
106 while j < children.len() {
107 if let RedTree::Leaf(t_inner) = &children[j] {
108 if t_inner.kind == RustTokenType::LeftBracket {
109 bracket_count += 1;
110 }
111 else if t_inner.kind == RustTokenType::RightBracket {
112 bracket_count -= 1;
113 if bracket_count == 0 {
114 i = j;
115 break;
116 }
117 }
118 }
119 j += 1;
120 }
121 }
122 else {
123 break;
124 }
125 }
126 else {
127 break;
128 }
129 i += 1;
130 }
131
132 let remaining = &children[i..];
133 if remaining.is_empty() {
134 return Err(oak_core::OakError::syntax_error("Generic parameter name missing after attributes".to_string(), children[0].span().start, None));
135 }
136
137 if let RedTree::Leaf(t) = &remaining[0] {
139 if t.kind == RustTokenType::Lifetime {
140 let lifetime = Lifetime { name: crate::builder::text(source, t.span.clone().into()), span: t.span.clone().into() };
141
142 let mut bounds = Vec::new();
143 if remaining.len() > 1 {
144 if let RedTree::Leaf(t_colon) = &remaining[1] {
145 if t_colon.kind == RustTokenType::Colon {
146 for child in &remaining[2..] {
147 if let RedTree::Leaf(t_bound) = child {
148 if t_bound.kind == RustTokenType::Lifetime {
149 bounds.push(Lifetime { name: crate::builder::text(source, t_bound.span.clone().into()), span: t_bound.span.clone().into() });
150 }
151 }
152 }
153 }
154 }
155 }
156 return Ok(GenericParam::Lifetime(lifetime));
160 }
161 }
162
163 if let RedTree::Leaf(t) = &remaining[0] {
165 if t.kind == RustTokenType::Const {
166 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
167 let mut ty = Type::Path("usize".to_string()); let mut default = None;
169
170 let mut j = 1;
171 while j < remaining.len() {
172 match &remaining[j] {
173 RedTree::Leaf(t_id) if t_id.kind == RustTokenType::Identifier => {
174 name.name = crate::builder::text(source, t_id.span.clone().into());
175 name.span = t_id.span.clone().into();
176 }
177 RedTree::Leaf(t_colon) if t_colon.kind == RustTokenType::Colon => {
178 if j + 1 < remaining.len() {
179 if let RedTree::Node(n_ty) = &remaining[j + 1] {
180 ty = self.build_type(n_ty.clone(), source)?;
181 j += 1;
182 }
183 }
184 }
185 RedTree::Leaf(t_eq) if t_eq.kind == RustTokenType::Eq => {
186 if j + 1 < remaining.len() {
187 if let RedTree::Node(n_expr) = &remaining[j + 1] {
188 default = Some(self.build_expr(n_expr.clone(), source)?);
189 j += 1;
190 }
191 }
192 }
193 _ => {}
194 }
195 j += 1;
196 }
197 return Ok(GenericParam::Const { name, ty, default });
198 }
199 }
200
201 let mut name = Identifier { name: String::new(), span: Range { start: 0, end: 0 } };
203 let mut bounds = Vec::new();
204 let mut default = None;
205
206 let mut j = 0;
207 while j < remaining.len() {
208 match &remaining[j] {
209 RedTree::Leaf(t_id) if t_id.kind == RustTokenType::Identifier => {
210 name.name = crate::builder::text(source, t_id.span.clone().into());
211 name.span = t_id.span.clone().into();
212 }
213 RedTree::Leaf(t_colon) if t_colon.kind == RustTokenType::Colon => {
214 let mut k = j + 1;
215 while k < remaining.len() {
216 if let RedTree::Leaf(t_eq) = &remaining[k] {
217 if t_eq.kind == RustTokenType::Eq {
218 break;
219 }
220 }
221 k += 1;
222 }
223 bounds = self.parse_type_param_bounds(&remaining[j + 1..k], source)?;
224 j = k - 1;
225 }
226 RedTree::Leaf(t_eq) if t_eq.kind == RustTokenType::Eq => {
227 if j + 1 < remaining.len() {
228 if let RedTree::Node(n_ty) = &remaining[j + 1] {
229 default = Some(self.build_type(n_ty.clone(), source)?);
230 j += 1;
231 }
232 }
233 }
234 _ => {}
235 }
236 j += 1;
237 }
238
239 Ok(GenericParam::Type { name, bounds, default })
240 }
241
242 fn parse_type_param_bounds(&self, children: &[RedTree<RustLanguage>], source: &SourceText) -> Result<Vec<TypeParamBound>, oak_core::OakError> {
243 let mut bounds = Vec::new();
244 for child in children {
245 match child {
246 RedTree::Leaf(t) if t.kind == RustTokenType::Lifetime => {
247 bounds.push(TypeParamBound::Lifetime(Lifetime { name: crate::builder::text(source, t.span.clone().into()), span: t.span.clone().into() }));
248 }
249 RedTree::Node(n) => {
250 bounds.push(TypeParamBound::Trait(self.build_type(n.clone(), source)?));
251 }
252 _ => {}
253 }
254 }
255 Ok(bounds)
256 }
257
258 fn parse_where_clause(&self, children: &[RedTree<RustLanguage>], span: Range<usize>, source: &SourceText) -> Result<WhereClause, oak_core::OakError> {
259 let mut predicates = Vec::new();
260 let mut current_start = 0;
261
262 while current_start < children.len() {
263 let mut current_end = current_start;
264 while current_end < children.len() {
265 if let RedTree::Leaf(t) = &children[current_end] {
266 if t.kind == RustTokenType::Comma {
267 break;
268 }
269 }
270 current_end += 1;
271 }
272
273 if current_start < current_end {
274 predicates.push(self.parse_where_predicate(&children[current_start..current_end], source)?);
275 }
276
277 current_start = current_end + 1;
278 }
279
280 Ok(WhereClause { predicates, span })
281 }
282
283 fn parse_where_predicate(&self, children: &[RedTree<RustLanguage>], source: &SourceText) -> Result<WherePredicate, oak_core::OakError> {
284 let mut colon_idx = None;
285 for (i, child) in children.iter().enumerate() {
286 if let RedTree::Leaf(t) = child {
287 if t.kind == RustTokenType::Colon {
288 colon_idx = Some(i);
289 break;
290 }
291 }
292 }
293
294 if let Some(idx) = colon_idx {
295 let left = &children[..idx];
296 let right = &children[idx + 1..];
297
298 if left.len() == 1 {
299 if let RedTree::Leaf(t) = &left[0] {
300 if t.kind == RustTokenType::Lifetime {
301 let lifetime = Lifetime { name: crate::builder::text(source, t.span.clone().into()), span: t.span.clone().into() };
302 let mut bounds = Vec::new();
303 for child in right {
304 if let RedTree::Leaf(t_bound) = child {
305 if t_bound.kind == RustTokenType::Lifetime {
306 bounds.push(Lifetime { name: crate::builder::text(source, t_bound.span.clone().into()), span: t_bound.span.clone().into() });
307 }
308 }
309 }
310 return Ok(WherePredicate::Lifetime { lifetime, bounds });
311 }
312 }
313 }
314
315 let bounded_ty = if left.len() == 1 {
316 if let RedTree::Node(n) = &left[0] { self.build_type(n.clone(), source)? } else { Type::Path(crate::builder::text(source, left[0].span().into())) }
317 }
318 else {
319 Type::Path(crate::builder::text(source, Range { start: left[0].span().start, end: left.last().unwrap().span().end }))
320 };
321
322 let bounds = self.parse_type_param_bounds(right, source)?;
323 Ok(WherePredicate::Type { bounded_ty, bounds })
324 }
325 else {
326 Err(oak_core::OakError::syntax_error("Missing colon in where predicate".to_string(), children[0].span().start, None))
327 }
328 }
329}