1use crate::document::constructor::{DocumentConstructor, Scope as InnerScope};
21use crate::document::interpreter_sink::InterpreterSink;
22use crate::document::{ConstructorError, InsertError, NodeId};
23use crate::path::PathSegment;
24use crate::prelude_internal::*;
25use crate::source::{
26 BindingSource, Comment, EureSource, SectionSource, SourceDocument, SourceId, SourceKey,
27 SourcePath, SourcePathSegment, Trivia,
28};
29
30#[derive(Debug)]
32enum BuilderContext {
33 EureBlock {
35 source_id: SourceId,
37 saved_path: SourcePath,
39 saved_trivia: Vec<Trivia>,
41 },
42 SectionItems {
44 trivia_before: Vec<Trivia>,
46 path: SourcePath,
48 value: Option<NodeId>,
50 bindings: Vec<BindingSource>,
52 },
53}
54
55pub struct SourceConstructor {
92 inner: DocumentConstructor,
94
95 sources: Vec<EureSource>,
97
98 builder_stack: Vec<BuilderContext>,
100
101 pending_path: Vec<SourcePathSegment>,
103
104 pending_trivia: Vec<Trivia>,
106
107 last_bound_node: Option<NodeId>,
109
110 last_block_id: Option<SourceId>,
112
113 skip_path_restore_for_next_scope: bool,
116
117 suspended_path_tracking: usize,
119}
120
121#[derive(Debug, Clone)]
127pub struct Scope {
128 inner: InnerScope,
129 pending_path: SourcePath,
130 restore_pending_path: bool,
131}
132
133impl Default for SourceConstructor {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139impl SourceConstructor {
140 #[must_use]
142 pub fn new() -> Self {
143 let sources = vec![EureSource::default()];
145
146 Self {
147 inner: DocumentConstructor::new(),
148 sources,
149 builder_stack: vec![BuilderContext::EureBlock {
150 source_id: SourceId(0),
151 saved_path: Vec::new(),
152 saved_trivia: Vec::new(),
153 }],
154 pending_path: Vec::new(),
155 pending_trivia: Vec::new(),
156 last_bound_node: None,
157 last_block_id: None,
158 skip_path_restore_for_next_scope: false,
159 suspended_path_tracking: 0,
160 }
161 }
162
163 #[must_use]
165 pub fn finish(mut self) -> SourceDocument {
166 if !self.pending_trivia.is_empty() {
168 self.sources[0].trailing_trivia = std::mem::take(&mut self.pending_trivia);
169 }
170 SourceDocument::new(self.inner.finish(), self.sources)
171 }
172
173 fn current_source_mut(&mut self) -> &mut EureSource {
177 for ctx in self.builder_stack.iter().rev() {
178 if let BuilderContext::EureBlock { source_id, .. } = ctx {
179 return &mut self.sources[source_id.0];
180 }
181 }
182 &mut self.sources[0]
184 }
185
186 pub fn begin_scope(&mut self) -> Scope {
195 InterpreterSink::begin_scope(self)
196 }
197
198 pub fn end_scope(&mut self, scope: Scope) -> Result<(), InsertError> {
200 InterpreterSink::end_scope(self, scope)
201 }
202
203 pub fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, InsertError> {
205 InterpreterSink::navigate(self, segment)
206 }
207
208 pub fn navigate_partial_map_entry(
210 &mut self,
211 key: crate::value::PartialObjectKey,
212 ) -> Result<NodeId, InsertError> {
213 self.pending_path.push(SourcePathSegment {
214 key: Self::partial_object_key_to_source_key(&key),
215 array: None,
216 });
217 self.inner.navigate_partial_map_entry(key)
218 }
219
220 pub fn require_hole(&self) -> Result<(), InsertError> {
222 InterpreterSink::require_hole(self)
223 }
224
225 pub fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), InsertError> {
227 InterpreterSink::bind_primitive(self, value)
228 }
229
230 pub fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), InsertError> {
232 InterpreterSink::bind_hole(self, label)
233 }
234
235 pub fn bind_empty_map(&mut self) -> Result<(), InsertError> {
237 InterpreterSink::bind_empty_map(self)
238 }
239
240 pub fn bind_empty_partial_map(&mut self) -> Result<(), InsertError> {
242 self.last_bound_node = Some(self.inner.current_node_id());
243 self.inner.bind_empty_partial_map()
244 }
245
246 pub fn bind_empty_array(&mut self) -> Result<(), InsertError> {
248 InterpreterSink::bind_empty_array(self)
249 }
250
251 pub fn bind_empty_tuple(&mut self) -> Result<(), InsertError> {
253 InterpreterSink::bind_empty_tuple(self)
254 }
255
256 pub fn bind_from(&mut self, value: impl Into<PrimitiveValue>) -> Result<(), InsertError> {
258 InterpreterSink::bind_from(self, value)
259 }
260
261 pub fn current_node_id(&self) -> NodeId {
263 InterpreterSink::current_node_id(self)
264 }
265
266 pub fn current_path(&self) -> &[PathSegment] {
268 InterpreterSink::current_path(self)
269 }
270
271 pub fn current_node(&self) -> &crate::document::node::Node {
273 self.inner.current_node()
274 }
275
276 pub fn current_node_mut(&mut self) -> &mut crate::document::node::Node {
278 self.inner.current_node_mut()
279 }
280
281 pub fn set_last_bound_node(&mut self, node_id: NodeId) {
283 self.last_bound_node = Some(node_id);
284 }
285
286 pub fn clone_pending_path(&self) -> SourcePath {
288 self.pending_path.clone()
289 }
290
291 pub fn set_pending_path(&mut self, path: SourcePath) {
293 self.pending_path = path;
294 }
295
296 pub fn suspend_path_tracking(&mut self) {
298 self.suspended_path_tracking += 1;
299 }
300
301 pub fn resume_path_tracking(&mut self) {
303 self.suspended_path_tracking = self.suspended_path_tracking.saturating_sub(1);
304 }
305
306 pub fn document(&self) -> &EureDocument {
308 InterpreterSink::document(self)
309 }
310
311 pub fn document_mut(&mut self) -> &mut EureDocument {
313 InterpreterSink::document_mut(self)
314 }
315
316 pub fn begin_eure_block(&mut self) {
322 InterpreterSink::begin_eure_block(self)
323 }
324
325 pub fn set_block_value(&mut self) -> Result<(), InsertError> {
327 InterpreterSink::set_block_value(self)
328 }
329
330 pub fn end_eure_block(&mut self) -> Result<(), InsertError> {
332 InterpreterSink::end_eure_block(self)
333 }
334
335 pub fn begin_binding(&mut self) {
337 InterpreterSink::begin_binding(self)
338 }
339
340 pub fn end_binding_value(&mut self) -> Result<(), InsertError> {
342 InterpreterSink::end_binding_value(self)
343 }
344
345 pub fn end_binding_block(&mut self) -> Result<(), InsertError> {
347 InterpreterSink::end_binding_block(self)
348 }
349
350 pub fn begin_section(&mut self) {
352 InterpreterSink::begin_section(self)
353 }
354
355 pub fn begin_section_items(&mut self) {
357 InterpreterSink::begin_section_items(self)
358 }
359
360 pub fn end_section_items(&mut self) -> Result<(), InsertError> {
362 InterpreterSink::end_section_items(self)
363 }
364
365 pub fn end_section_block(&mut self) -> Result<(), InsertError> {
367 InterpreterSink::end_section_block(self)
368 }
369
370 pub fn comment(&mut self, comment: Comment) {
372 InterpreterSink::comment(self, comment)
373 }
374
375 pub fn blank_line(&mut self) {
377 InterpreterSink::blank_line(self)
378 }
379
380 pub fn add_trivia(&mut self, trivia: Trivia) {
382 self.pending_trivia.push(trivia);
383 }
384
385 fn path_segment_to_source(segment: &PathSegment) -> SourcePathSegment {
391 match segment {
392 PathSegment::Ident(id) => SourcePathSegment::ident(id.clone()),
393 PathSegment::Extension(id) => SourcePathSegment::extension(id.clone()),
394 PathSegment::PartialValue(key) => SourcePathSegment {
395 key: Self::partial_object_key_to_source_key(key),
396 array: None,
397 },
398 PathSegment::HoleKey(label) => SourcePathSegment {
399 key: SourceKey::hole(label.clone()),
400 array: None,
401 },
402 PathSegment::Value(key) => SourcePathSegment {
403 key: Self::object_key_to_source_key(key),
404 array: None,
405 },
406 PathSegment::TupleIndex(idx) => SourcePathSegment {
407 key: SourceKey::TupleIndex(*idx),
408 array: None,
409 },
410 PathSegment::ArrayIndex(_) => {
411 unreachable!(
414 "ArrayIndex should be merged with previous segment, not converted directly"
415 )
416 }
417 }
418 }
419
420 fn partial_object_key_to_source_key(key: &crate::value::PartialObjectKey) -> SourceKey {
421 match key {
422 crate::value::PartialObjectKey::String(s) => {
423 if let Ok(id) = s.parse::<Identifier>() {
424 SourceKey::Ident(id)
425 } else {
426 SourceKey::quoted(s.clone())
427 }
428 }
429 crate::value::PartialObjectKey::Number(n) => {
430 if let Ok(n64) = i64::try_from(n) {
431 SourceKey::Integer(n64)
432 } else {
433 SourceKey::quoted(n.to_string())
434 }
435 }
436 crate::value::PartialObjectKey::Hole(label) => SourceKey::hole(label.clone()),
437 crate::value::PartialObjectKey::Tuple(keys) => SourceKey::Tuple(
438 keys.iter()
439 .map(Self::partial_object_key_to_source_key)
440 .collect(),
441 ),
442 }
443 }
444
445 fn object_key_to_source_key(key: &ObjectKey) -> SourceKey {
447 match key {
448 ObjectKey::String(s) => {
449 if let Ok(id) = s.parse::<Identifier>() {
451 SourceKey::Ident(id)
452 } else {
453 SourceKey::quoted(s.clone())
454 }
455 }
456 ObjectKey::Number(n) => {
457 if let Ok(n64) = i64::try_from(n) {
459 SourceKey::Integer(n64)
460 } else {
461 SourceKey::quoted(n.to_string())
462 }
463 }
464 ObjectKey::Tuple(keys) => {
465 SourceKey::Tuple(keys.iter().map(Self::object_key_to_source_key).collect())
466 }
467 }
468 }
469
470 fn push_binding(&mut self, mut binding: BindingSource) {
472 binding.trivia_before = std::mem::take(&mut self.pending_trivia);
474
475 match self.builder_stack.last_mut() {
476 Some(BuilderContext::SectionItems { bindings, .. }) => {
477 bindings.push(binding);
478 }
479 Some(BuilderContext::EureBlock { source_id, .. }) => {
480 self.sources[source_id.0].bindings.push(binding);
481 }
482 None => {
483 self.sources[0].bindings.push(binding);
485 }
486 }
487 }
488
489 fn push_section(&mut self, mut section: SectionSource, trivia: Vec<Trivia>) {
491 section.trivia_before = trivia;
493 self.current_source_mut().sections.push(section);
494 }
495}
496
497impl InterpreterSink for SourceConstructor {
498 type Error = InsertError;
499 type Scope = Scope;
500
501 fn begin_scope(&mut self) -> Self::Scope {
502 let restore_pending_path = !self.skip_path_restore_for_next_scope;
503 self.skip_path_restore_for_next_scope = false;
504 Scope {
505 inner: self.inner.begin_scope(),
506 pending_path: self.pending_path.clone(),
507 restore_pending_path,
508 }
509 }
510
511 fn end_scope(&mut self, scope: Self::Scope) -> Result<(), Self::Error> {
512 if scope.restore_pending_path {
513 self.pending_path = scope.pending_path;
514 }
515 InterpreterSink::end_scope(&mut self.inner, scope.inner)
516 }
517
518 fn navigate(&mut self, segment: PathSegment) -> Result<NodeId, Self::Error> {
519 if self.suspended_path_tracking == 0 {
520 if let PathSegment::ArrayIndex(idx) = &segment {
522 if let Some(last) = self.pending_path.last_mut() {
523 last.array = Some(*idx);
524 } else if !matches!(
525 self.builder_stack.last(),
526 Some(BuilderContext::SectionItems { .. })
527 ) {
528 return Err(InsertError {
529 kind: ConstructorError::StandaloneArrayIndex.into(),
530 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
531 });
532 }
533 } else {
534 let source_segment = Self::path_segment_to_source(&segment);
535 self.pending_path.push(source_segment);
536 }
537 }
538
539 InterpreterSink::navigate(&mut self.inner, segment)
540 }
541
542 fn require_hole(&self) -> Result<(), Self::Error> {
543 self.inner.require_hole()
544 }
545
546 fn bind_primitive(&mut self, value: PrimitiveValue) -> Result<(), Self::Error> {
547 self.last_bound_node = Some(self.inner.current_node_id());
548 InterpreterSink::bind_primitive(&mut self.inner, value)
549 }
550
551 fn bind_hole(&mut self, label: Option<Identifier>) -> Result<(), Self::Error> {
552 self.last_bound_node = Some(self.inner.current_node_id());
553 InterpreterSink::bind_hole(&mut self.inner, label)
554 }
555
556 fn bind_empty_map(&mut self) -> Result<(), Self::Error> {
557 self.last_bound_node = Some(self.inner.current_node_id());
558 InterpreterSink::bind_empty_map(&mut self.inner)
559 }
560
561 fn bind_empty_array(&mut self) -> Result<(), Self::Error> {
562 self.last_bound_node = Some(self.inner.current_node_id());
563 InterpreterSink::bind_empty_array(&mut self.inner)
564 }
565
566 fn bind_empty_tuple(&mut self) -> Result<(), Self::Error> {
567 self.last_bound_node = Some(self.inner.current_node_id());
568 InterpreterSink::bind_empty_tuple(&mut self.inner)
569 }
570
571 fn current_node_id(&self) -> NodeId {
572 self.inner.current_node_id()
573 }
574
575 fn current_path(&self) -> &[PathSegment] {
576 self.inner.current_path()
577 }
578
579 fn document(&self) -> &EureDocument {
580 self.inner.document()
581 }
582
583 fn document_mut(&mut self) -> &mut EureDocument {
584 self.inner.document_mut()
585 }
586
587 fn begin_eure_block(&mut self) {
592 let source_id = SourceId(self.sources.len());
594 self.sources.push(EureSource::default());
595
596 let saved_path = std::mem::take(&mut self.pending_path);
598 let saved_trivia = std::mem::take(&mut self.pending_trivia);
599
600 self.builder_stack.push(BuilderContext::EureBlock {
602 source_id,
603 saved_path,
604 saved_trivia,
605 });
606 }
607
608 fn set_block_value(&mut self) -> Result<(), Self::Error> {
609 let node_id = self.last_bound_node.take().ok_or_else(|| InsertError {
611 kind: ConstructorError::MissingBindBeforeSetBlockValue.into(),
612 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
613 })?;
614 self.current_source_mut().value = Some(node_id);
615 Ok(())
616 }
617
618 fn end_eure_block(&mut self) -> Result<(), Self::Error> {
619 if !self.pending_trivia.is_empty() {
621 let source_id = match self.builder_stack.last() {
622 Some(BuilderContext::EureBlock { source_id, .. }) => *source_id,
623 _ => {
624 return Err(InsertError {
625 kind: ConstructorError::InvalidBuilderStackForEndEureBlock.into(),
626 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
627 });
628 }
629 };
630 self.sources[source_id.0].trailing_trivia = std::mem::take(&mut self.pending_trivia);
631 }
632
633 match self.builder_stack.pop() {
635 Some(BuilderContext::EureBlock {
636 source_id,
637 saved_path,
638 saved_trivia,
639 }) => {
640 self.last_block_id = Some(source_id);
641 self.pending_path = saved_path;
643 self.pending_trivia = saved_trivia;
644 Ok(())
645 }
646 _ => Err(InsertError {
647 kind: ConstructorError::InvalidBuilderStackForEndEureBlock.into(),
648 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
649 }),
650 }
651 }
652
653 fn begin_binding(&mut self) {
654 self.pending_path.clear();
655 self.skip_path_restore_for_next_scope = true;
656 }
657
658 fn end_binding_value(&mut self) -> Result<(), Self::Error> {
659 let path = std::mem::take(&mut self.pending_path);
661 let node_id = self.last_bound_node.take().ok_or_else(|| InsertError {
662 kind: ConstructorError::MissingBindBeforeEndBindingValue.into(),
663 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
664 })?;
665
666 let binding = BindingSource::value(path, node_id);
667 self.push_binding(binding);
668 Ok(())
669 }
670
671 fn end_binding_block(&mut self) -> Result<(), Self::Error> {
672 let path = std::mem::take(&mut self.pending_path);
674 let source_id = self.last_block_id.take().ok_or_else(|| InsertError {
675 kind: ConstructorError::MissingEndEureBlockBeforeEndBindingBlock.into(),
676 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
677 })?;
678
679 let binding = BindingSource::block(path, source_id);
680 self.push_binding(binding);
681 Ok(())
682 }
683
684 fn begin_section(&mut self) {
685 self.pending_path.clear();
686 self.skip_path_restore_for_next_scope = true;
687 }
688
689 fn begin_section_items(&mut self) {
690 let path = std::mem::take(&mut self.pending_path);
692 let trivia_before = std::mem::take(&mut self.pending_trivia);
693
694 let value = self.last_bound_node.take();
696
697 self.builder_stack.push(BuilderContext::SectionItems {
698 trivia_before,
699 path,
700 value,
701 bindings: Vec::new(),
702 });
703 }
704
705 fn end_section_items(&mut self) -> Result<(), Self::Error> {
706 match self.builder_stack.pop() {
708 Some(BuilderContext::SectionItems {
709 trivia_before,
710 path,
711 value,
712 bindings,
713 }) => {
714 let section = SectionSource::items(path, value, bindings);
715 self.push_section(section, trivia_before);
716 Ok(())
717 }
718 _ => Err(InsertError {
719 kind: ConstructorError::InvalidBuilderStackForEndSectionItems.into(),
720 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
721 }),
722 }
723 }
724
725 fn end_section_block(&mut self) -> Result<(), Self::Error> {
726 let path = std::mem::take(&mut self.pending_path);
728 let trivia_before = std::mem::take(&mut self.pending_trivia);
729 let source_id = self.last_block_id.take().ok_or_else(|| InsertError {
730 kind: ConstructorError::MissingEndEureBlockBeforeEndSectionBlock.into(),
731 path: EurePath::from_iter(self.inner.current_path().iter().cloned()),
732 })?;
733
734 let section = SectionSource::block(path, source_id);
735 self.push_section(section, trivia_before);
736 Ok(())
737 }
738
739 fn comment(&mut self, comment: Comment) {
740 self.pending_trivia.push(Trivia::Comment(comment));
741 }
742
743 fn blank_line(&mut self) {
744 self.pending_trivia.push(Trivia::BlankLine);
745 }
746}
747
748#[cfg(test)]
749mod tests {
750 use super::*;
751 use crate::document::InsertErrorKind;
752 use crate::path::ArrayIndexKind;
753 use crate::source::{BindSource, SectionBody};
754
755 fn ident(s: &str) -> Identifier {
756 s.parse().unwrap()
757 }
758
759 #[test]
764 fn test_pattern1_simple_binding() {
765 let mut constructor = SourceConstructor::new();
766
767 constructor.begin_binding();
769 let scope = constructor.begin_scope();
770 constructor
771 .navigate(PathSegment::Ident(ident("name")))
772 .unwrap();
773 constructor
774 .bind_primitive(PrimitiveValue::Text(Text::plaintext("Alice")))
775 .unwrap();
776 constructor.end_scope(scope).unwrap();
777 constructor.end_binding_value().unwrap();
778
779 let source_doc = constructor.finish();
780
781 let root = source_doc.root_source();
783 assert_eq!(root.bindings.len(), 1);
784 assert!(root.sections.is_empty());
785 assert!(root.value.is_none());
786
787 let binding = &root.bindings[0];
788 assert_eq!(binding.path.len(), 1);
789 assert_eq!(binding.path[0].key, SourceKey::Ident(ident("name")));
790 match &binding.bind {
791 BindSource::Value(node_id) => {
792 assert!(node_id.0 > 0); }
794 _ => panic!("Expected BindSource::Value"),
795 }
796 }
797
798 #[test]
799 fn test_pattern1_nested_path() {
800 let mut constructor = SourceConstructor::new();
801
802 constructor.begin_binding();
804 let scope = constructor.begin_scope();
805 constructor
806 .navigate(PathSegment::Ident(ident("a")))
807 .unwrap();
808 constructor
809 .navigate(PathSegment::Ident(ident("b")))
810 .unwrap();
811 constructor
812 .navigate(PathSegment::Ident(ident("c")))
813 .unwrap();
814 constructor
815 .bind_primitive(PrimitiveValue::Integer(42.into()))
816 .unwrap();
817 constructor.end_scope(scope).unwrap();
818 constructor.end_binding_value().unwrap();
819
820 let source_doc = constructor.finish();
821
822 let root = source_doc.root_source();
823 assert_eq!(root.bindings.len(), 1);
824
825 let binding = &root.bindings[0];
826 assert_eq!(binding.path.len(), 3);
827 assert_eq!(binding.path[0].key, SourceKey::Ident(ident("a")));
828 assert_eq!(binding.path[1].key, SourceKey::Ident(ident("b")));
829 assert_eq!(binding.path[2].key, SourceKey::Ident(ident("c")));
830 }
831
832 #[test]
837 fn test_pattern2_binding_block() {
838 let mut constructor = SourceConstructor::new();
839
840 constructor.begin_binding();
842 let scope = constructor.begin_scope();
843 constructor
844 .navigate(PathSegment::Ident(ident("user")))
845 .unwrap();
846 constructor.begin_eure_block();
847
848 constructor.begin_binding();
850 let inner_scope = constructor.begin_scope();
851 constructor
852 .navigate(PathSegment::Ident(ident("name")))
853 .unwrap();
854 constructor
855 .bind_primitive(PrimitiveValue::Text(Text::plaintext("Bob")))
856 .unwrap();
857 constructor.end_scope(inner_scope).unwrap();
858 constructor.end_binding_value().unwrap();
859
860 constructor.end_eure_block().unwrap();
861 constructor.end_scope(scope).unwrap();
862 constructor.end_binding_block().unwrap();
863
864 let source_doc = constructor.finish();
865
866 let root = source_doc.root_source();
868 assert_eq!(root.bindings.len(), 1);
869
870 let binding = &root.bindings[0];
871 assert_eq!(binding.path.len(), 1);
872 assert_eq!(binding.path[0].key, SourceKey::Ident(ident("user")));
873
874 match &binding.bind {
875 BindSource::Block(source_id) => {
876 let inner_source = source_doc.source(*source_id);
877 assert!(inner_source.value.is_none());
878 assert_eq!(inner_source.bindings.len(), 1);
879 assert_eq!(
880 inner_source.bindings[0].path[0].key,
881 SourceKey::Ident(ident("name"))
882 );
883 }
884 _ => panic!("Expected BindSource::Block"),
885 }
886 }
887
888 #[test]
893 fn test_pattern3_binding_value_block() {
894 let mut constructor = SourceConstructor::new();
895
896 constructor.begin_binding();
898 let scope = constructor.begin_scope();
899 constructor
900 .navigate(PathSegment::Ident(ident("data")))
901 .unwrap();
902 constructor.begin_eure_block();
903
904 constructor.bind_empty_array().unwrap();
906 constructor.set_block_value().unwrap();
907
908 constructor.begin_binding();
910 let inner_scope = constructor.begin_scope();
911 constructor
912 .navigate(PathSegment::Extension(ident("schema")))
913 .unwrap();
914 constructor
915 .bind_primitive(PrimitiveValue::Text(Text::plaintext("array")))
916 .unwrap();
917 constructor.end_scope(inner_scope).unwrap();
918 constructor.end_binding_value().unwrap();
919
920 constructor.end_eure_block().unwrap();
921 constructor.end_scope(scope).unwrap();
922 constructor.end_binding_block().unwrap();
923
924 let source_doc = constructor.finish();
925
926 let root = source_doc.root_source();
927 assert_eq!(root.bindings.len(), 1);
928
929 let binding = &root.bindings[0];
930 match &binding.bind {
931 BindSource::Block(source_id) => {
932 let inner_source = source_doc.source(*source_id);
933 assert!(inner_source.value.is_some());
935 assert_eq!(inner_source.bindings.len(), 1);
937 }
938 _ => panic!("Expected BindSource::Block"),
939 }
940 }
941
942 #[test]
947 fn test_pattern4_section_items() {
948 let mut constructor = SourceConstructor::new();
949
950 constructor.begin_section();
956 let scope = constructor.begin_scope();
957 constructor
958 .navigate(PathSegment::Ident(ident("server")))
959 .unwrap();
960 constructor.begin_section_items();
961
962 constructor.begin_binding();
964 let inner_scope1 = constructor.begin_scope();
965 constructor
966 .navigate(PathSegment::Ident(ident("host")))
967 .unwrap();
968 constructor
969 .bind_primitive(PrimitiveValue::Text(Text::plaintext("localhost")))
970 .unwrap();
971 constructor.end_scope(inner_scope1).unwrap();
972 constructor.end_binding_value().unwrap();
973
974 constructor.begin_binding();
976 let inner_scope2 = constructor.begin_scope();
977 constructor
978 .navigate(PathSegment::Ident(ident("port")))
979 .unwrap();
980 constructor
981 .bind_primitive(PrimitiveValue::Integer(8080.into()))
982 .unwrap();
983 constructor.end_scope(inner_scope2).unwrap();
984 constructor.end_binding_value().unwrap();
985
986 constructor.end_section_items().unwrap();
987 constructor.end_scope(scope).unwrap();
988
989 let source_doc = constructor.finish();
990
991 let root = source_doc.root_source();
992 assert!(root.bindings.is_empty());
993 assert_eq!(root.sections.len(), 1);
994
995 let section = &root.sections[0];
996 assert_eq!(section.path.len(), 1);
997 assert_eq!(section.path[0].key, SourceKey::Ident(ident("server")));
998
999 match §ion.body {
1000 SectionBody::Items { value, bindings } => {
1001 assert!(value.is_none());
1002 assert_eq!(bindings.len(), 2);
1003 assert_eq!(bindings[0].path[0].key, SourceKey::Ident(ident("host")));
1004 assert_eq!(bindings[1].path[0].key, SourceKey::Ident(ident("port")));
1005 }
1006 _ => panic!("Expected SectionBody::Items"),
1007 }
1008 }
1009
1010 #[test]
1015 fn test_pattern5_section_block() {
1016 let mut constructor = SourceConstructor::new();
1017
1018 constructor.begin_section();
1020 let scope = constructor.begin_scope();
1021 constructor
1022 .navigate(PathSegment::Ident(ident("server")))
1023 .unwrap();
1024 constructor.begin_eure_block();
1025
1026 constructor.begin_binding();
1028 let inner_scope = constructor.begin_scope();
1029 constructor
1030 .navigate(PathSegment::Ident(ident("host")))
1031 .unwrap();
1032 constructor
1033 .bind_primitive(PrimitiveValue::Text(Text::plaintext("localhost")))
1034 .unwrap();
1035 constructor.end_scope(inner_scope).unwrap();
1036 constructor.end_binding_value().unwrap();
1037
1038 constructor.end_eure_block().unwrap();
1039 constructor.end_scope(scope).unwrap();
1040 constructor.end_section_block().unwrap();
1041
1042 let source_doc = constructor.finish();
1043
1044 let root = source_doc.root_source();
1045 assert!(root.bindings.is_empty());
1046 assert_eq!(root.sections.len(), 1);
1047
1048 let section = &root.sections[0];
1049 match §ion.body {
1050 SectionBody::Block(source_id) => {
1051 let inner_source = source_doc.source(*source_id);
1052 assert!(inner_source.value.is_none());
1053 assert_eq!(inner_source.bindings.len(), 1);
1054 }
1055 _ => panic!("Expected SectionBody::Block"),
1056 }
1057 }
1058
1059 #[test]
1064 fn test_pattern6_section_value_block() {
1065 let mut constructor = SourceConstructor::new();
1066
1067 constructor.begin_section();
1069 let scope = constructor.begin_scope();
1070 constructor
1071 .navigate(PathSegment::Ident(ident("data")))
1072 .unwrap();
1073 constructor.begin_eure_block();
1074
1075 constructor.bind_empty_array().unwrap();
1077 constructor.set_block_value().unwrap();
1078
1079 constructor.begin_binding();
1081 let inner_scope = constructor.begin_scope();
1082 constructor
1083 .navigate(PathSegment::Extension(ident("schema")))
1084 .unwrap();
1085 constructor
1086 .bind_primitive(PrimitiveValue::Text(Text::plaintext("array")))
1087 .unwrap();
1088 constructor.end_scope(inner_scope).unwrap();
1089 constructor.end_binding_value().unwrap();
1090
1091 constructor.end_eure_block().unwrap();
1092 constructor.end_scope(scope).unwrap();
1093 constructor.end_section_block().unwrap();
1094
1095 let source_doc = constructor.finish();
1096
1097 let root = source_doc.root_source();
1098 assert_eq!(root.sections.len(), 1);
1099
1100 let section = &root.sections[0];
1101 match §ion.body {
1102 SectionBody::Block(source_id) => {
1103 let inner_source = source_doc.source(*source_id);
1104 assert!(inner_source.value.is_some());
1106 assert_eq!(inner_source.bindings.len(), 1);
1108 }
1109 _ => panic!("Expected SectionBody::Block"),
1110 }
1111 }
1112
1113 #[test]
1118 fn test_array_index_with_key() {
1119 let mut constructor = SourceConstructor::new();
1121
1122 constructor.begin_binding();
1123 let scope = constructor.begin_scope();
1124 constructor
1125 .navigate(PathSegment::Ident(ident("items")))
1126 .unwrap();
1127 constructor
1128 .navigate(PathSegment::ArrayIndex(ArrayIndexKind::Specific(0)))
1129 .unwrap();
1130 constructor
1131 .bind_primitive(PrimitiveValue::Text(Text::plaintext("first")))
1132 .unwrap();
1133 constructor.end_scope(scope).unwrap();
1134 constructor.end_binding_value().unwrap();
1135
1136 let source_doc = constructor.finish();
1137
1138 let root = source_doc.root_source();
1139 assert_eq!(root.bindings.len(), 1);
1140
1141 let binding = &root.bindings[0];
1142 assert_eq!(binding.path.len(), 1);
1144 assert_eq!(binding.path[0].key, SourceKey::Ident(ident("items")));
1145 assert_eq!(binding.path[0].array, Some(ArrayIndexKind::Specific(0)));
1146 }
1147
1148 #[test]
1149 fn test_array_push_marker() {
1150 let mut constructor = SourceConstructor::new();
1152
1153 constructor.begin_binding();
1154 let scope = constructor.begin_scope();
1155 constructor
1156 .navigate(PathSegment::Ident(ident("items")))
1157 .unwrap();
1158 constructor
1159 .navigate(PathSegment::ArrayIndex(ArrayIndexKind::Push))
1160 .unwrap();
1161 constructor
1162 .bind_primitive(PrimitiveValue::Text(Text::plaintext("new")))
1163 .unwrap();
1164 constructor.end_scope(scope).unwrap();
1165 constructor.end_binding_value().unwrap();
1166
1167 let source_doc = constructor.finish();
1168
1169 let root = source_doc.root_source();
1170 let binding = &root.bindings[0];
1171 assert_eq!(binding.path.len(), 1);
1172 assert_eq!(binding.path[0].key, SourceKey::Ident(ident("items")));
1173 assert_eq!(binding.path[0].array, Some(ArrayIndexKind::Push));
1175 }
1176
1177 #[test]
1178 fn test_standalone_array_index_returns_error() {
1179 let mut constructor = SourceConstructor::new();
1181
1182 constructor.begin_binding();
1183 let _scope = constructor.begin_scope();
1184 let result = constructor.navigate(PathSegment::ArrayIndex(ArrayIndexKind::Specific(0)));
1186 assert!(matches!(
1187 result,
1188 Err(InsertError {
1189 kind: InsertErrorKind::ConstructorError(ConstructorError::StandaloneArrayIndex),
1190 ..
1191 })
1192 ));
1193 }
1194
1195 #[test]
1200 fn test_end_binding_value_without_bind_returns_error() {
1201 let mut constructor = SourceConstructor::new();
1202
1203 constructor.begin_binding();
1204 let scope = constructor.begin_scope();
1205 constructor
1206 .navigate(PathSegment::Ident(ident("name")))
1207 .unwrap();
1208 constructor.end_scope(scope).unwrap();
1210 let result = constructor.end_binding_value();
1211 assert!(matches!(
1212 result,
1213 Err(InsertError {
1214 kind: InsertErrorKind::ConstructorError(
1215 ConstructorError::MissingBindBeforeEndBindingValue
1216 ),
1217 ..
1218 })
1219 ));
1220 }
1221
1222 #[test]
1223 fn test_set_block_value_without_bind_returns_error() {
1224 let mut constructor = SourceConstructor::new();
1225
1226 constructor.begin_binding();
1227 let _scope = constructor.begin_scope();
1228 constructor
1229 .navigate(PathSegment::Ident(ident("data")))
1230 .unwrap();
1231 constructor.begin_eure_block();
1232 let result = constructor.set_block_value();
1234 assert!(matches!(
1235 result,
1236 Err(InsertError {
1237 kind: InsertErrorKind::ConstructorError(
1238 ConstructorError::MissingBindBeforeSetBlockValue
1239 ),
1240 ..
1241 })
1242 ));
1243 }
1244
1245 #[test]
1246 fn test_end_binding_block_without_end_eure_block_returns_error() {
1247 let mut constructor = SourceConstructor::new();
1248
1249 constructor.begin_binding();
1250 let scope = constructor.begin_scope();
1251 constructor
1252 .navigate(PathSegment::Ident(ident("data")))
1253 .unwrap();
1254 constructor.end_scope(scope).unwrap();
1256 let result = constructor.end_binding_block();
1257 assert!(matches!(
1258 result,
1259 Err(InsertError {
1260 kind: InsertErrorKind::ConstructorError(
1261 ConstructorError::MissingEndEureBlockBeforeEndBindingBlock
1262 ),
1263 ..
1264 })
1265 ));
1266 }
1267
1268 #[test]
1273 fn test_multiple_bindings() {
1274 let mut constructor = SourceConstructor::new();
1275
1276 for (name, value) in [("a", 1), ("b", 2)] {
1278 constructor.begin_binding();
1279 let scope = constructor.begin_scope();
1280 constructor
1281 .navigate(PathSegment::Ident(ident(name)))
1282 .unwrap();
1283 constructor
1284 .bind_primitive(PrimitiveValue::Integer(value.into()))
1285 .unwrap();
1286 constructor.end_scope(scope).unwrap();
1287 constructor.end_binding_value().unwrap();
1288 }
1289
1290 let source_doc = constructor.finish();
1291
1292 let root = source_doc.root_source();
1293 assert_eq!(root.bindings.len(), 2);
1294 assert_eq!(root.bindings[0].path[0].key, SourceKey::Ident(ident("a")));
1295 assert_eq!(root.bindings[1].path[0].key, SourceKey::Ident(ident("b")));
1296 }
1297
1298 #[test]
1299 fn test_nested_blocks() {
1300 let mut constructor = SourceConstructor::new();
1301
1302 constructor.begin_binding();
1304 let scope1 = constructor.begin_scope();
1305 constructor
1306 .navigate(PathSegment::Ident(ident("outer")))
1307 .unwrap();
1308 constructor.begin_eure_block();
1309
1310 constructor.begin_binding();
1311 let scope2 = constructor.begin_scope();
1312 constructor
1313 .navigate(PathSegment::Ident(ident("inner")))
1314 .unwrap();
1315 constructor.begin_eure_block();
1316
1317 constructor.begin_binding();
1318 let scope3 = constructor.begin_scope();
1319 constructor
1320 .navigate(PathSegment::Ident(ident("value")))
1321 .unwrap();
1322 constructor
1323 .bind_primitive(PrimitiveValue::Integer(1.into()))
1324 .unwrap();
1325 constructor.end_scope(scope3).unwrap();
1326 constructor.end_binding_value().unwrap();
1327
1328 constructor.end_eure_block().unwrap();
1329 constructor.end_scope(scope2).unwrap();
1330 constructor.end_binding_block().unwrap();
1331
1332 constructor.end_eure_block().unwrap();
1333 constructor.end_scope(scope1).unwrap();
1334 constructor.end_binding_block().unwrap();
1335
1336 let source_doc = constructor.finish();
1337
1338 let root = source_doc.root_source();
1340 assert_eq!(root.bindings.len(), 1);
1341
1342 if let BindSource::Block(outer_id) = &root.bindings[0].bind {
1343 let outer = source_doc.source(*outer_id);
1344 assert_eq!(outer.bindings.len(), 1);
1345
1346 if let BindSource::Block(inner_id) = &outer.bindings[0].bind {
1347 let inner = source_doc.source(*inner_id);
1348 assert_eq!(inner.bindings.len(), 1);
1349 assert!(matches!(inner.bindings[0].bind, BindSource::Value(_)));
1350 } else {
1351 panic!("Expected inner block");
1352 }
1353 } else {
1354 panic!("Expected outer block");
1355 }
1356 }
1357
1358 #[test]
1363 fn test_trivia_before_binding() {
1364 let mut constructor = SourceConstructor::new();
1365
1366 constructor.comment(Comment::Line("This is a comment".to_string()));
1368 constructor.blank_line();
1369
1370 constructor.begin_binding();
1372 let scope = constructor.begin_scope();
1373 constructor
1374 .navigate(PathSegment::Ident(ident("name")))
1375 .unwrap();
1376 constructor
1377 .bind_primitive(PrimitiveValue::Text(Text::plaintext("Alice")))
1378 .unwrap();
1379 constructor.end_scope(scope).unwrap();
1380 constructor.end_binding_value().unwrap();
1381
1382 let source_doc = constructor.finish();
1383
1384 let root = source_doc.root_source();
1385 assert_eq!(root.bindings.len(), 1);
1386
1387 let binding = &root.bindings[0];
1389 assert_eq!(binding.trivia_before.len(), 2);
1390 assert!(matches!(
1391 &binding.trivia_before[0],
1392 Trivia::Comment(Comment::Line(s)) if s == "This is a comment"
1393 ));
1394 assert!(matches!(&binding.trivia_before[1], Trivia::BlankLine));
1395 }
1396
1397 #[test]
1398 fn test_trivia_before_section() {
1399 let mut constructor = SourceConstructor::new();
1400
1401 constructor.blank_line();
1403
1404 constructor.begin_section();
1406 let scope = constructor.begin_scope();
1407 constructor
1408 .navigate(PathSegment::Ident(ident("server")))
1409 .unwrap();
1410 constructor.begin_section_items();
1411
1412 constructor.begin_binding();
1414 let inner_scope = constructor.begin_scope();
1415 constructor
1416 .navigate(PathSegment::Ident(ident("host")))
1417 .unwrap();
1418 constructor
1419 .bind_primitive(PrimitiveValue::Text(Text::plaintext("localhost")))
1420 .unwrap();
1421 constructor.end_scope(inner_scope).unwrap();
1422 constructor.end_binding_value().unwrap();
1423
1424 constructor.end_section_items().unwrap();
1425 constructor.end_scope(scope).unwrap();
1426
1427 let source_doc = constructor.finish();
1428
1429 let root = source_doc.root_source();
1430 assert_eq!(root.sections.len(), 1);
1431
1432 let section = &root.sections[0];
1434 assert_eq!(section.trivia_before.len(), 1);
1435 assert!(matches!(§ion.trivia_before[0], Trivia::BlankLine));
1436 }
1437
1438 #[test]
1439 fn test_trailing_trivia() {
1440 let mut constructor = SourceConstructor::new();
1441
1442 constructor.begin_binding();
1444 let scope = constructor.begin_scope();
1445 constructor
1446 .navigate(PathSegment::Ident(ident("name")))
1447 .unwrap();
1448 constructor
1449 .bind_primitive(PrimitiveValue::Text(Text::plaintext("Alice")))
1450 .unwrap();
1451 constructor.end_scope(scope).unwrap();
1452 constructor.end_binding_value().unwrap();
1453
1454 constructor.blank_line();
1456 constructor.comment(Comment::Line("end of file".to_string()));
1457
1458 let source_doc = constructor.finish();
1459
1460 let root = source_doc.root_source();
1461 assert_eq!(root.trailing_trivia.len(), 2);
1462 assert!(matches!(&root.trailing_trivia[0], Trivia::BlankLine));
1463 assert!(matches!(
1464 &root.trailing_trivia[1],
1465 Trivia::Comment(Comment::Line(s)) if s == "end of file"
1466 ));
1467 }
1468
1469 #[test]
1470 fn test_trivia_between_bindings() {
1471 let mut constructor = SourceConstructor::new();
1472
1473 constructor.begin_binding();
1475 let scope1 = constructor.begin_scope();
1476 constructor
1477 .navigate(PathSegment::Ident(ident("a")))
1478 .unwrap();
1479 constructor
1480 .bind_primitive(PrimitiveValue::Integer(1.into()))
1481 .unwrap();
1482 constructor.end_scope(scope1).unwrap();
1483 constructor.end_binding_value().unwrap();
1484
1485 constructor.blank_line();
1487 constructor.comment(Comment::Line("Second binding".to_string()));
1488
1489 constructor.begin_binding();
1491 let scope2 = constructor.begin_scope();
1492 constructor
1493 .navigate(PathSegment::Ident(ident("b")))
1494 .unwrap();
1495 constructor
1496 .bind_primitive(PrimitiveValue::Integer(2.into()))
1497 .unwrap();
1498 constructor.end_scope(scope2).unwrap();
1499 constructor.end_binding_value().unwrap();
1500
1501 let source_doc = constructor.finish();
1502
1503 let root = source_doc.root_source();
1504 assert_eq!(root.bindings.len(), 2);
1505
1506 assert!(root.bindings[0].trivia_before.is_empty());
1508
1509 assert_eq!(root.bindings[1].trivia_before.len(), 2);
1511 assert!(matches!(
1512 &root.bindings[1].trivia_before[0],
1513 Trivia::BlankLine
1514 ));
1515 assert!(matches!(
1516 &root.bindings[1].trivia_before[1],
1517 Trivia::Comment(Comment::Line(s)) if s == "Second binding"
1518 ));
1519 }
1520}