1use crate::syntax::{SyntaxKind, SyntaxNode, SyntaxToken};
26
27#[derive(Debug, Clone, PartialEq, Eq, Hash)]
35pub enum Value {
36 Struct(Struct),
38 Tuple(Tuple),
40 List(List),
42 Map(Map),
44 EnumVariant(EnumVariant),
46 Unit(Unit),
48 Literal(Literal),
50 Error(SyntaxNode),
53}
54
55impl Value {
56 #[must_use]
62 pub fn cast(node: SyntaxNode) -> Option<Self> {
63 Some(match node.kind() {
64 SyntaxKind::Struct => Self::Struct(Struct(node)),
65 SyntaxKind::Tuple => Self::Tuple(Tuple(node)),
66 SyntaxKind::List => Self::List(List(node)),
67 SyntaxKind::Map => Self::Map(Map(node)),
68 SyntaxKind::EnumVariant => Self::EnumVariant(EnumVariant(node)),
69 SyntaxKind::Unit => Self::Unit(Unit(node)),
70 SyntaxKind::Literal => Self::Literal(Literal(node)),
71 SyntaxKind::Error => Self::Error(node),
72 _ => return None,
73 })
74 }
75
76 #[must_use]
78 pub fn syntax(&self) -> &SyntaxNode {
79 match self {
80 Self::Struct(n) => n.syntax(),
81 Self::Tuple(n) => n.syntax(),
82 Self::List(n) => n.syntax(),
83 Self::Map(n) => n.syntax(),
84 Self::EnumVariant(n) => n.syntax(),
85 Self::Unit(n) => n.syntax(),
86 Self::Literal(n) => n.syntax(),
87 Self::Error(n) => n,
88 }
89 }
90}
91
92fn first_value_child(parent: &SyntaxNode) -> Option<Value> {
98 parent.children().find_map(Value::cast)
99}
100
101#[derive(Debug, Clone, PartialEq, Eq, Hash)]
106pub struct Document(SyntaxNode);
107
108impl Document {
109 #[must_use]
111 pub fn cast(node: SyntaxNode) -> Option<Self> {
112 (node.kind() == SyntaxKind::Root).then_some(Self(node))
113 }
114
115 #[must_use]
117 pub fn syntax(&self) -> &SyntaxNode {
118 &self.0
119 }
120
121 #[must_use]
124 pub fn value(&self) -> Option<Value> {
125 first_value_child(&self.0)
126 }
127
128 pub fn extension_attrs(&self) -> impl Iterator<Item = ExtensionAttr> + '_ {
130 self.0.children().filter_map(ExtensionAttr::cast)
131 }
132}
133
134#[derive(Debug, Clone, PartialEq, Eq, Hash)]
136pub struct Struct(SyntaxNode);
137
138impl Struct {
139 #[must_use]
141 pub fn cast(node: SyntaxNode) -> Option<Self> {
142 (node.kind() == SyntaxKind::Struct).then_some(Self(node))
143 }
144
145 #[must_use]
147 pub fn syntax(&self) -> &SyntaxNode {
148 &self.0
149 }
150
151 #[must_use]
154 pub fn name(&self) -> Option<SyntaxToken> {
155 self.0.first_token_of(SyntaxKind::Ident)
156 }
157
158 #[must_use]
160 pub fn name_text(&self) -> Option<String> {
161 self.name().map(|t| t.text().to_string())
162 }
163
164 pub fn fields(&self) -> impl Iterator<Item = StructField> + '_ {
166 self.0.children().filter_map(StructField::cast)
167 }
168}
169
170#[derive(Debug, Clone, PartialEq, Eq, Hash)]
172pub struct StructField(SyntaxNode);
173
174impl StructField {
175 #[must_use]
177 pub fn cast(node: SyntaxNode) -> Option<Self> {
178 (node.kind() == SyntaxKind::StructField).then_some(Self(node))
179 }
180
181 #[must_use]
183 pub fn syntax(&self) -> &SyntaxNode {
184 &self.0
185 }
186
187 #[must_use]
189 pub fn name(&self) -> Option<SyntaxToken> {
190 self.0.first_token_of(SyntaxKind::Ident)
191 }
192
193 #[must_use]
195 pub fn name_text(&self) -> Option<String> {
196 self.name().map(|t| t.text().to_string())
197 }
198
199 #[must_use]
201 pub fn value(&self) -> Option<Value> {
202 first_value_child(&self.0)
203 }
204}
205
206#[derive(Debug, Clone, PartialEq, Eq, Hash)]
208pub struct Tuple(SyntaxNode);
209
210impl Tuple {
211 #[must_use]
213 pub fn cast(node: SyntaxNode) -> Option<Self> {
214 (node.kind() == SyntaxKind::Tuple).then_some(Self(node))
215 }
216
217 #[must_use]
219 pub fn syntax(&self) -> &SyntaxNode {
220 &self.0
221 }
222
223 pub fn items(&self) -> impl Iterator<Item = Value> + '_ {
225 self.0.children().filter_map(Value::cast)
226 }
227}
228
229#[derive(Debug, Clone, PartialEq, Eq, Hash)]
231pub struct List(SyntaxNode);
232
233impl List {
234 #[must_use]
236 pub fn cast(node: SyntaxNode) -> Option<Self> {
237 (node.kind() == SyntaxKind::List).then_some(Self(node))
238 }
239
240 #[must_use]
242 pub fn syntax(&self) -> &SyntaxNode {
243 &self.0
244 }
245
246 pub fn items(&self) -> impl Iterator<Item = Value> + '_ {
248 self.0.children().filter_map(Value::cast)
249 }
250}
251
252#[derive(Debug, Clone, PartialEq, Eq, Hash)]
254pub struct Map(SyntaxNode);
255
256impl Map {
257 #[must_use]
259 pub fn cast(node: SyntaxNode) -> Option<Self> {
260 (node.kind() == SyntaxKind::Map).then_some(Self(node))
261 }
262
263 #[must_use]
265 pub fn syntax(&self) -> &SyntaxNode {
266 &self.0
267 }
268
269 pub fn entries(&self) -> impl Iterator<Item = MapEntry> + '_ {
271 self.0.children().filter_map(MapEntry::cast)
272 }
273}
274
275#[derive(Debug, Clone, PartialEq, Eq, Hash)]
277pub struct MapEntry(SyntaxNode);
278
279impl MapEntry {
280 #[must_use]
282 pub fn cast(node: SyntaxNode) -> Option<Self> {
283 (node.kind() == SyntaxKind::MapEntry).then_some(Self(node))
284 }
285
286 #[must_use]
288 pub fn syntax(&self) -> &SyntaxNode {
289 &self.0
290 }
291
292 #[must_use]
295 pub fn key(&self) -> Option<Value> {
296 self.0.children().filter_map(Value::cast).next()
297 }
298
299 #[must_use]
301 pub fn value(&self) -> Option<Value> {
302 self.0.children().filter_map(Value::cast).nth(1)
303 }
304}
305
306#[derive(Debug, Clone, PartialEq, Eq, Hash)]
308pub struct EnumVariant(SyntaxNode);
309
310impl EnumVariant {
311 #[must_use]
313 pub fn cast(node: SyntaxNode) -> Option<Self> {
314 (node.kind() == SyntaxKind::EnumVariant).then_some(Self(node))
315 }
316
317 #[must_use]
319 pub fn syntax(&self) -> &SyntaxNode {
320 &self.0
321 }
322
323 #[must_use]
325 pub fn name(&self) -> Option<SyntaxToken> {
326 self.0.first_token_of(SyntaxKind::Ident)
327 }
328
329 #[must_use]
331 pub fn name_text(&self) -> Option<String> {
332 self.name().map(|t| t.text().to_string())
333 }
334
335 pub fn entries(&self) -> impl Iterator<Item = MapEntry> + '_ {
338 self.0.children().filter_map(MapEntry::cast)
339 }
340}
341
342#[derive(Debug, Clone, PartialEq, Eq, Hash)]
344pub struct Unit(SyntaxNode);
345
346impl Unit {
347 #[must_use]
349 pub fn cast(node: SyntaxNode) -> Option<Self> {
350 (node.kind() == SyntaxKind::Unit).then_some(Self(node))
351 }
352
353 #[must_use]
355 pub fn syntax(&self) -> &SyntaxNode {
356 &self.0
357 }
358}
359
360#[derive(Debug, Clone, PartialEq, Eq, Hash)]
362pub struct Literal(SyntaxNode);
363
364impl Literal {
365 #[must_use]
367 pub fn cast(node: SyntaxNode) -> Option<Self> {
368 (node.kind() == SyntaxKind::Literal).then_some(Self(node))
369 }
370
371 #[must_use]
373 pub fn syntax(&self) -> &SyntaxNode {
374 &self.0
375 }
376
377 #[must_use]
379 pub fn token(&self) -> Option<SyntaxToken> {
380 self.0
381 .children_with_tokens()
382 .filter_map(|el| el.as_token().cloned())
383 .find(|t| !t.is_trivia())
384 }
385
386 #[must_use]
389 pub fn token_kind(&self) -> Option<SyntaxKind> {
390 self.token().map(|t| t.kind())
391 }
392
393 #[must_use]
396 pub fn text(&self) -> Option<String> {
397 self.token().map(|t| t.text().to_string())
398 }
399}
400
401#[derive(Debug, Clone, PartialEq, Eq, Hash)]
403pub struct ExtensionAttr(SyntaxNode);
404
405impl ExtensionAttr {
406 #[must_use]
408 pub fn cast(node: SyntaxNode) -> Option<Self> {
409 (node.kind() == SyntaxKind::ExtensionAttr).then_some(Self(node))
410 }
411
412 #[must_use]
414 pub fn syntax(&self) -> &SyntaxNode {
415 &self.0
416 }
417
418 pub fn extensions(&self) -> impl Iterator<Item = SyntaxToken> + '_ {
421 self.0
422 .children_with_tokens()
423 .filter_map(|el| el.as_token().cloned())
424 .filter(|t| t.kind() == SyntaxKind::Ident)
425 }
426}
427
428#[cfg(test)]
429mod tests {
430 use super::*;
431 use crate::parser::parse;
432
433 fn doc_of(src: &str) -> Document {
435 Document::cast(parse(src).root()).expect("root is always a Document")
436 }
437
438 #[test]
439 fn struct_fields_and_name() {
440 let d = doc_of("Point(x: 1, y: -2.0)");
441 let Some(Value::Struct(s)) = d.value() else {
442 panic!("expected a struct");
443 };
444 assert_eq!(s.name_text().as_deref(), Some("Point"));
445 let fields: Vec<_> = s.fields().collect();
446 assert_eq!(fields.len(), 2);
447 assert_eq!(fields[0].name_text().as_deref(), Some("x"));
448 assert_eq!(fields[1].name_text().as_deref(), Some("y"));
449 let Some(Value::Literal(lit)) = fields[0].value() else {
451 panic!("x should be a literal");
452 };
453 assert_eq!(lit.text().as_deref(), Some("1"));
454 assert_eq!(lit.token_kind(), Some(SyntaxKind::Integer));
455 }
456
457 #[test]
458 fn anonymous_struct_has_no_name() {
459 let d = doc_of("(a: 1, b: 2)");
460 let Some(Value::Struct(s)) = d.value() else {
461 panic!("expected a struct");
462 };
463 assert_eq!(s.name_text(), None);
464 assert_eq!(s.fields().count(), 2);
465 }
466
467 #[test]
468 fn list_items() {
469 let d = doc_of("[1, 2, 3,]");
470 let Some(Value::List(list)) = d.value() else {
471 panic!("expected a list");
472 };
473 let items: Vec<_> = list.items().collect();
474 assert_eq!(items.len(), 3);
475 for it in &items {
476 assert!(matches!(it, Value::Literal(_)));
477 }
478 }
479
480 #[test]
481 fn tuple_items() {
482 let d = doc_of("(1, \"two\", 'c')");
483 let Some(Value::Tuple(t)) = d.value() else {
484 panic!("expected a tuple");
485 };
486 assert_eq!(t.items().count(), 3);
487 }
488
489 #[test]
490 fn map_entries_with_non_string_keys() {
491 let d = doc_of("{ 1: \"one\", 'c': true }");
492 let Some(Value::Map(m)) = d.value() else {
493 panic!("expected a map");
494 };
495 let entries: Vec<_> = m.entries().collect();
496 assert_eq!(entries.len(), 2);
497 let Some(Value::Literal(k0)) = entries[0].key() else {
499 panic!("key 0 should be a literal");
500 };
501 assert_eq!(k0.token_kind(), Some(SyntaxKind::Integer));
502 let Some(Value::Literal(v0)) = entries[0].value() else {
503 panic!("value 0 should be a literal");
504 };
505 assert_eq!(v0.token_kind(), Some(SyntaxKind::String));
506 }
507
508 #[test]
509 fn enum_variant_struct_like() {
510 let d = doc_of("Variant { field: 1 }");
511 let Some(Value::EnumVariant(v)) = d.value() else {
512 panic!("expected an enum variant");
513 };
514 assert_eq!(v.name_text().as_deref(), Some("Variant"));
515 assert_eq!(v.entries().count(), 1);
516 }
517
518 #[test]
519 fn bare_enum_variant() {
520 let d = doc_of("Unit");
521 let Some(Value::EnumVariant(v)) = d.value() else {
522 panic!("expected a bare variant");
523 };
524 assert_eq!(v.name_text().as_deref(), Some("Unit"));
525 assert_eq!(v.entries().count(), 0);
526 }
527
528 #[test]
529 fn unit_value() {
530 let d = doc_of("()");
531 assert!(matches!(d.value(), Some(Value::Unit(_))));
532 }
533
534 #[test]
535 fn literal_text_is_verbatim() {
536 let d = doc_of("r#\"raw \"q\" str\"#");
537 let Some(Value::Literal(lit)) = d.value() else {
538 panic!("expected a literal");
539 };
540 assert_eq!(lit.token_kind(), Some(SyntaxKind::RawString));
541 assert_eq!(lit.text().as_deref(), Some("r#\"raw \"q\" str\"#"));
542 }
543
544 #[test]
545 fn extension_attrs_and_value() {
546 let d = doc_of("#![enable(implicit_some)]\nSome(5)");
547 let attrs: Vec<_> = d.extension_attrs().collect();
548 assert_eq!(attrs.len(), 1);
549 let exts: Vec<_> = attrs[0]
550 .extensions()
551 .map(|t| t.text().to_string())
552 .collect();
553 assert!(exts.contains(&"implicit_some".to_string()));
555 assert!(d.value().is_some());
557 }
558
559 #[test]
560 fn error_value_is_reachable() {
561 let d = doc_of("@");
564 assert!(matches!(d.value(), Some(Value::Error(_))));
565 }
566
567 #[test]
568 fn value_syntax_round_trips_text() {
569 let src = "Foo(x: [1, 2], y: { 'a': 'b' })";
570 let d = doc_of(src);
571 let v = d.value().expect("has a value");
572 assert_eq!(v.syntax().text(), src);
574 }
575}