1use std::cell::RefCell;
34use std::collections::VecDeque;
35use std::fmt::Display;
36use std::iter::Peekable;
37use std::rc::Rc;
38use std::rc::Weak;
39
40use super::common::Ranged;
41use crate::ast;
42use crate::errors::ParseError;
43use crate::parse_to_ast;
44use crate::string::ParseStringErrorKind;
45use crate::ParseOptions;
46
47mod input;
48
49pub use input::*;
50
51macro_rules! add_root_node_method {
52 () => {
53 pub fn root_node(&self) -> Option<CstRootNode> {
58 self
59 .ancestors()
60 .filter_map(|parent| match parent {
61 CstContainerNode::Root(node) => Some(node),
62 _ => None,
63 })
64 .next()
65 }
66 };
67}
68
69macro_rules! add_parent_info_methods {
70 () => {
71 pub fn parent(&self) -> Option<CstContainerNode> {
76 self.parent_info().map(|p| p.parent.as_container_node())
77 }
78
79 pub fn ancestors(&self) -> impl Iterator<Item = CstContainerNode> {
81 AncestorIterator::new(self.clone().into())
82 }
83
84 pub fn child_index(&self) -> usize {
87 self.parent_info().map(|p| p.child_index).unwrap_or(0)
88 }
89
90 pub fn previous_sibling(&self) -> Option<CstNode> {
92 let parent_info = self.parent_info()?;
93 if parent_info.child_index == 0 {
94 return None;
95 }
96 parent_info
97 .parent
98 .as_container_node()
99 .child_at_index(parent_info.child_index - 1)
100 }
101
102 pub fn previous_siblings(&self) -> impl Iterator<Item = CstNode> {
105 PreviousSiblingIterator::new(self.clone().into())
106 }
107
108 pub fn next_sibling(&self) -> Option<CstNode> {
110 let parent_info = self.parent_info()?;
111 parent_info
112 .parent
113 .as_container_node()
114 .child_at_index(parent_info.child_index + 1)
115 }
116
117 pub fn next_siblings(&self) -> impl Iterator<Item = CstNode> {
120 NextSiblingIterator::new(self.clone().into())
121 }
122
123 pub fn indent_text(&self) -> Option<String> {
125 indent_text(&self.clone().into())
126 }
127
128 pub fn trailing_comma(&self) -> Option<CstToken> {
130 find_trailing_comma(&self.clone().into())
131 }
132
133 pub fn uses_trailing_commas(&self) -> bool {
135 uses_trailing_commas(self.clone().into())
136 }
137 };
138}
139
140fn find_trailing_comma(node: &CstNode) -> Option<CstToken> {
141 for next_sibling in node.next_siblings() {
142 match next_sibling {
143 CstNode::Container(_) => return None,
144 CstNode::Leaf(leaf) => match leaf {
145 CstLeafNode::BooleanLit(_)
146 | CstLeafNode::NullKeyword(_)
147 | CstLeafNode::NumberLit(_)
148 | CstLeafNode::StringLit(_)
149 | CstLeafNode::WordLit(_) => return None,
150 CstLeafNode::Token(token) => {
151 if token.value() == ',' {
152 return Some(token);
153 } else {
154 return None;
155 }
156 }
157 CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
158 }
160 },
161 }
162 }
163
164 None
165}
166
167macro_rules! add_parent_methods {
168 () => {
169 add_parent_info_methods!();
170
171 fn parent_info(&self) -> Option<ParentInfo> {
172 self.0.borrow().parent.clone()
173 }
174
175 fn set_parent(&self, parent: Option<ParentInfo>) {
176 self.0.borrow_mut().parent = parent;
177 }
178 };
179}
180
181macro_rules! impl_from_leaf_or_container {
182 ($node_name:ident, $variant:ident, $leaf_or_container:ident, $leaf_or_container_variant:ident) => {
183 impl From<$node_name> for CstNode {
184 fn from(value: $node_name) -> Self {
185 CstNode::$leaf_or_container_variant($leaf_or_container::$variant(value))
186 }
187 }
188
189 impl From<$node_name> for $leaf_or_container {
190 fn from(value: $node_name) -> Self {
191 $leaf_or_container::$variant(value)
192 }
193 }
194 };
195}
196
197macro_rules! impl_container_methods {
198 ($node_name:ident, $variant:ident) => {
199 impl_from_leaf_or_container!($node_name, $variant, CstContainerNode, Container);
200
201 impl $node_name {
202 add_parent_methods!();
203
204 pub fn children(&self) -> Vec<CstNode> {
206 self.0.borrow().value.clone()
207 }
208
209 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
211 self
212 .0
213 .borrow()
214 .value
215 .iter()
216 .filter(|n| !n.is_trivia() && !n.is_token())
217 .cloned()
218 .collect()
219 }
220
221 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
223 self.0.borrow().value.get(index).cloned()
224 }
225
226 fn remove_child_set_no_parent(&self, index: usize) {
227 let mut inner = self.0.borrow_mut();
228 if index < inner.value.len() {
229 let container = self.clone().into();
230 let child = inner.value.remove(index);
231 child.set_parent(None);
232
233 for index in index..inner.value.len() {
235 inner.value[index].set_parent(Some(ParentInfo {
236 parent: WeakParent::from_container(&container),
237 child_index: index,
238 }));
239 }
240 }
241 }
242 }
243 };
244}
245
246macro_rules! impl_leaf_methods {
247 ($node_name:ident, $variant:ident) => {
248 impl_from_leaf_or_container!($node_name, $variant, CstLeafNode, Leaf);
249
250 impl $node_name {
251 add_parent_methods!();
252 add_root_node_method!();
253 }
254 };
255}
256
257#[derive(Debug, Clone)]
258enum WeakParent {
259 Root(Weak<CstRootNodeInner>),
260 Object(Weak<CstObjectInner>),
261 ObjectProp(Weak<CstObjectPropInner>),
262 Array(Weak<CstArrayInner>),
263}
264
265impl WeakParent {
266 pub fn from_container(container: &CstContainerNode) -> Self {
267 match container {
268 CstContainerNode::Root(node) => WeakParent::Root(Rc::downgrade(&node.0)),
269 CstContainerNode::Object(node) => WeakParent::Object(Rc::downgrade(&node.0)),
270 CstContainerNode::ObjectProp(node) => WeakParent::ObjectProp(Rc::downgrade(&node.0)),
271 CstContainerNode::Array(node) => WeakParent::Array(Rc::downgrade(&node.0)),
272 }
273 }
274
275 pub fn as_container_node(&self) -> CstContainerNode {
276 const PANIC_MSG: &str = "Programming error. Ensure you keep around the RootNode for the duration of using the CST.";
280 match self {
281 WeakParent::Root(weak) => CstRootNode(weak.upgrade().expect(PANIC_MSG)).into(),
282 WeakParent::Object(weak) => CstObject(weak.upgrade().expect(PANIC_MSG)).into(),
283 WeakParent::ObjectProp(weak) => CstObjectProp(weak.upgrade().expect(PANIC_MSG)).into(),
284 WeakParent::Array(weak) => CstArray(weak.upgrade().expect(PANIC_MSG)).into(),
285 }
286 }
287}
288
289#[derive(Clone, Debug)]
290struct ParentInfo {
291 pub parent: WeakParent,
292 pub child_index: usize,
293}
294
295#[derive(Debug)]
296struct CstValueInner<T> {
297 parent: Option<ParentInfo>,
298 value: T,
299}
300
301impl<T> CstValueInner<T> {
302 fn new(value: T) -> Rc<RefCell<Self>> {
303 Rc::new(RefCell::new(CstValueInner { parent: None, value }))
304 }
305}
306
307type CstChildrenInner = CstValueInner<Vec<CstNode>>;
308
309#[derive(Debug, Clone)]
311pub enum CstNode {
312 Container(CstContainerNode),
313 Leaf(CstLeafNode),
314}
315
316impl CstNode {
317 add_parent_info_methods!();
318 add_root_node_method!();
319
320 pub fn is_trivia(&self) -> bool {
322 match self {
323 CstNode::Leaf(leaf) => match leaf {
324 CstLeafNode::BooleanLit(_)
325 | CstLeafNode::NullKeyword(_)
326 | CstLeafNode::NumberLit(_)
327 | CstLeafNode::StringLit(_)
328 | CstLeafNode::Token(_)
329 | CstLeafNode::WordLit(_) => false,
330 CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => true,
331 },
332 CstNode::Container(_) => false,
333 }
334 }
335
336 pub fn leading_comments_same_line(&self) -> impl Iterator<Item = CstComment> {
338 self
339 .previous_siblings()
340 .take_while(|n| n.is_whitespace() || n.is_comment())
341 .filter_map(|n| match n {
342 CstNode::Leaf(CstLeafNode::Comment(comment)) => Some(comment.clone()),
343 _ => None,
344 })
345 }
346
347 pub fn trailing_comments_same_line(&self) -> impl Iterator<Item = CstComment> {
351 for sibling in self.next_siblings() {
353 if sibling.is_newline() {
354 break;
355 } else if !sibling.is_comment() && !sibling.is_whitespace() {
356 return Box::new(std::iter::empty()) as Box<dyn Iterator<Item = CstComment>>;
357 }
358 }
359
360 Box::new(
361 self
362 .next_siblings()
363 .take_while(|n| n.is_whitespace() || n.is_comment())
364 .filter_map(|n| match n {
365 CstNode::Leaf(CstLeafNode::Comment(comment)) => Some(comment.clone()),
366 _ => None,
367 }),
368 )
369 }
370
371 pub fn is_newline(&self) -> bool {
373 matches!(self, CstNode::Leaf(CstLeafNode::Newline(_)))
374 }
375
376 pub fn is_comma(&self) -> bool {
378 match self {
379 CstNode::Leaf(CstLeafNode::Token(t)) => t.value() == ',',
380 _ => false,
381 }
382 }
383
384 pub fn is_comment(&self) -> bool {
386 matches!(self, CstNode::Leaf(CstLeafNode::Comment(_)))
387 }
388
389 pub fn is_token(&self) -> bool {
391 matches!(self, CstNode::Leaf(CstLeafNode::Token(_)))
392 }
393
394 pub fn is_whitespace(&self) -> bool {
396 matches!(self, CstNode::Leaf(CstLeafNode::Whitespace(_)))
397 }
398
399 pub fn token_char(&self) -> Option<char> {
401 match self {
402 CstNode::Leaf(CstLeafNode::Token(token)) => Some(token.value()),
403 _ => None,
404 }
405 }
406
407 pub fn children(&self) -> Vec<CstNode> {
409 match self {
410 CstNode::Container(n) => n.children(),
411 CstNode::Leaf(_) => Vec::new(),
412 }
413 }
414
415 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
417 match self {
418 CstNode::Container(n) => n.children_exclude_trivia_and_tokens(),
419 CstNode::Leaf(_) => Vec::new(),
420 }
421 }
422
423 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
425 match self {
426 CstNode::Container(n) => n.child_at_index(index),
427 CstNode::Leaf(_) => None,
428 }
429 }
430
431 pub fn element_index(&self) -> Option<usize> {
435 let child_index = self.child_index();
436 let array = self.parent()?.as_array()?;
437 array.elements().iter().position(|p| p.child_index() == child_index)
438 }
439
440 pub fn as_root_node(&self) -> Option<CstRootNode> {
442 match self {
443 CstNode::Container(CstContainerNode::Root(node)) => Some(node.clone()),
444 _ => None,
445 }
446 }
447
448 pub fn as_object(&self) -> Option<CstObject> {
450 match self {
451 CstNode::Container(CstContainerNode::Object(node)) => Some(node.clone()),
453 _ => None,
454 }
455 }
456
457 pub fn as_array(&self) -> Option<CstArray> {
459 match self {
460 CstNode::Container(CstContainerNode::Array(node)) => Some(node.clone()),
461 _ => None,
462 }
463 }
464
465 pub fn as_object_prop(&self) -> Option<CstObjectProp> {
467 match self {
468 CstNode::Container(CstContainerNode::ObjectProp(node)) => Some(node.clone()),
469 _ => None,
470 }
471 }
472
473 pub fn as_boolean_lit(&self) -> Option<CstBooleanLit> {
475 match self {
476 CstNode::Leaf(CstLeafNode::BooleanLit(node)) => Some(node.clone()),
477 _ => None,
478 }
479 }
480
481 pub fn as_null_keyword(&self) -> Option<CstNullKeyword> {
483 match self {
484 CstNode::Leaf(CstLeafNode::NullKeyword(node)) => Some(node.clone()),
485 _ => None,
486 }
487 }
488
489 pub fn as_number_lit(&self) -> Option<CstNumberLit> {
491 match self {
492 CstNode::Leaf(CstLeafNode::NumberLit(node)) => Some(node.clone()),
493 _ => None,
494 }
495 }
496
497 pub fn as_string_lit(&self) -> Option<CstStringLit> {
499 match self {
500 CstNode::Leaf(CstLeafNode::StringLit(node)) => Some(node.clone()),
501 _ => None,
502 }
503 }
504
505 pub fn as_word_lit(&self) -> Option<CstWordLit> {
507 match self {
508 CstNode::Leaf(CstLeafNode::WordLit(node)) => Some(node.clone()),
509 _ => None,
510 }
511 }
512
513 pub fn as_token(&self) -> Option<CstToken> {
515 match self {
516 CstNode::Leaf(CstLeafNode::Token(node)) => Some(node.clone()),
517 _ => None,
518 }
519 }
520
521 pub fn as_newline(&self) -> Option<CstNewline> {
523 match self {
524 CstNode::Leaf(CstLeafNode::Newline(node)) => Some(node.clone()),
525 _ => None,
526 }
527 }
528
529 pub fn as_whitespace(&self) -> Option<CstWhitespace> {
531 match self {
532 CstNode::Leaf(CstLeafNode::Whitespace(node)) => Some(node.clone()),
533 _ => None,
534 }
535 }
536
537 pub fn as_comment(&self) -> Option<CstComment> {
539 match self {
540 CstNode::Leaf(CstLeafNode::Comment(node)) => Some(node.clone()),
541 _ => None,
542 }
543 }
544
545 pub fn remove(self) {
549 match self {
550 CstNode::Container(n) => n.remove(),
551 CstNode::Leaf(n) => n.remove(),
552 }
553 }
554
555 fn parent_info(&self) -> Option<ParentInfo> {
556 match self {
557 CstNode::Container(node) => node.parent_info(),
558 CstNode::Leaf(node) => node.parent_info(),
559 }
560 }
561
562 fn set_parent(&self, parent: Option<ParentInfo>) {
563 match self {
564 CstNode::Container(node) => node.set_parent(parent),
565 CstNode::Leaf(node) => node.set_parent(parent),
566 }
567 }
568
569 fn remove_raw(self) {
571 let Some(parent_info) = self.parent_info() else {
572 return; };
574 parent_info
575 .parent
576 .as_container_node()
577 .remove_child_set_no_parent(parent_info.child_index);
578 }
579}
580
581impl Display for CstNode {
582 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
583 match self {
584 CstNode::Container(node) => node.fmt(f),
585 CstNode::Leaf(node) => node.fmt(f),
586 }
587 }
588}
589
590#[derive(Default, Debug, Clone)]
591struct StyleInfo {
592 pub uses_trailing_commas: bool,
593 pub newline_kind: CstNewlineKind,
594}
595
596#[derive(Debug, Clone)]
598pub enum CstContainerNode {
599 Root(CstRootNode),
600 Array(CstArray),
601 Object(CstObject),
602 ObjectProp(CstObjectProp),
603}
604
605impl CstContainerNode {
606 add_parent_info_methods!();
607 add_root_node_method!();
608
609 pub fn is_root(&self) -> bool {
611 matches!(self, CstContainerNode::Root(_))
612 }
613
614 pub fn is_array(&self) -> bool {
616 matches!(self, CstContainerNode::Array(_))
617 }
618
619 pub fn is_object(&self) -> bool {
621 matches!(self, CstContainerNode::Object(_))
622 }
623
624 pub fn is_object_prop(&self) -> bool {
626 matches!(self, CstContainerNode::ObjectProp(_))
627 }
628
629 pub fn as_root(&self) -> Option<CstRootNode> {
631 match self {
632 CstContainerNode::Root(node) => Some(node.clone()),
633 _ => None,
634 }
635 }
636
637 pub fn as_array(&self) -> Option<CstArray> {
639 match self {
640 CstContainerNode::Array(node) => Some(node.clone()),
641 _ => None,
642 }
643 }
644
645 pub fn as_object(&self) -> Option<CstObject> {
647 match self {
648 CstContainerNode::Object(node) => Some(node.clone()),
649 _ => None,
650 }
651 }
652
653 pub fn as_object_prop(&self) -> Option<CstObjectProp> {
655 match self {
656 CstContainerNode::ObjectProp(node) => Some(node.clone()),
657 _ => None,
658 }
659 }
660
661 pub fn children(&self) -> Vec<CstNode> {
663 match self {
664 CstContainerNode::Root(n) => n.children(),
665 CstContainerNode::Object(n) => n.children(),
666 CstContainerNode::ObjectProp(n) => n.children(),
667 CstContainerNode::Array(n) => n.children(),
668 }
669 }
670
671 pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
673 match self {
674 CstContainerNode::Root(n) => n.children_exclude_trivia_and_tokens(),
675 CstContainerNode::Object(n) => n.children_exclude_trivia_and_tokens(),
676 CstContainerNode::ObjectProp(n) => n.children_exclude_trivia_and_tokens(),
677 CstContainerNode::Array(n) => n.children_exclude_trivia_and_tokens(),
678 }
679 }
680
681 pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
683 match self {
684 CstContainerNode::Root(node) => node.child_at_index(index),
685 CstContainerNode::Object(node) => node.child_at_index(index),
686 CstContainerNode::ObjectProp(node) => node.child_at_index(index),
687 CstContainerNode::Array(node) => node.child_at_index(index),
688 }
689 }
690
691 fn remove_child_set_no_parent(&self, index: usize) {
692 match self {
693 CstContainerNode::Root(n) => n.remove_child_set_no_parent(index),
694 CstContainerNode::Object(n) => n.remove_child_set_no_parent(index),
695 CstContainerNode::ObjectProp(n) => n.remove_child_set_no_parent(index),
696 CstContainerNode::Array(n) => n.remove_child_set_no_parent(index),
697 }
698 }
699
700 pub fn remove(self) {
702 match self {
703 CstContainerNode::Root(n) => n.clear_children(),
704 CstContainerNode::Object(n) => n.remove(),
705 CstContainerNode::ObjectProp(n) => n.remove(),
706 CstContainerNode::Array(n) => n.remove(),
707 }
708 }
709
710 fn parent_info(&self) -> Option<ParentInfo> {
711 match self {
712 CstContainerNode::Root(node) => node.parent_info(),
713 CstContainerNode::Object(node) => node.parent_info(),
714 CstContainerNode::ObjectProp(node) => node.parent_info(),
715 CstContainerNode::Array(node) => node.parent_info(),
716 }
717 }
718
719 fn set_parent(&self, parent: Option<ParentInfo>) {
720 match self {
721 CstContainerNode::Root(node) => node.set_parent(parent),
722 CstContainerNode::Object(node) => node.set_parent(parent),
723 CstContainerNode::ObjectProp(node) => node.set_parent(parent),
724 CstContainerNode::Array(node) => node.set_parent(parent),
725 }
726 }
727
728 #[inline(always)]
729 fn raw_append_child(&self, child: CstNode) {
730 self.raw_insert_child(None, child);
731 }
732
733 #[inline(always)]
734 fn raw_insert_child(&self, index: Option<&mut usize>, child: CstNode) {
735 self.raw_insert_children(index, vec![child]);
736 }
737
738 #[inline(always)]
739 fn raw_append_children(&self, children: Vec<CstNode>) {
740 self.raw_insert_children(None, children);
741 }
742
743 fn raw_insert_children(&self, index: Option<&mut usize>, children: Vec<CstNode>) {
744 if children.is_empty() {
745 return;
746 }
747
748 let weak_parent = WeakParent::from_container(self);
749 let mut container = match self {
750 CstContainerNode::Root(node) => node.0.borrow_mut(),
751 CstContainerNode::Object(node) => node.0.borrow_mut(),
752 CstContainerNode::ObjectProp(node) => node.0.borrow_mut(),
753 CstContainerNode::Array(node) => node.0.borrow_mut(),
754 };
755 let insert_index = index.as_ref().map(|i| **i).unwrap_or(container.value.len());
756 if let Some(i) = index {
757 *i += children.len();
758 }
759 container.value.splice(insert_index..insert_index, children);
760
761 for (i, child) in container.value.iter().enumerate().skip(insert_index) {
763 child.set_parent(Some(ParentInfo {
764 parent: weak_parent.clone(),
765 child_index: i,
766 }));
767 }
768 }
769
770 fn raw_insert_value_with_internal_indent(
771 &self,
772 insert_index: Option<&mut usize>,
773 value: InsertValue,
774 style_info: &StyleInfo,
775 indents: &Indents,
776 ) {
777 match value {
778 InsertValue::Value(value) => {
779 let is_multiline = value.force_multiline();
780 match value {
781 CstInputValue::Null => {
782 self.raw_insert_child(insert_index, CstLeafNode::NullKeyword(CstNullKeyword::new()).into());
783 }
784 CstInputValue::Bool(value) => {
785 self.raw_insert_child(insert_index, CstLeafNode::BooleanLit(CstBooleanLit::new(value)).into());
786 }
787 CstInputValue::Number(value) => {
788 self.raw_insert_child(insert_index, CstLeafNode::NumberLit(CstNumberLit::new(value)).into());
789 }
790 CstInputValue::String(value) => {
791 self.raw_insert_child(
792 insert_index,
793 CstLeafNode::StringLit(CstStringLit::new_escaped(&value)).into(),
794 );
795 }
796 CstInputValue::Array(elements) => {
797 let array_node: CstContainerNode = CstArray::new_no_tokens().into();
798 self.raw_insert_child(insert_index, array_node.clone().into());
799
800 array_node.raw_append_child(CstToken::new('[').into());
801 if !elements.is_empty() {
802 let indents = indents.indent();
803 let mut elements = elements.into_iter().peekable();
804 while let Some(value) = elements.next() {
805 if is_multiline {
806 array_node.raw_insert_children(
807 None,
808 vec![
809 CstNewline::new(style_info.newline_kind).into(),
810 CstWhitespace::new(indents.current_indent.clone()).into(),
811 ],
812 );
813 }
814
815 array_node.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, &indents);
816
817 if style_info.uses_trailing_commas && is_multiline || elements.peek().is_some() {
818 if is_multiline {
819 array_node.raw_append_child(CstToken::new(',').into());
820 } else {
821 array_node.raw_insert_children(
822 None,
823 vec![CstToken::new(',').into(), CstWhitespace::new(" ".to_string()).into()],
824 );
825 }
826 }
827 }
828 }
829
830 if is_multiline {
831 array_node.raw_append_children(vec![
832 CstNewline::new(style_info.newline_kind).into(),
833 CstWhitespace::new(indents.current_indent.clone()).into(),
834 ]);
835 }
836
837 array_node.raw_append_child(CstToken::new(']').into());
838 }
839 CstInputValue::Object(properties) => {
840 let object_node: CstContainerNode = CstObject::new_no_tokens().into();
841 self.raw_insert_child(insert_index, object_node.clone().into());
842
843 object_node.raw_append_child(CstToken::new('{').into());
844
845 if !properties.is_empty() {
846 {
847 let indents = indents.indent();
848 let mut properties = properties.into_iter().peekable();
849 while let Some((prop_name, value)) = properties.next() {
850 object_node.raw_append_child(CstNewline::new(style_info.newline_kind).into());
851 object_node.raw_append_child(CstWhitespace::new(indents.current_indent.clone()).into());
852 object_node.raw_insert_value_with_internal_indent(
853 None,
854 InsertValue::Property(&prop_name, value),
855 style_info,
856 &indents,
857 );
858 if style_info.uses_trailing_commas || properties.peek().is_some() {
859 object_node.raw_append_child(CstToken::new(',').into());
860 }
861 }
862 }
863
864 object_node.raw_append_children(vec![
865 CstNewline::new(style_info.newline_kind).into(),
866 CstWhitespace::new(indents.current_indent.clone()).into(),
867 ]);
868 }
869
870 object_node.raw_append_child(CstToken::new('}').into());
871 }
872 }
873 }
874 InsertValue::Property(prop_name, value) => {
875 let prop = CstContainerNode::ObjectProp(CstObjectProp::new());
876 self.raw_insert_child(insert_index, prop.clone().into());
877 prop.raw_insert_children(
878 None,
879 vec![
880 CstStringLit::new_escaped(prop_name).into(),
881 CstToken::new(':').into(),
882 CstWhitespace::new(" ".to_string()).into(),
883 ],
884 );
885 prop.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, indents);
886 }
887 }
888 }
889}
890
891impl From<CstContainerNode> for CstNode {
892 fn from(value: CstContainerNode) -> Self {
893 CstNode::Container(value)
894 }
895}
896
897impl Display for CstContainerNode {
898 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
899 match self {
900 CstContainerNode::Root(node) => node.fmt(f),
901 CstContainerNode::Object(node) => node.fmt(f),
902 CstContainerNode::ObjectProp(node) => node.fmt(f),
903 CstContainerNode::Array(node) => node.fmt(f),
904 }
905 }
906}
907
908#[derive(Debug, Clone)]
910pub enum CstLeafNode {
911 BooleanLit(CstBooleanLit),
912 NullKeyword(CstNullKeyword),
913 NumberLit(CstNumberLit),
914 StringLit(CstStringLit),
915 WordLit(CstWordLit),
916 Token(CstToken),
917 Whitespace(CstWhitespace),
918 Newline(CstNewline),
919 Comment(CstComment),
920}
921
922impl CstLeafNode {
923 add_parent_info_methods!();
924 add_root_node_method!();
925
926 pub fn remove(self) {
928 match self {
929 CstLeafNode::BooleanLit(n) => n.remove(),
930 CstLeafNode::NullKeyword(n) => n.remove(),
931 CstLeafNode::NumberLit(n) => n.remove(),
932 CstLeafNode::StringLit(n) => n.remove(),
933 CstLeafNode::WordLit(n) => n.remove(),
934 CstLeafNode::Token(n) => n.remove(),
935 CstLeafNode::Whitespace(n) => n.remove(),
936 CstLeafNode::Newline(n) => n.remove(),
937 CstLeafNode::Comment(n) => n.remove(),
938 }
939 }
940
941 fn parent_info(&self) -> Option<ParentInfo> {
942 match self {
943 CstLeafNode::BooleanLit(node) => node.parent_info(),
944 CstLeafNode::NullKeyword(node) => node.parent_info(),
945 CstLeafNode::NumberLit(node) => node.parent_info(),
946 CstLeafNode::StringLit(node) => node.parent_info(),
947 CstLeafNode::WordLit(node) => node.parent_info(),
948 CstLeafNode::Token(node) => node.parent_info(),
949 CstLeafNode::Whitespace(node) => node.parent_info(),
950 CstLeafNode::Newline(node) => node.parent_info(),
951 CstLeafNode::Comment(node) => node.parent_info(),
952 }
953 }
954
955 fn set_parent(&self, parent: Option<ParentInfo>) {
956 match self {
957 CstLeafNode::BooleanLit(node) => node.set_parent(parent),
958 CstLeafNode::NullKeyword(node) => node.set_parent(parent),
959 CstLeafNode::NumberLit(node) => node.set_parent(parent),
960 CstLeafNode::StringLit(node) => node.set_parent(parent),
961 CstLeafNode::WordLit(node) => node.set_parent(parent),
962 CstLeafNode::Token(node) => node.set_parent(parent),
963 CstLeafNode::Whitespace(node) => node.set_parent(parent),
964 CstLeafNode::Newline(node) => node.set_parent(parent),
965 CstLeafNode::Comment(node) => node.set_parent(parent),
966 }
967 }
968}
969
970impl Display for CstLeafNode {
971 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
972 match self {
973 CstLeafNode::BooleanLit(node) => node.fmt(f),
974 CstLeafNode::NullKeyword(node) => node.fmt(f),
975 CstLeafNode::NumberLit(node) => node.fmt(f),
976 CstLeafNode::StringLit(node) => node.fmt(f),
977 CstLeafNode::WordLit(node) => node.fmt(f),
978 CstLeafNode::Token(node) => node.fmt(f),
979 CstLeafNode::Whitespace(node) => node.fmt(f),
980 CstLeafNode::Newline(node) => node.fmt(f),
981 CstLeafNode::Comment(node) => node.fmt(f),
982 }
983 }
984}
985
986impl From<CstLeafNode> for CstNode {
987 fn from(value: CstLeafNode) -> Self {
988 CstNode::Leaf(value)
989 }
990}
991
992#[derive(Default, Debug, Clone, Copy)]
994pub enum TrailingCommaMode {
995 #[default]
997 Never,
998 IfMultiline,
1000}
1001
1002type CstRootNodeInner = RefCell<CstChildrenInner>;
1003
1004#[derive(Debug, Clone)]
1008pub struct CstRootNode(Rc<CstRootNodeInner>);
1009
1010impl_container_methods!(CstRootNode, Root);
1011
1012impl CstRootNode {
1013 pub fn parse(text: &str, parse_options: &ParseOptions) -> Result<Self, ParseError> {
1048 let parse_result = parse_to_ast(
1049 text,
1050 &crate::CollectOptions {
1051 comments: crate::CommentCollectionStrategy::AsTokens,
1052 tokens: true,
1053 },
1054 parse_options,
1055 )?;
1056
1057 Ok(
1058 CstBuilder {
1059 text,
1060 tokens: parse_result.tokens.unwrap().into_iter().collect(),
1061 }
1062 .build(parse_result.value),
1063 )
1064 }
1065
1066 pub fn single_indent_text(&self) -> Option<String> {
1068 let root_value = self.value()?;
1069 let first_non_trivia_child = root_value.children_exclude_trivia_and_tokens().first()?.clone();
1070 let mut last_whitespace = None;
1071 for previous_trivia in first_non_trivia_child.previous_siblings() {
1072 match previous_trivia {
1073 CstNode::Leaf(CstLeafNode::Whitespace(whitespace)) => {
1074 last_whitespace = Some(whitespace);
1075 }
1076 CstNode::Leaf(CstLeafNode::Newline(_)) => {
1077 return last_whitespace.map(|whitespace| whitespace.0.borrow().value.clone());
1078 }
1079 _ => {
1080 last_whitespace = None;
1081 }
1082 }
1083 }
1084 None
1085 }
1086
1087 pub fn newline_kind(&self) -> CstNewlineKind {
1089 let mut current_children: VecDeque<CstContainerNode> = VecDeque::from([self.clone().into()]);
1090 while let Some(child) = current_children.pop_front() {
1091 for child in child.children() {
1092 if let CstNode::Container(child) = child {
1093 current_children.push_back(child);
1094 } else if let CstNode::Leaf(CstLeafNode::Newline(node)) = child {
1095 return node.kind();
1096 }
1097 }
1098 }
1099 CstNewlineKind::LineFeed
1100 }
1101
1102 pub fn value(&self) -> Option<CstNode> {
1104 for child in &self.0.borrow().value {
1105 if !child.is_trivia() {
1106 return Some(child.clone());
1107 }
1108 }
1109 None
1110 }
1111
1112 pub fn set_value(&self, root_value: CstInputValue) {
1114 let container: CstContainerNode = self.clone().into();
1115 let style_info = StyleInfo {
1116 newline_kind: self.newline_kind(),
1117 uses_trailing_commas: uses_trailing_commas(self.clone().into()),
1118 };
1119 let indents = compute_indents(&self.clone().into());
1120 let mut insert_index = if let Some(root_value) = self.value() {
1121 let index = root_value.child_index();
1122 root_value.remove_raw();
1123 index
1124 } else {
1125 let children = self.children();
1126 let mut index = match children.last() {
1127 Some(CstNode::Leaf(CstLeafNode::Newline(_))) => children.len() - 1,
1128 _ => children.len(),
1129 };
1130 let previous_node = if index == 0 { None } else { children.get(index - 1) };
1131 if let Some(CstNode::Leaf(CstLeafNode::Comment(_))) = previous_node {
1132 container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1134 }
1135 if self.child_at_index(index).is_none() {
1136 container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1138 index -= 1;
1139 }
1140 index
1141 };
1142 container.raw_insert_value_with_internal_indent(
1143 Some(&mut insert_index),
1144 InsertValue::Value(root_value),
1145 &style_info,
1146 &indents,
1147 );
1148 }
1149
1150 pub fn object_value(&self) -> Option<CstObject> {
1152 self.value()?.as_object()
1153 }
1154
1155 pub fn object_value_or_create(&self) -> Option<CstObject> {
1161 match self.value() {
1162 Some(CstNode::Container(CstContainerNode::Object(node))) => Some(node),
1163 Some(_) => None,
1164 None => {
1165 self.set_value(CstInputValue::Object(Vec::new()));
1166 self.object_value()
1167 }
1168 }
1169 }
1170
1171 pub fn object_value_or_set(&self) -> CstObject {
1176 match self.value() {
1177 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1178 _ => {
1179 self.set_value(CstInputValue::Object(Vec::new()));
1180 self.object_value().unwrap()
1181 }
1182 }
1183 }
1184
1185 pub fn array_value(&self) -> Option<CstArray> {
1187 self.value()?.as_array()
1188 }
1189
1190 pub fn array_value_or_create(&self) -> Option<CstArray> {
1196 match self.value() {
1197 Some(CstNode::Container(CstContainerNode::Array(node))) => Some(node),
1198 Some(_) => None,
1199 None => {
1200 self.set_value(CstInputValue::Array(Vec::new()));
1201 self.array_value()
1202 }
1203 }
1204 }
1205
1206 pub fn array_value_or_set(&self) -> CstArray {
1211 match self.value() {
1212 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1213 _ => {
1214 self.set_value(CstInputValue::Array(Vec::new()));
1215 self.array_value().unwrap()
1216 }
1217 }
1218 }
1219
1220 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1226 let Some(value) = self.value() else {
1227 return;
1228 };
1229
1230 match value {
1231 CstNode::Container(container) => match container {
1232 CstContainerNode::Array(n) => n.set_trailing_commas(mode),
1233 CstContainerNode::Object(n) => n.set_trailing_commas(mode),
1234 _ => {}
1235 },
1236 CstNode::Leaf(_) => {}
1237 }
1238 }
1239
1240 pub fn clear_children(&self) {
1242 let children = std::mem::take(&mut self.0.borrow_mut().value);
1243 for child in children {
1244 child.set_parent(None);
1245 }
1246 }
1247}
1248
1249impl Display for CstRootNode {
1250 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1251 for child in &self.0.borrow().value {
1252 write!(f, "{}", child)?;
1253 }
1254 Ok(())
1255 }
1256}
1257
1258#[derive(Debug, Clone)]
1260pub struct CstStringLit(Rc<RefCell<CstValueInner<String>>>);
1261
1262impl_leaf_methods!(CstStringLit, StringLit);
1263
1264impl CstStringLit {
1265 fn new(value: String) -> Self {
1266 Self(CstValueInner::new(value))
1267 }
1268
1269 fn new_escaped(value: &str) -> Self {
1270 Self::new(format!("\"{}\"", value.replace("\"", "\\\"")))
1271 }
1272
1273 pub fn set_raw_value(&self, value: String) {
1275 self.0.borrow_mut().value = value;
1276 }
1277
1278 pub fn raw_value(&self) -> String {
1280 self.0.borrow().value.clone()
1281 }
1282
1283 pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
1285 let inner = self.0.borrow();
1286 crate::string::parse_string(&inner.value)
1287 .map(|value| value.into_owned())
1288 .map_err(|err| err.kind)
1289 }
1290
1291 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1293 replace_with(self.into(), InsertValue::Value(replacement))
1294 }
1295
1296 pub fn remove(self) {
1298 remove_comma_separated(self.into())
1299 }
1300}
1301
1302impl Display for CstStringLit {
1303 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1304 write!(f, "{}", self.0.borrow().value)
1305 }
1306}
1307
1308#[derive(Debug, Clone)]
1310pub struct CstWordLit(Rc<RefCell<CstValueInner<String>>>);
1311
1312impl_leaf_methods!(CstWordLit, WordLit);
1313
1314impl CstWordLit {
1315 fn new(value: String) -> Self {
1316 Self(CstValueInner::new(value))
1317 }
1318
1319 pub fn set_raw_value(&self, value: String) {
1321 self.0.borrow_mut().value = value;
1322 }
1323
1324 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1326 replace_with(self.into(), InsertValue::Value(replacement))
1327 }
1328
1329 pub fn remove(self) {
1331 remove_comma_separated(self.into())
1332 }
1333}
1334
1335impl Display for CstWordLit {
1336 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1337 write!(f, "{}", self.0.borrow().value)
1338 }
1339}
1340
1341#[derive(Debug, Clone)]
1342pub struct CstNumberLit(Rc<RefCell<CstValueInner<String>>>);
1343
1344impl_leaf_methods!(CstNumberLit, NumberLit);
1345
1346impl CstNumberLit {
1347 fn new(value: String) -> Self {
1348 Self(CstValueInner::new(value))
1349 }
1350
1351 pub fn set_raw_value(&self, value: String) {
1353 self.0.borrow_mut().value = value;
1354 }
1355
1356 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1358 replace_with(self.into(), InsertValue::Value(replacement))
1359 }
1360
1361 pub fn remove(self) {
1363 remove_comma_separated(self.into())
1364 }
1365}
1366
1367impl Display for CstNumberLit {
1368 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1369 write!(f, "{}", self.0.borrow().value)
1370 }
1371}
1372
1373#[derive(Debug, Clone)]
1375pub struct CstBooleanLit(Rc<RefCell<CstValueInner<bool>>>);
1376
1377impl_leaf_methods!(CstBooleanLit, BooleanLit);
1378
1379impl CstBooleanLit {
1380 fn new(value: bool) -> Self {
1381 Self(CstValueInner::new(value))
1382 }
1383
1384 pub fn value(&self) -> bool {
1386 self.0.borrow().value
1387 }
1388
1389 pub fn set_value(&self, value: bool) {
1391 self.0.borrow_mut().value = value;
1392 }
1393
1394 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1396 replace_with(self.into(), InsertValue::Value(replacement))
1397 }
1398
1399 pub fn remove(self) {
1401 remove_comma_separated(self.into())
1402 }
1403}
1404
1405impl Display for CstBooleanLit {
1406 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1407 if self.0.borrow().value {
1408 write!(f, "true")
1409 } else {
1410 write!(f, "false")
1411 }
1412 }
1413}
1414
1415#[derive(Debug, Clone)]
1417pub struct CstNullKeyword(Rc<RefCell<CstValueInner<()>>>);
1418
1419impl CstNullKeyword {
1420 fn new() -> Self {
1421 Self(CstValueInner::new(()))
1422 }
1423
1424 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1426 replace_with(self.into(), InsertValue::Value(replacement))
1427 }
1428
1429 pub fn remove(self) {
1431 remove_comma_separated(self.into())
1432 }
1433}
1434
1435impl_leaf_methods!(CstNullKeyword, NullKeyword);
1436
1437impl Display for CstNullKeyword {
1438 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1439 write!(f, "null")
1440 }
1441}
1442
1443type CstObjectInner = RefCell<CstChildrenInner>;
1444
1445#[derive(Debug, Clone)]
1447pub struct CstObject(Rc<CstObjectInner>);
1448
1449impl_container_methods!(CstObject, Object);
1450
1451impl CstObject {
1452 add_root_node_method!();
1453
1454 fn new_no_tokens() -> Self {
1455 Self(CstValueInner::new(Vec::new()))
1456 }
1457
1458 fn new_with_tokens() -> Self {
1459 let object = CstObject::new_no_tokens();
1460 let container: CstContainerNode = object.clone().into();
1461 container.raw_append_children(vec![CstToken::new('{').into(), CstToken::new('}').into()]);
1462 object
1463 }
1464
1465 pub fn array_value(&self, name: &str) -> Option<CstArray> {
1469 match self.get(name)?.value()? {
1470 CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1471 _ => None,
1472 }
1473 }
1474
1475 pub fn array_value_or_create(&self, name: &str) -> Option<CstArray> {
1482 match self.get(name) {
1483 Some(prop) => match prop.value()? {
1484 CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1485 _ => None,
1486 },
1487 None => {
1488 self.append(name, CstInputValue::Array(Vec::new()));
1489 self.array_value(name)
1490 }
1491 }
1492 }
1493
1494 pub fn array_value_or_set(&self, name: &str) -> CstArray {
1499 match self.get(name) {
1500 Some(prop) => match prop.value() {
1501 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1502 Some(node) => {
1503 let mut index = node.child_index();
1504 node.remove_raw();
1505 let container: CstContainerNode = prop.clone().into();
1506 let array = CstArray::new_with_tokens();
1507 container.raw_insert_child(Some(&mut index), array.clone().into());
1508 array
1509 }
1510 _ => {
1511 let mut index = prop.children().len();
1512 let container: CstContainerNode = prop.clone().into();
1513 let array = CstArray::new_with_tokens();
1514 container.raw_insert_child(Some(&mut index), array.clone().into());
1515 array
1516 }
1517 },
1518 None => {
1519 self.append(name, CstInputValue::Array(Vec::new()));
1520 self.array_value(name).unwrap()
1521 }
1522 }
1523 }
1524
1525 pub fn object_value(&self, name: &str) -> Option<CstObject> {
1529 match self.get(name)?.value()? {
1530 CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1531 _ => None,
1532 }
1533 }
1534
1535 pub fn object_value_or_create(&self, name: &str) -> Option<CstObject> {
1542 match self.get(name) {
1543 Some(prop) => match prop.value()? {
1544 CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1545 _ => None,
1546 },
1547 None => {
1548 self.append(name, CstInputValue::Object(Vec::new()));
1549 self.object_value(name)
1550 }
1551 }
1552 }
1553
1554 pub fn object_value_or_set(&self, name: &str) -> CstObject {
1559 match self.get(name) {
1560 Some(prop) => match prop.value() {
1561 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1562 Some(node) => {
1563 let mut index = node.child_index();
1564 node.remove_raw();
1565 let container: CstContainerNode = prop.clone().into();
1566 let object = CstObject::new_with_tokens();
1567 container.raw_insert_child(Some(&mut index), object.clone().into());
1568 object
1569 }
1570 _ => {
1571 let mut index = prop.children().len();
1572 let container: CstContainerNode = prop.clone().into();
1573 let object = CstObject::new_with_tokens();
1574 container.raw_insert_child(Some(&mut index), object.clone().into());
1575 object
1576 }
1577 },
1578 None => {
1579 self.append(name, CstInputValue::Object(Vec::new()));
1580 self.object_value(name).unwrap()
1581 }
1582 }
1583 }
1584
1585 pub fn get(&self, name: &str) -> Option<CstObjectProp> {
1589 for child in &self.0.borrow().value {
1590 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = child {
1591 let Some(prop_name) = prop.name() else {
1592 continue;
1593 };
1594 let Ok(prop_name_str) = prop_name.decoded_value() else {
1595 continue;
1596 };
1597 if prop_name_str == name {
1598 return Some(prop.clone());
1599 }
1600 }
1601 }
1602 None
1603 }
1604
1605 pub fn properties(&self) -> Vec<CstObjectProp> {
1607 self
1608 .0
1609 .borrow()
1610 .value
1611 .iter()
1612 .filter_map(|child| match child {
1613 CstNode::Container(CstContainerNode::ObjectProp(prop)) => Some(prop.clone()),
1614 _ => None,
1615 })
1616 .collect()
1617 }
1618
1619 pub fn append(&self, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1623 self.insert_or_append(None, prop_name, value)
1624 }
1625
1626 pub fn insert(&self, index: usize, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1630 self.insert_or_append(Some(index), prop_name, value)
1631 }
1632
1633 fn insert_or_append(&self, index: Option<usize>, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1634 self.ensure_multiline();
1635 insert_or_append_to_container(
1636 &CstContainerNode::Object(self.clone()),
1637 self.properties().into_iter().map(|c| c.into()).collect(),
1638 index,
1639 InsertValue::Property(prop_name, value),
1640 )
1641 .as_object_prop()
1642 .unwrap()
1643 }
1644
1645 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1647 replace_with(self.into(), InsertValue::Value(replacement))
1648 }
1649
1650 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1652 set_trailing_commas(
1653 mode,
1654 &self.clone().into(),
1655 self.properties().into_iter().map(|c| c.into()),
1656 );
1657 }
1658
1659 pub fn ensure_multiline(&self) {
1661 ensure_multiline(&self.clone().into());
1662 }
1663
1664 pub fn remove(self) {
1666 remove_comma_separated(self.into())
1667 }
1668}
1669
1670impl Display for CstObject {
1671 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1672 for child in &self.0.borrow().value {
1673 write!(f, "{}", child)?;
1674 }
1675 Ok(())
1676 }
1677}
1678
1679type CstObjectPropInner = RefCell<CstChildrenInner>;
1680
1681#[derive(Debug, Clone)]
1683pub struct CstObjectProp(Rc<CstObjectPropInner>);
1684
1685impl_container_methods!(CstObjectProp, ObjectProp);
1686
1687impl CstObjectProp {
1688 add_root_node_method!();
1689
1690 fn new() -> Self {
1691 Self(CstValueInner::new(Vec::new()))
1692 }
1693
1694 pub fn name(&self) -> Option<ObjectPropName> {
1698 for child in &self.0.borrow().value {
1699 match child {
1700 CstNode::Leaf(CstLeafNode::StringLit(node)) => return Some(ObjectPropName::String(node.clone())),
1701 CstNode::Leaf(CstLeafNode::WordLit(node)) => return Some(ObjectPropName::Word(node.clone())),
1702 _ => {
1703 }
1705 }
1706 }
1707 None
1708 }
1709
1710 pub fn property_index(&self) -> usize {
1711 let child_index = self.child_index();
1712 let Some(parent) = self.parent().and_then(|p| p.as_object()) else {
1713 return 0;
1714 };
1715 parent
1716 .properties()
1717 .iter()
1718 .position(|p| p.child_index() == child_index)
1719 .unwrap_or(0)
1720 }
1721
1722 pub fn set_value(&self, replacement: CstInputValue) {
1723 let maybe_value = self.value();
1724 let mut value_index = maybe_value
1725 .as_ref()
1726 .map(|v| v.child_index())
1727 .unwrap_or_else(|| self.children().len());
1728 let container: CstContainerNode = self.clone().into();
1729 let indents = compute_indents(&container.clone().into());
1730 let style_info = &StyleInfo {
1731 newline_kind: container.root_node().map(|v| v.newline_kind()).unwrap_or_default(),
1732 uses_trailing_commas: uses_trailing_commas(maybe_value.unwrap_or_else(|| container.clone().into())),
1733 };
1734 self.remove_child_set_no_parent(value_index);
1735 container.raw_insert_value_with_internal_indent(
1736 Some(&mut value_index),
1737 InsertValue::Value(replacement),
1738 style_info,
1739 &indents,
1740 );
1741 }
1742
1743 pub fn value(&self) -> Option<CstNode> {
1747 let name = self.name()?;
1748 let parent_info = name.parent_info()?;
1749 let children = &self.0.borrow().value;
1750 let mut children = children[parent_info.child_index + 1..].iter();
1751
1752 for child in children.by_ref() {
1754 if let CstNode::Leaf(CstLeafNode::Token(token)) = child {
1755 if token.value() == ':' {
1756 break;
1757 }
1758 }
1759 }
1760
1761 for child in children {
1763 match child {
1764 CstNode::Leaf(leaf) => match leaf {
1765 CstLeafNode::BooleanLit(_)
1766 | CstLeafNode::NullKeyword(_)
1767 | CstLeafNode::NumberLit(_)
1768 | CstLeafNode::StringLit(_)
1769 | CstLeafNode::WordLit(_) => return Some(child.clone()),
1770 CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
1771 }
1773 },
1774 CstNode::Container(container) => match container {
1775 CstContainerNode::Object(_) | CstContainerNode::Array(_) => return Some(child.clone()),
1776 CstContainerNode::Root(_) | CstContainerNode::ObjectProp(_) => return None,
1777 },
1778 }
1779 }
1780
1781 None
1782 }
1783
1784 pub fn object_value(&self) -> Option<CstObject> {
1786 self.value()?.as_object()
1787 }
1788
1789 pub fn object_value_or_set(&self) -> CstObject {
1791 match self.value() {
1792 Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1793 _ => {
1794 self.set_value(CstInputValue::Object(Vec::new()));
1795 self.object_value().unwrap()
1796 }
1797 }
1798 }
1799
1800 pub fn array_value(&self) -> Option<CstArray> {
1802 self.value()?.as_array()
1803 }
1804
1805 pub fn array_value_or_set(&self) -> CstArray {
1807 match self.value() {
1808 Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1809 _ => {
1810 self.set_value(CstInputValue::Array(Vec::new()));
1811 self.array_value().unwrap()
1812 }
1813 }
1814 }
1815
1816 pub fn previous_property(&self) -> Option<CstObjectProp> {
1818 for sibling in self.previous_siblings() {
1819 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1820 return Some(prop);
1821 }
1822 }
1823 None
1824 }
1825
1826 pub fn next_property(&self) -> Option<CstObjectProp> {
1828 for sibling in self.next_siblings() {
1829 if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1830 return Some(prop);
1831 }
1832 }
1833 None
1834 }
1835
1836 pub fn replace_with(self, key: &str, replacement: CstInputValue) -> Option<CstNode> {
1838 replace_with(self.into(), InsertValue::Property(key, replacement))
1839 }
1840
1841 pub fn remove(self) {
1843 remove_comma_separated(self.into())
1844 }
1845}
1846
1847impl Display for CstObjectProp {
1848 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1849 for child in &self.0.borrow().value {
1850 write!(f, "{}", child)?;
1851 }
1852 Ok(())
1853 }
1854}
1855
1856#[derive(Debug, Clone)]
1858pub enum ObjectPropName {
1859 String(CstStringLit),
1860 Word(CstWordLit),
1861}
1862
1863impl ObjectPropName {
1864 add_root_node_method!();
1865 add_parent_info_methods!();
1866
1867 pub fn as_string_lit(&self) -> Option<CstStringLit> {
1869 match self {
1870 ObjectPropName::String(n) => Some(n.clone()),
1871 ObjectPropName::Word(_) => None,
1872 }
1873 }
1874
1875 pub fn as_word_lit(&self) -> Option<CstWordLit> {
1877 match self {
1878 ObjectPropName::String(_) => None,
1879 ObjectPropName::Word(n) => Some(n.clone()),
1880 }
1881 }
1882
1883 pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
1885 match self {
1886 ObjectPropName::String(n) => n.decoded_value(),
1887 ObjectPropName::Word(n) => Ok(n.0.borrow().value.clone()),
1888 }
1889 }
1890
1891 fn parent_info(&self) -> Option<ParentInfo> {
1892 match self {
1893 ObjectPropName::String(n) => n.parent_info(),
1894 ObjectPropName::Word(n) => n.parent_info(),
1895 }
1896 }
1897}
1898
1899impl From<ObjectPropName> for CstNode {
1900 fn from(value: ObjectPropName) -> Self {
1901 match value {
1902 ObjectPropName::String(n) => n.into(),
1903 ObjectPropName::Word(n) => n.into(),
1904 }
1905 }
1906}
1907
1908type CstArrayInner = RefCell<CstChildrenInner>;
1909
1910#[derive(Debug, Clone)]
1912pub struct CstArray(Rc<CstArrayInner>);
1913
1914impl_container_methods!(CstArray, Array);
1915
1916impl CstArray {
1917 add_root_node_method!();
1918
1919 fn new_no_tokens() -> Self {
1920 Self(CstValueInner::new(Vec::new()))
1921 }
1922
1923 fn new_with_tokens() -> Self {
1924 let array = CstArray::new_no_tokens();
1925 let container: CstContainerNode = array.clone().into();
1926 container.raw_append_children(vec![CstToken::new('[').into(), CstToken::new(']').into()]);
1927 array
1928 }
1929
1930 pub fn elements(&self) -> Vec<CstNode> {
1932 self
1933 .0
1934 .borrow()
1935 .value
1936 .iter()
1937 .filter(|child| match child {
1938 CstNode::Container(_) => true,
1939 CstNode::Leaf(leaf) => match leaf {
1940 CstLeafNode::BooleanLit(_)
1941 | CstLeafNode::NullKeyword(_)
1942 | CstLeafNode::NumberLit(_)
1943 | CstLeafNode::StringLit(_)
1944 | CstLeafNode::WordLit(_) => true,
1945 CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
1946 false
1947 }
1948 },
1949 })
1950 .cloned()
1951 .collect()
1952 }
1953
1954 pub fn append(&self, value: CstInputValue) -> CstNode {
1958 self.insert_or_append(None, value)
1959 }
1960
1961 pub fn insert(&self, index: usize, value: CstInputValue) -> CstNode {
1965 self.insert_or_append(Some(index), value)
1966 }
1967
1968 pub fn ensure_multiline(&self) {
1970 ensure_multiline(&self.clone().into());
1971 }
1972
1973 pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1975 set_trailing_commas(mode, &self.clone().into(), self.elements().into_iter());
1976 }
1977
1978 fn insert_or_append(&self, index: Option<usize>, value: CstInputValue) -> CstNode {
1979 insert_or_append_to_container(
1980 &CstContainerNode::Array(self.clone()),
1981 self.elements(),
1982 index,
1983 InsertValue::Value(value),
1984 )
1985 }
1986
1987 pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1989 replace_with(self.into(), InsertValue::Value(replacement))
1990 }
1991
1992 pub fn remove(self) {
1994 remove_comma_separated(self.into())
1995 }
1996}
1997
1998impl Display for CstArray {
1999 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2000 for child in &self.0.borrow().value {
2001 write!(f, "{}", child)?;
2002 }
2003 Ok(())
2004 }
2005}
2006
2007#[derive(Debug, Clone)]
2009pub struct CstToken(Rc<RefCell<CstValueInner<char>>>);
2010
2011impl_leaf_methods!(CstToken, Token);
2012
2013impl CstToken {
2014 fn new(value: char) -> Self {
2015 Self(CstValueInner::new(value))
2016 }
2017
2018 pub fn set_value(&self, value: char) {
2020 self.0.borrow_mut().value = value;
2021 }
2022
2023 pub fn value(&self) -> char {
2025 self.0.borrow().value
2026 }
2027
2028 pub fn remove(self) {
2030 Into::<CstNode>::into(self).remove_raw()
2031 }
2032}
2033
2034impl Display for CstToken {
2035 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2036 write!(f, "{}", self.0.borrow().value)
2037 }
2038}
2039
2040#[derive(Debug, Clone)]
2042pub struct CstWhitespace(Rc<RefCell<CstValueInner<String>>>);
2043
2044impl_leaf_methods!(CstWhitespace, Whitespace);
2045
2046impl CstWhitespace {
2047 fn new(value: String) -> Self {
2048 Self(CstValueInner::new(value))
2049 }
2050
2051 pub fn set_value(&self, value: String) {
2053 self.0.borrow_mut().value = value;
2054 }
2055
2056 pub fn value(&self) -> String {
2058 self.0.borrow().value.clone()
2059 }
2060
2061 pub fn remove(self) {
2063 Into::<CstNode>::into(self).remove_raw()
2064 }
2065}
2066
2067impl Display for CstWhitespace {
2068 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2069 write!(f, "{}", self.0.borrow().value)
2070 }
2071}
2072
2073#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
2075pub enum CstNewlineKind {
2076 #[default]
2077 LineFeed,
2078 CarriageReturnLineFeed,
2079}
2080
2081#[derive(Debug, Clone)]
2083pub struct CstNewline(Rc<RefCell<CstValueInner<CstNewlineKind>>>);
2084
2085impl_leaf_methods!(CstNewline, Newline);
2086
2087impl CstNewline {
2088 fn new(kind: CstNewlineKind) -> Self {
2089 Self(CstValueInner::new(kind))
2090 }
2091
2092 pub fn kind(&self) -> CstNewlineKind {
2094 self.0.borrow().value
2095 }
2096
2097 pub fn set_kind(&self, kind: CstNewlineKind) {
2099 self.0.borrow_mut().value = kind;
2100 }
2101
2102 pub fn remove(self) {
2104 Into::<CstNode>::into(self).remove_raw()
2105 }
2106}
2107
2108impl Display for CstNewline {
2109 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2110 match self.0.borrow().value {
2111 #[allow(clippy::write_with_newline)] CstNewlineKind::LineFeed => write!(f, "\n"),
2113 CstNewlineKind::CarriageReturnLineFeed => write!(f, "\r\n"),
2114 }
2115 }
2116}
2117
2118#[derive(Debug, Clone)]
2119pub struct CstComment(Rc<RefCell<CstValueInner<String>>>);
2120
2121impl_leaf_methods!(CstComment, Comment);
2122
2123impl CstComment {
2124 fn new(value: String) -> Self {
2125 Self(CstValueInner::new(value))
2126 }
2127
2128 pub fn is_line_comment(&self) -> bool {
2130 self.0.borrow().value.starts_with("//")
2131 }
2132
2133 pub fn set_raw_value(&self, value: String) {
2138 self.0.borrow_mut().value = value;
2139 }
2140
2141 pub fn raw_value(&self) -> String {
2143 self.0.borrow().value.clone()
2144 }
2145
2146 pub fn remove(self) {
2148 if self.is_line_comment() {
2149 for node in self.previous_siblings() {
2150 if node.is_whitespace() {
2151 node.remove_raw();
2152 } else {
2153 if node.is_newline() {
2154 node.remove_raw();
2155 }
2156 break;
2157 }
2158 }
2159 }
2160
2161 Into::<CstNode>::into(self).remove_raw()
2162 }
2163}
2164
2165impl Display for CstComment {
2166 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2167 write!(f, "{}", self.0.borrow().value)
2168 }
2169}
2170
2171struct CstBuilder<'a> {
2172 pub text: &'a str,
2173 pub tokens: VecDeque<crate::tokens::TokenAndRange<'a>>,
2174}
2175
2176impl<'a> CstBuilder<'a> {
2177 pub fn build(&mut self, ast_value: Option<crate::ast::Value<'a>>) -> CstRootNode {
2178 let root_node = CstContainerNode::Root(CstRootNode(Rc::new(RefCell::new(CstChildrenInner {
2179 parent: None,
2180 value: Vec::new(),
2181 }))));
2182
2183 if let Some(ast_value) = ast_value {
2184 let range = ast_value.range();
2185 self.scan_from_to(&root_node, 0, range.start);
2186 self.build_value(&root_node, ast_value);
2187 self.scan_from_to(&root_node, range.end, self.text.len());
2188 } else {
2189 self.scan_from_to(&root_node, 0, self.text.len());
2190 }
2191
2192 match root_node {
2193 CstContainerNode::Root(node) => node,
2194 _ => unreachable!(),
2195 }
2196 }
2197
2198 fn scan_from_to(&mut self, container: &CstContainerNode, from: usize, to: usize) {
2199 if from == to {
2200 return;
2201 }
2202
2203 let mut last_from = from;
2204 while let Some(token) = self.tokens.front() {
2205 if token.range.end <= from {
2206 self.tokens.pop_front();
2207 } else if token.range.start < to {
2208 if token.range.start > last_from {
2209 self.build_whitespace(container, &self.text[last_from..token.range.start]);
2210 }
2211 let token = self.tokens.pop_front().unwrap();
2212 match token.token {
2213 crate::tokens::Token::OpenBrace
2214 | crate::tokens::Token::CloseBrace
2215 | crate::tokens::Token::OpenBracket
2216 | crate::tokens::Token::CloseBracket
2217 | crate::tokens::Token::Comma
2218 | crate::tokens::Token::Colon => {
2219 self.build_token(container, token.token.as_str().chars().next().unwrap());
2220 }
2221 crate::tokens::Token::Null
2222 | crate::tokens::Token::String(_)
2223 | crate::tokens::Token::Word(_)
2224 | crate::tokens::Token::Boolean(_)
2225 | crate::tokens::Token::Number(_) => unreachable!(
2226 "programming error parsing cst {:?} scanning {} to {}",
2227 token.token, from, to
2228 ),
2229 crate::tokens::Token::CommentLine(_) | crate::tokens::Token::CommentBlock(_) => {
2230 container
2231 .raw_append_child(CstComment::new(self.text[token.range.start..token.range.end].to_string()).into());
2232 }
2233 }
2234 last_from = token.range.end;
2235 } else {
2236 break;
2237 }
2238 }
2239
2240 if last_from < to {
2241 self.build_whitespace(container, &self.text[last_from..to]);
2242 }
2243 }
2244
2245 fn build_value(&mut self, container: &CstContainerNode, ast_value: ast::Value<'_>) {
2246 match ast_value {
2247 ast::Value::StringLit(string_lit) => self.build_string_lit(container, string_lit),
2248 ast::Value::NumberLit(number_lit) => {
2249 container.raw_append_child(CstNumberLit::new(number_lit.value.to_string()).into())
2250 }
2251 ast::Value::BooleanLit(boolean_lit) => container.raw_append_child(CstBooleanLit::new(boolean_lit.value).into()),
2252 ast::Value::Object(object) => {
2253 let object = self.build_object(object);
2254 container.raw_append_child(object.into())
2255 }
2256 ast::Value::Array(array) => {
2257 let array = self.build_array(array);
2258 container.raw_append_child(array.into())
2259 }
2260 ast::Value::NullKeyword(_) => container.raw_append_child(CstNullKeyword::new().into()),
2261 }
2262 }
2263
2264 fn build_object(&mut self, object: ast::Object<'_>) -> CstContainerNode {
2265 let container = CstContainerNode::Object(CstObject::new_no_tokens());
2266 let mut last_range_end = object.range.start;
2267 for prop in object.properties {
2268 self.scan_from_to(&container, last_range_end, prop.range.start);
2269 last_range_end = prop.range.end;
2270 let object_prop = self.build_object_prop(prop);
2271 container.raw_append_child(CstNode::Container(object_prop));
2272 }
2273 self.scan_from_to(&container, last_range_end, object.range.end);
2274
2275 container
2276 }
2277
2278 fn build_object_prop(&mut self, prop: ast::ObjectProp<'_>) -> CstContainerNode {
2279 let container = CstContainerNode::ObjectProp(CstObjectProp::new());
2280 let name_range = prop.name.range();
2281 let value_range = prop.value.range();
2282
2283 match prop.name {
2284 ast::ObjectPropName::String(string_lit) => {
2285 self.build_string_lit(&container, string_lit);
2286 }
2287 ast::ObjectPropName::Word(word_lit) => {
2288 container.raw_append_child(CstWordLit::new(word_lit.value.to_string()).into());
2289 }
2290 }
2291
2292 self.scan_from_to(&container, name_range.end, value_range.start);
2293 self.build_value(&container, prop.value);
2294
2295 container
2296 }
2297
2298 fn build_token(&self, container: &CstContainerNode, value: char) {
2299 container.raw_append_child(CstToken::new(value).into());
2300 }
2301
2302 fn build_whitespace(&self, container: &CstContainerNode, value: &str) {
2303 if value.is_empty() {
2304 return;
2305 }
2306
2307 let mut last_found_index = 0;
2308 let mut chars = value.char_indices().peekable();
2309 let maybe_add_previous_text = |from: usize, to: usize| {
2310 let text = &value[from..to];
2311 if !text.is_empty() {
2312 container.raw_append_child(CstWhitespace::new(text.to_string()).into());
2313 }
2314 };
2315 while let Some((i, c)) = chars.next() {
2316 if c == '\r' && chars.peek().map(|(_, c)| *c) == Some('\n') {
2317 maybe_add_previous_text(last_found_index, i);
2318 container.raw_append_child(CstNewline::new(CstNewlineKind::CarriageReturnLineFeed).into());
2319 last_found_index = i + 2;
2320 chars.next(); } else if c == '\n' {
2322 maybe_add_previous_text(last_found_index, i);
2323 container.raw_append_child(CstNewline::new(CstNewlineKind::LineFeed).into());
2324 last_found_index = i + 1;
2325 }
2326 }
2327
2328 maybe_add_previous_text(last_found_index, value.len());
2329 }
2330
2331 fn build_string_lit(&self, container: &CstContainerNode, lit: ast::StringLit<'_>) {
2332 container.raw_append_child(CstStringLit::new(self.text[lit.range.start..lit.range.end].to_string()).into());
2333 }
2334
2335 fn build_array(&mut self, array: ast::Array<'_>) -> CstContainerNode {
2336 let container = CstContainerNode::Array(CstArray::new_no_tokens());
2337 let mut last_range_end = array.range.start;
2338 for element in array.elements {
2339 let element_range = element.range();
2340 self.scan_from_to(&container, last_range_end, element_range.start);
2341 self.build_value(&container, element);
2342 last_range_end = element_range.end;
2343 }
2344 self.scan_from_to(&container, last_range_end, array.range.end);
2345
2346 container
2347 }
2348}
2349
2350fn remove_comma_separated(node: CstNode) {
2351 fn check_next_node_same_line(trailing_comma: &CstToken) -> bool {
2352 for sibling in trailing_comma.next_siblings() {
2353 match sibling {
2354 CstNode::Container(_) => return true,
2355 CstNode::Leaf(n) => match n {
2356 CstLeafNode::BooleanLit(_)
2357 | CstLeafNode::NullKeyword(_)
2358 | CstLeafNode::NumberLit(_)
2359 | CstLeafNode::StringLit(_)
2360 | CstLeafNode::WordLit(_)
2361 | CstLeafNode::Token(_) => return true,
2362 CstLeafNode::Whitespace(_) | CstLeafNode::Comment(_) => {
2363 }
2365 CstLeafNode::Newline(_) => return false,
2366 },
2367 }
2368 }
2369
2370 true
2371 }
2372
2373 let parent = node.parent();
2374 let trailing_comma = node.trailing_comma();
2375 let is_in_array_or_obj = parent
2376 .as_ref()
2377 .map(|p| matches!(p, CstContainerNode::Array(_) | CstContainerNode::Object(_)))
2378 .unwrap_or(false);
2379 let remove_up_to_next_line = trailing_comma
2380 .as_ref()
2381 .map(|c| !check_next_node_same_line(c))
2382 .unwrap_or(true);
2383
2384 for previous in node.previous_siblings() {
2385 if previous.is_trivia() && !previous.is_newline() {
2386 previous.remove_raw();
2387 } else {
2388 break;
2389 }
2390 }
2391
2392 let mut found_newline = false;
2393 let mut next_siblings = node.next_siblings();
2394
2395 if trailing_comma.is_some() {
2397 for next in next_siblings.by_ref() {
2398 let is_comma = next.is_comma();
2399 if next.is_newline() {
2400 found_newline = true;
2401 }
2402 next.remove_raw();
2403 if is_comma {
2404 break;
2405 }
2406 }
2407 } else if is_in_array_or_obj {
2408 if let Some(previous_comma) = node.previous_siblings().find(|n| n.is_comma()) {
2409 previous_comma.remove();
2410 }
2411 }
2412
2413 if remove_up_to_next_line && !found_newline {
2415 let mut next_siblings = node.next_siblings().peekable();
2416 while let Some(sibling) = next_siblings.next() {
2417 if sibling.is_trivia() {
2418 if sibling.is_newline() {
2419 sibling.remove_raw();
2420 break;
2421 } else if sibling.is_whitespace()
2422 && next_siblings
2423 .peek()
2424 .map(|n| !n.is_whitespace() && !n.is_newline() && !n.is_comment())
2425 .unwrap_or(false)
2426 {
2427 break;
2428 }
2429 sibling.remove_raw();
2430 } else {
2431 break;
2432 }
2433 }
2434 }
2435
2436 node.remove_raw();
2437
2438 if let Some(parent) = parent {
2439 match parent {
2440 CstContainerNode::Root(n) => {
2441 if n.children().iter().all(|c| c.is_whitespace() || c.is_newline()) {
2442 n.clear_children();
2443 }
2444 }
2445 CstContainerNode::Object(_) | CstContainerNode::Array(_) => {
2446 let children = parent.children();
2447 if children
2448 .iter()
2449 .skip(1)
2450 .take(children.len() - 2)
2451 .all(|c| c.is_whitespace() || c.is_newline())
2452 {
2453 for c in children {
2454 if c.is_whitespace() || c.is_newline() {
2455 c.remove();
2456 }
2457 }
2458 }
2459 }
2460 CstContainerNode::ObjectProp(_) => {}
2461 }
2462 }
2463}
2464
2465fn indent_text(node: &CstNode) -> Option<String> {
2466 let mut last_whitespace: Option<String> = None;
2467 for previous_sibling in node.previous_siblings() {
2468 match previous_sibling {
2469 CstNode::Container(_) => return None,
2470 CstNode::Leaf(leaf) => match leaf {
2471 CstLeafNode::Newline(_) => {
2472 return last_whitespace;
2473 }
2474 CstLeafNode::Whitespace(whitespace) => {
2475 last_whitespace = match last_whitespace {
2476 Some(last_whitespace) => Some(format!("{}{}", whitespace.value(), last_whitespace)),
2477 None => Some(whitespace.value()),
2478 };
2479 }
2480 CstLeafNode::Comment(_) => {
2481 last_whitespace = None;
2482 }
2483 _ => return None,
2484 },
2485 }
2486 }
2487 last_whitespace
2488}
2489
2490fn uses_trailing_commas(node: CstNode) -> bool {
2491 let node = match node {
2492 CstNode::Container(node) => node,
2493 CstNode::Leaf(_) => return false,
2494 };
2495 let mut pending_nodes: VecDeque<CstContainerNode> = VecDeque::from([node.clone()]);
2496 while let Some(node) = pending_nodes.pop_front() {
2497 let children = node.children();
2498 if !node.is_root() {
2499 if let Some(object) = node.as_object() {
2500 if children.iter().any(|c| c.is_whitespace()) {
2501 let properties = object.properties();
2502 if let Some(last_property) = properties.last() {
2503 return last_property.trailing_comma().is_some();
2504 }
2505 }
2506 } else if let Some(object) = node.as_array() {
2507 if children.iter().any(|c| c.is_whitespace()) {
2508 let elements = object.elements();
2509 if let Some(last_property) = elements.last() {
2510 return last_property.trailing_comma().is_some();
2511 }
2512 }
2513 }
2514 }
2515
2516 for child in children {
2517 if let CstNode::Container(child) = child {
2518 pending_nodes.push_back(child);
2519 }
2520 }
2521 }
2522
2523 false }
2525
2526fn replace_with(node: CstNode, replacement: InsertValue) -> Option<CstNode> {
2527 let mut child_index = node.child_index();
2528 let parent = node.parent()?;
2529 let indents = compute_indents(&parent.clone().into());
2530 let style_info = StyleInfo {
2531 newline_kind: parent.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2532 uses_trailing_commas: uses_trailing_commas(parent.clone().into()),
2533 };
2534 parent.remove_child_set_no_parent(child_index);
2535 parent.raw_insert_value_with_internal_indent(Some(&mut child_index), replacement, &style_info, &indents);
2536 parent.child_at_index(child_index - 1)
2537}
2538
2539enum InsertValue<'a> {
2540 Value(CstInputValue),
2541 Property(&'a str, CstInputValue),
2542}
2543
2544fn insert_or_append_to_container(
2545 container: &CstContainerNode,
2546 elements: Vec<CstNode>,
2547 index: Option<usize>,
2548 value: InsertValue,
2549) -> CstNode {
2550 fn has_separating_newline(siblings: impl Iterator<Item = CstNode>) -> bool {
2551 for sibling in siblings {
2552 if sibling.is_newline() {
2553 return true;
2554 } else if sibling.is_trivia() {
2555 continue;
2556 } else {
2557 break;
2558 }
2559 }
2560 false
2561 }
2562
2563 trim_inner_start_and_end_blanklines(container);
2564
2565 let children = container.children();
2566 let index = index.unwrap_or(elements.len());
2567 let index = std::cmp::min(index, elements.len());
2568 let next_node = elements.get(index);
2569 let previous_node = if index == 0 { None } else { elements.get(index - 1) };
2570 let style_info = StyleInfo {
2571 newline_kind: container.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2572 uses_trailing_commas: uses_trailing_commas(container.clone().into()),
2573 };
2574 let indents = compute_indents(&container.clone().into());
2575 let child_indents = elements
2576 .first()
2577 .map(compute_indents)
2578 .unwrap_or_else(|| indents.indent());
2579 let has_newline = children.iter().any(|child| child.is_newline());
2580 let force_multiline = has_newline
2581 || match &value {
2582 InsertValue::Value(v) => v.force_multiline(),
2583 InsertValue::Property(..) => true,
2584 };
2585 let mut insert_index: usize;
2586 let inserted_node: CstNode;
2587 if let Some(previous_node) = previous_node {
2588 if previous_node.trailing_comma().is_none() {
2589 let mut index = previous_node.child_index() + 1;
2590 container.raw_insert_child(Some(&mut index), CstToken::new(',').into());
2591 }
2592
2593 let trailing_comma: CstNode = previous_node.trailing_comma().unwrap().into();
2594 insert_index = trailing_comma
2595 .trailing_comments_same_line()
2596 .last()
2597 .map(|t| t.child_index())
2598 .unwrap_or_else(|| trailing_comma.child_index())
2599 + 1;
2600 if force_multiline {
2601 container.raw_insert_children(
2602 Some(&mut insert_index),
2603 vec![
2604 CstNewline::new(style_info.newline_kind).into(),
2605 CstStringLit::new(child_indents.current_indent.clone()).into(),
2606 ],
2607 );
2608 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2609 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2610 } else {
2611 container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2612 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2613 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2614 }
2615 } else {
2616 insert_index = if elements.is_empty() {
2617 children
2618 .iter()
2619 .rev()
2620 .skip(1)
2621 .take_while(|t| t.is_whitespace() || t.is_newline())
2622 .last()
2623 .unwrap_or_else(|| children.last().unwrap())
2624 .child_index()
2625 } else {
2626 children.first().unwrap().child_index() + 1
2627 };
2628 if force_multiline {
2629 container.raw_insert_children(
2630 Some(&mut insert_index),
2631 vec![
2632 CstNewline::new(style_info.newline_kind).into(),
2633 CstStringLit::new(child_indents.current_indent.clone()).into(),
2634 ],
2635 );
2636 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2637 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2638 if next_node.is_none()
2639 && !has_separating_newline(container.child_at_index(insert_index - 1).unwrap().next_siblings())
2640 {
2641 container.raw_insert_children(
2642 Some(&mut insert_index),
2643 vec![
2644 CstNewline::new(style_info.newline_kind).into(),
2645 CstStringLit::new(indents.current_indent.clone()).into(),
2646 ],
2647 );
2648 }
2649 } else {
2650 container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2651 inserted_node = container.child_at_index(insert_index - 1).unwrap();
2652 }
2653 }
2654
2655 if next_node.is_some() {
2656 container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2657
2658 if force_multiline {
2659 let comma_token = container.child_at_index(insert_index - 1).unwrap();
2660 if !has_separating_newline(comma_token.next_siblings()) {
2661 container.raw_insert_children(
2662 Some(&mut insert_index),
2663 vec![
2664 CstNewline::new(style_info.newline_kind).into(),
2665 CstStringLit::new(indents.current_indent.clone()).into(),
2666 ],
2667 );
2668 }
2669 } else {
2670 container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2671 }
2672 } else if style_info.uses_trailing_commas && force_multiline {
2673 container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2674 }
2675
2676 inserted_node
2677}
2678
2679fn set_trailing_commas(
2680 mode: TrailingCommaMode,
2681 parent: &CstContainerNode,
2682 elems_or_props: impl Iterator<Item = CstNode>,
2683) {
2684 let mut elems_or_props = elems_or_props.peekable();
2685 let use_trailing_commas = match mode {
2686 TrailingCommaMode::Never => false,
2687 TrailingCommaMode::IfMultiline => true,
2688 };
2689 while let Some(element) = elems_or_props.next() {
2690 if elems_or_props.peek().is_none() {
2692 if use_trailing_commas {
2693 if element.trailing_comma().is_none() && parent.children().iter().any(|c| c.is_newline()) {
2694 let mut insert_index = element.child_index() + 1;
2695 parent.raw_insert_child(Some(&mut insert_index), CstToken::new(',').into());
2696 }
2697 } else if let Some(trailing_comma) = element.trailing_comma() {
2698 trailing_comma.remove();
2699 }
2700 }
2701
2702 let maybe_prop_value = element.as_object_prop().and_then(|p| p.value());
2704 match maybe_prop_value.unwrap_or(element) {
2705 CstNode::Container(CstContainerNode::Array(array)) => {
2706 array.set_trailing_commas(mode);
2707 }
2708 CstNode::Container(CstContainerNode::Object(object)) => {
2709 object.set_trailing_commas(mode);
2710 }
2711 _ => {}
2712 }
2713 }
2714}
2715
2716fn trim_inner_start_and_end_blanklines(node: &CstContainerNode) {
2717 fn remove_blank_lines_after_first(children: &mut Peekable<impl Iterator<Item = CstNode>>) {
2718 for child in children.by_ref() {
2720 if child.is_whitespace() {
2721 } else if child.is_newline() {
2723 break; } else {
2725 return; }
2727 }
2728
2729 let mut pending = Vec::new();
2730 for child in children.by_ref() {
2731 if child.is_whitespace() {
2732 pending.push(child);
2733 } else if child.is_newline() {
2734 child.remove();
2735 for child in pending.drain(..) {
2736 child.remove();
2737 }
2738 } else {
2739 break;
2740 }
2741 }
2742 }
2743
2744 let children = node.children();
2745 let len = children.len();
2746
2747 if len < 2 {
2748 return; }
2750
2751 let mut children = children.into_iter().skip(1).take(len - 2).peekable();
2753 remove_blank_lines_after_first(&mut children);
2754 let mut children = children.rev().peekable();
2755 remove_blank_lines_after_first(&mut children);
2756}
2757
2758fn ensure_multiline(container: &CstContainerNode) {
2759 let children = container.children();
2760 if children.iter().any(|c| c.is_newline()) {
2761 return;
2762 }
2763
2764 let indents = compute_indents(&container.clone().into());
2765 let child_indents = indents.indent();
2766 let newline_kind = container
2767 .root_node()
2768 .map(|r| r.newline_kind())
2769 .unwrap_or(CstNewlineKind::LineFeed);
2770
2771 let children_len = children.len();
2773 let mut children = children.into_iter().skip(1).peekable().take(children_len - 2);
2774 let mut index = 1;
2775 while let Some(child) = children.next() {
2776 if child.is_whitespace() {
2777 child.remove();
2778 continue;
2779 } else {
2780 container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2782 container.raw_insert_child(
2783 Some(&mut index),
2784 CstWhitespace::new(child_indents.current_indent.clone()).into(),
2785 );
2786
2787 index += 1;
2789
2790 let mut trailing_whitespace = Vec::new();
2792 for next_child in children.by_ref() {
2793 if next_child.is_whitespace() {
2794 trailing_whitespace.push(next_child);
2795 } else {
2796 index += 1 + trailing_whitespace.len();
2797 trailing_whitespace.clear();
2798 if next_child.token_char() == Some(',') {
2799 break;
2800 }
2801 }
2802 }
2803
2804 for trailing_whitespace in trailing_whitespace {
2805 trailing_whitespace.remove();
2806 }
2807 }
2808 }
2809
2810 container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2812 if !indents.current_indent.is_empty() {
2813 container.raw_insert_child(Some(&mut index), CstWhitespace::new(indents.current_indent).into());
2814 }
2815}
2816
2817#[derive(Debug)]
2818struct Indents {
2819 current_indent: String,
2820 single_indent: String,
2821}
2822
2823impl Indents {
2824 pub fn indent(&self) -> Indents {
2825 Indents {
2826 current_indent: format!("{}{}", self.current_indent, self.single_indent),
2827 single_indent: self.single_indent.clone(),
2828 }
2829 }
2830}
2831
2832fn compute_indents(node: &CstNode) -> Indents {
2833 let mut indent_level = 0;
2834 let mut stored_last_indent = node.indent_text();
2835 let mut ancestors = node.ancestors().peekable();
2836
2837 while ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
2838 ancestors.next();
2839 }
2840
2841 while let Some(ancestor) = ancestors.next() {
2842 if ancestor.is_root() {
2843 break;
2844 }
2845
2846 if ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
2847 continue;
2848 }
2849
2850 indent_level += 1;
2851
2852 if let Some(indent_text) = ancestor.indent_text() {
2853 match stored_last_indent {
2854 Some(last_indent) => {
2855 if let Some(single_indent_text) = last_indent.strip_prefix(&indent_text) {
2856 return Indents {
2857 current_indent: format!("{}{}", last_indent, single_indent_text.repeat(indent_level - 1)),
2858 single_indent: single_indent_text.to_string(),
2859 };
2860 }
2861 stored_last_indent = None;
2862 }
2863 None => {
2864 stored_last_indent = Some(indent_text);
2865 }
2866 }
2867 } else {
2868 stored_last_indent = None;
2869 }
2870 }
2871
2872 if indent_level == 1 {
2873 if let Some(indent_text) = node.indent_text() {
2874 return Indents {
2875 current_indent: indent_text.clone(),
2876 single_indent: indent_text,
2877 };
2878 }
2879 }
2880
2881 if let Some(root_value) = node.root_node().and_then(|r| r.value()) {
2883 for child in root_value.children() {
2884 if let Some(single_indent) = child.indent_text() {
2885 return Indents {
2886 current_indent: single_indent.repeat(indent_level),
2887 single_indent,
2888 };
2889 }
2890 }
2891 }
2892
2893 let single_indent = " ";
2895 Indents {
2896 current_indent: single_indent.repeat(indent_level),
2897 single_indent: single_indent.to_string(),
2898 }
2899}
2900
2901struct AncestorIterator {
2902 next: Option<CstContainerNode>,
2905}
2906
2907impl AncestorIterator {
2908 pub fn new(node: CstNode) -> Self {
2909 Self {
2910 next: node.parent_info().map(|i| i.parent.as_container_node()),
2911 }
2912 }
2913}
2914
2915impl Iterator for AncestorIterator {
2916 type Item = CstContainerNode;
2917
2918 fn next(&mut self) -> Option<Self::Item> {
2919 let next = self.next.take()?;
2920 self.next = next.parent_info().map(|i| i.parent.as_container_node());
2921 Some(next)
2922 }
2923}
2924
2925struct NextSiblingIterator {
2926 next: Option<CstNode>,
2929}
2930
2931impl NextSiblingIterator {
2932 pub fn new(node: CstNode) -> Self {
2933 Self {
2934 next: node.next_sibling(),
2935 }
2936 }
2937}
2938
2939impl Iterator for NextSiblingIterator {
2940 type Item = CstNode;
2941
2942 fn next(&mut self) -> Option<Self::Item> {
2943 let next_sibling = self.next.take()?;
2944 self.next = next_sibling.next_sibling();
2945 Some(next_sibling)
2946 }
2947}
2948
2949struct PreviousSiblingIterator {
2950 previous: Option<CstNode>,
2953}
2954
2955impl PreviousSiblingIterator {
2956 pub fn new(node: CstNode) -> Self {
2957 Self {
2958 previous: node.previous_sibling(),
2959 }
2960 }
2961}
2962
2963impl Iterator for PreviousSiblingIterator {
2964 type Item = CstNode;
2965
2966 fn next(&mut self) -> Option<Self::Item> {
2967 let previous_sibling = self.previous.take()?;
2968 self.previous = previous_sibling.previous_sibling();
2969 Some(previous_sibling)
2970 }
2971}
2972
2973#[cfg(test)]
2974mod test {
2975 use pretty_assertions::assert_eq;
2976
2977 use crate::cst::CstInputValue;
2978 use crate::cst::TrailingCommaMode;
2979 use crate::json;
2980
2981 use super::CstRootNode;
2982
2983 #[test]
2984 fn single_indent_text() {
2985 let cases = [
2986 (
2987 " ",
2988 r#"
2989{
2990 "prop": {
2991 "nested": 4
2992 }
2993}
2994 "#,
2995 ),
2996 (
2997 " ",
2998 r#"
2999{
3000 /* test */ "prop": {}
3001}
3002 "#,
3003 ),
3004 (
3005 " ",
3006 r#"
3007{
3008 /* test */ "prop": {}
3009}
3010 "#,
3011 ),
3012 (
3013 "\t",
3014 "
3015{
3016\t/* test */ \"prop\": {}
3017}
3018 ",
3019 ),
3020 ];
3021 for (expected, text) in cases {
3022 let root = build_cst(text);
3023 assert_eq!(root.single_indent_text(), Some(expected.to_string()), "Text: {}", text);
3024 }
3025 }
3026
3027 #[test]
3028 fn modify_values() {
3029 let cst = build_cst(
3030 r#"{
3031 "value": 5,
3032 // comment
3033 "value2": "hello",
3034 value3: true
3035}"#,
3036 );
3037
3038 let root_value = cst.value().unwrap();
3039 let root_obj = root_value.as_object().unwrap();
3040 {
3041 let prop = root_obj.get("value").unwrap();
3042 prop
3043 .value()
3044 .unwrap()
3045 .as_number_lit()
3046 .unwrap()
3047 .set_raw_value("10".to_string());
3048 assert!(prop.trailing_comma().is_some());
3049 assert!(prop.previous_property().is_none());
3050 assert_eq!(
3051 prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3052 "value2"
3053 );
3054 assert_eq!(prop.indent_text().unwrap(), " ");
3055 }
3056 {
3057 let prop = root_obj.get("value2").unwrap();
3058 prop
3059 .value()
3060 .unwrap()
3061 .as_string_lit()
3062 .unwrap()
3063 .set_raw_value("\"5\"".to_string());
3064 assert!(prop.trailing_comma().is_some());
3065 assert_eq!(
3066 prop
3067 .previous_property()
3068 .unwrap()
3069 .name()
3070 .unwrap()
3071 .decoded_value()
3072 .unwrap(),
3073 "value"
3074 );
3075 assert_eq!(
3076 prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3077 "value3"
3078 );
3079 }
3080 {
3081 let prop = root_obj.get("value3").unwrap();
3082 prop.value().unwrap().as_boolean_lit().unwrap().set_value(false);
3083 prop
3084 .name()
3085 .unwrap()
3086 .as_word_lit()
3087 .unwrap()
3088 .set_raw_value("value4".to_string());
3089 assert!(prop.trailing_comma().is_none());
3090 assert_eq!(
3091 prop
3092 .previous_property()
3093 .unwrap()
3094 .name()
3095 .unwrap()
3096 .decoded_value()
3097 .unwrap(),
3098 "value2"
3099 );
3100 assert!(prop.next_property().is_none());
3101 }
3102
3103 assert_eq!(
3104 cst.to_string(),
3105 r#"{
3106 "value": 10,
3107 // comment
3108 "value2": "5",
3109 value4: false
3110}"#
3111 );
3112 }
3113
3114 #[test]
3115 fn remove_properties() {
3116 fn run_test(prop_name: &str, json: &str, expected: &str) {
3117 let cst = build_cst(json);
3118 let root_value = cst.value().unwrap();
3119 let root_obj = root_value.as_object().unwrap();
3120 let prop = root_obj.get(prop_name).unwrap();
3121 prop.remove();
3122 assert_eq!(cst.to_string(), expected);
3123 }
3124
3125 run_test(
3126 "value2",
3127 r#"{
3128 "value": 5,
3129 // comment
3130 "value2": "hello",
3131 value3: true
3132}"#,
3133 r#"{
3134 "value": 5,
3135 // comment
3136 value3: true
3137}"#,
3138 );
3139
3140 run_test(
3141 "value2",
3142 r#"{
3143 "value": 5,
3144 // comment
3145 "value2": "hello"
3146 ,value3: true
3147}"#,
3148 r#"{
3150 "value": 5,
3151 // comment
3152value3: true
3153}"#,
3154 );
3155
3156 run_test("value", r#"{ "value": 5 }"#, r#"{}"#);
3157 run_test("value", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value2": 6 }"#);
3158 run_test("value2", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value": 5 }"#);
3159 }
3160
3161 #[test]
3162 fn insert_properties() {
3163 fn run_test(index: usize, prop_name: &str, value: CstInputValue, json: &str, expected: &str) {
3164 let cst = build_cst(json);
3165 let root_value = cst.value().unwrap();
3166 let root_obj = root_value.as_object().unwrap();
3167 root_obj.insert(index, prop_name, value);
3168 assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3169 }
3170
3171 run_test(
3172 0,
3173 "propName",
3174 json!([1]),
3175 r#"{}"#,
3176 r#"{
3177 "propName": [1]
3178}"#,
3179 );
3180
3181 run_test(
3183 0,
3184 "value0",
3185 json!([1]),
3186 r#"{
3187 "value1": 5
3188}"#,
3189 r#"{
3190 "value0": [1],
3191 "value1": 5
3192}"#,
3193 );
3194
3195 run_test(
3197 0,
3198 "value0",
3199 json!([1]),
3200 r#"{
3201 // some comment
3202 "value1": 5
3203}"#,
3204 r#"{
3205 "value0": [1],
3206 // some comment
3207 "value1": 5
3208}"#,
3209 );
3210
3211 run_test(
3213 1,
3214 "value1",
3215 json!({
3216 "value": 1
3217 }),
3218 r#"{
3219 "value0": 5 // comment
3220}"#,
3221 r#"{
3222 "value0": 5, // comment
3223 "value1": {
3224 "value": 1
3225 }
3226}"#,
3227 );
3228
3229 run_test(
3231 1,
3232 "propName",
3233 json!(true),
3234 r#"{
3235 "value": 4,
3236}"#,
3237 r#"{
3238 "value": 4,
3239 "propName": true,
3240}"#,
3241 );
3242
3243 run_test(
3245 1,
3246 "propName",
3247 json!(true),
3248 r#"{ "value": 4 }"#,
3249 r#"{
3250 "value": 4,
3251 "propName": true
3252}"#,
3253 );
3254
3255 run_test(
3257 1,
3258 "propName",
3259 json!(true),
3260 r#"{ "value": 4, }"#,
3261 r#"{
3262 "value": 4,
3263 "propName": true,
3264}"#,
3265 );
3266 }
3267
3268 #[test]
3269 fn remove_array_elements() {
3270 fn run_test(index: usize, json: &str, expected: &str) {
3271 let cst = build_cst(json);
3272 let root_value = cst.value().unwrap();
3273 let root_array = root_value.as_array().unwrap();
3274 let element = root_array.elements().get(index).unwrap().clone();
3275 element.remove();
3276 assert_eq!(cst.to_string(), expected);
3277 }
3278
3279 run_test(
3280 0,
3281 r#"[
3282 1,
3283]"#,
3284 r#"[]"#,
3285 );
3286 run_test(
3287 0,
3288 r#"[
3289 1,
3290 2,
3291]"#,
3292 r#"[
3293 2,
3294]"#,
3295 );
3296 run_test(
3297 0,
3298 r#"[
3299 1,
3300 2,
3301]"#,
3302 r#"[
3303 2,
3304]"#,
3305 );
3306
3307 run_test(
3308 1,
3309 r#"[
3310 1, // other comment
3311 2, // trailing comment
3312]"#,
3313 r#"[
3314 1, // other comment
3315]"#,
3316 );
3317
3318 run_test(
3319 1,
3320 r#"[
3321 1, // comment
3322 2
3323]"#,
3324 r#"[
3325 1 // comment
3326]"#,
3327 );
3328
3329 run_test(1, r#"[1, 2]"#, r#"[1]"#);
3330 run_test(1, r#"[ 1, 2 /* test */ ]"#, r#"[ 1 ]"#);
3331 run_test(1, r#"[1, /* test */ 2]"#, r#"[1]"#);
3332 run_test(
3333 1,
3334 r#"[1 /* a */, /* b */ 2 /* c */, /* d */ true]"#,
3335 r#"[1 /* a */, /* d */ true]"#,
3336 );
3337 }
3338
3339 #[test]
3340 fn insert_array_element() {
3341 #[track_caller]
3342 fn run_test(index: usize, value: CstInputValue, json: &str, expected: &str) {
3343 let cst = build_cst(json);
3344 let root_value = cst.value().unwrap();
3345 let root_array = root_value.as_array().unwrap();
3346 root_array.insert(index, value);
3347 assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3348 }
3349
3350 run_test(0, json!([1]), r#"[]"#, r#"[[1]]"#);
3351 run_test(0, json!([1, true, false, {}]), r#"[]"#, r#"[[1, true, false, {}]]"#);
3352 run_test(0, json!(10), r#"[]"#, r#"[10]"#);
3353 run_test(0, json!(10), r#"[1]"#, r#"[10, 1]"#);
3354 run_test(1, json!(10), r#"[1]"#, r#"[1, 10]"#);
3355 run_test(
3356 0,
3357 json!(10),
3358 r#"[
3359 1
3360]"#,
3361 r#"[
3362 10,
3363 1
3364]"#,
3365 );
3366 run_test(
3367 0,
3368 json!(10),
3369 r#"[
3370 /* test */ 1
3371]"#,
3372 r#"[
3373 10,
3374 /* test */ 1
3375]"#,
3376 );
3377
3378 run_test(
3379 0,
3380 json!({
3381 "value": 1,
3382 }),
3383 r#"[]"#,
3384 r#"[
3385 {
3386 "value": 1
3387 }
3388]"#,
3389 );
3390
3391 run_test(
3393 0,
3394 json!({
3395 "value": 1,
3396 }),
3397 r#"[
3398 // comment
3399]"#,
3400 r#"[
3401 // comment
3402 {
3403 "value": 1
3404 }
3405]"#,
3406 );
3407
3408 run_test(
3410 0,
3411 json!({
3412 "value": 1,
3413 }),
3414 r#"[
3415
3416]"#,
3417 r#"[
3418 {
3419 "value": 1
3420 }
3421]"#,
3422 );
3423 }
3424
3425 #[test]
3426 fn insert_array_element_trailing_commas() {
3427 let cst = build_cst(
3428 r#"{
3429 "prop": [
3430 1,
3431 2,
3432 ]
3433}"#,
3434 );
3435 cst
3436 .object_value_or_create()
3437 .unwrap()
3438 .array_value("prop")
3439 .unwrap()
3440 .append(json!(3));
3441 assert_eq!(
3442 cst.to_string(),
3443 r#"{
3444 "prop": [
3445 1,
3446 2,
3447 3,
3448 ]
3449}"#
3450 );
3451 }
3452
3453 #[test]
3454 fn remove_comment() {
3455 fn run_test(json: &str, expected: &str) {
3456 let cst = build_cst(json);
3457 let root_value = cst.value().unwrap();
3458 let root_obj = root_value.as_object().unwrap();
3459 root_obj
3460 .children()
3461 .into_iter()
3462 .filter_map(|c| c.as_comment())
3463 .next()
3464 .unwrap()
3465 .remove();
3466 assert_eq!(cst.to_string(), expected);
3467 }
3468
3469 run_test(
3470 r#"{
3471 "value": 5,
3472 // comment
3473 "value2": "hello",
3474 value3: true
3475}"#,
3476 r#"{
3477 "value": 5,
3478 "value2": "hello",
3479 value3: true
3480}"#,
3481 );
3482
3483 run_test(
3484 r#"{
3485 "value": 5, // comment
3486 "value2": "hello",
3487 value3: true
3488}"#,
3489 r#"{
3490 "value": 5,
3491 "value2": "hello",
3492 value3: true
3493}"#,
3494 );
3495 }
3496
3497 #[test]
3498 fn object_value_or_create() {
3499 {
3501 let cst = build_cst(r#"{ "value": 1 }"#);
3502 let obj = cst.object_value_or_create().unwrap();
3503 assert!(obj.get("value").is_some());
3504 }
3505 {
3507 let cst = build_cst(r#""#);
3508 cst.object_value_or_create().unwrap();
3509 assert_eq!(cst.to_string(), "{}\n");
3510 }
3511 {
3513 let cst = build_cst("// Copyright something");
3514 cst.object_value_or_create().unwrap();
3515 assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3516 }
3517 {
3519 let cst = build_cst("// Copyright something\n");
3520 cst.object_value_or_create().unwrap();
3521 assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3522 }
3523 }
3524
3525 #[test]
3526 fn array_ensure_multiline() {
3527 {
3529 let cst = build_cst(r#"[]"#);
3530 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3531 assert_eq!(cst.to_string(), "[\n]");
3532 }
3533 {
3535 let cst = build_cst(r#"[ ]"#);
3536 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3537 assert_eq!(cst.to_string(), "[\n]");
3538 }
3539 {
3541 let cst = build_cst(r#"[ /* test */ ]"#);
3542 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3543 assert_eq!(cst.to_string(), "[\n /* test */\n]");
3544 }
3545 {
3547 let cst = build_cst(r#"[ 1, 2, /* test */ 3 ]"#);
3548 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3549 assert_eq!(
3550 cst.to_string(),
3551 r#"[
3552 1,
3553 2,
3554 /* test */ 3
3555]"#
3556 );
3557 }
3558 {
3560 let cst = build_cst(
3561 r#"{
3562 "prop": {
3563 "value": [ 1, 2, /* test */ 3 ]
3564 }
3565}"#,
3566 );
3567 cst
3568 .value()
3569 .unwrap()
3570 .as_object()
3571 .unwrap()
3572 .get("prop")
3573 .unwrap()
3574 .value()
3575 .unwrap()
3576 .as_object()
3577 .unwrap()
3578 .get("value")
3579 .unwrap()
3580 .value()
3581 .unwrap()
3582 .as_array()
3583 .unwrap()
3584 .ensure_multiline();
3585 assert_eq!(
3586 cst.to_string(),
3587 r#"{
3588 "prop": {
3589 "value": [
3590 1,
3591 2,
3592 /* test */ 3
3593 ]
3594 }
3595}"#
3596 );
3597 }
3598 {
3600 let cst = build_cst("[ 1, 2, /* test */ 3 ]\r\n");
3601 cst.value().unwrap().as_array().unwrap().ensure_multiline();
3602 assert_eq!(cst.to_string(), "[\r\n 1,\r\n 2,\r\n /* test */ 3\r\n]\r\n");
3603 }
3604 }
3605
3606 #[test]
3607 fn object_ensure_multiline() {
3608 {
3610 let cst = build_cst(r#"{}"#);
3611 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3612 assert_eq!(cst.to_string(), "{\n}");
3613 }
3614 {
3616 let cst = build_cst(r#"{ }"#);
3617 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3618 assert_eq!(cst.to_string(), "{\n}");
3619 }
3620 {
3622 let cst = build_cst(r#"{ /* test */ }"#);
3623 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3624 assert_eq!(cst.to_string(), "{\n /* test */\n}");
3625 }
3626 {
3628 let cst = build_cst(r#"{ prop: 1, prop2: 2, /* test */ prop3: 3 }"#);
3629 cst.value().unwrap().as_object().unwrap().ensure_multiline();
3630 assert_eq!(
3631 cst.to_string(),
3632 r#"{
3633 prop: 1,
3634 prop2: 2,
3635 /* test */ prop3: 3
3636}"#
3637 );
3638 }
3639 {
3641 let cst = build_cst(
3642 r#"{
3643 "prop": {
3644 "value": { prop: 1, prop2: 2, /* test */ prop3: 3 }
3645 }
3646}"#,
3647 );
3648 cst
3649 .value()
3650 .unwrap()
3651 .as_object()
3652 .unwrap()
3653 .get("prop")
3654 .unwrap()
3655 .value()
3656 .unwrap()
3657 .as_object()
3658 .unwrap()
3659 .get("value")
3660 .unwrap()
3661 .value()
3662 .unwrap()
3663 .as_object()
3664 .unwrap()
3665 .ensure_multiline();
3666 assert_eq!(
3667 cst.to_string(),
3668 r#"{
3669 "prop": {
3670 "value": {
3671 prop: 1,
3672 prop2: 2,
3673 /* test */ prop3: 3
3674 }
3675 }
3676}"#
3677 );
3678 }
3679 }
3680
3681 #[test]
3682 fn sets_trailing_commas() {
3683 fn run_test(input: &str, mode: crate::cst::TrailingCommaMode, expected: &str) {
3684 let cst = build_cst(input);
3685 let root_value = cst.value().unwrap();
3686 let root_obj = root_value.as_object().unwrap();
3687 root_obj.set_trailing_commas(mode);
3688 assert_eq!(cst.to_string(), expected);
3689 }
3690
3691 run_test(
3693 r#"{
3694}"#,
3695 TrailingCommaMode::Never,
3696 r#"{
3697}"#,
3698 );
3699 run_test(
3700 r#"{
3701 // test
3702}"#,
3703 TrailingCommaMode::IfMultiline,
3704 r#"{
3705 // test
3706}"#,
3707 );
3708
3709 run_test(r#"{"a": 1}"#, TrailingCommaMode::Never, r#"{"a": 1}"#);
3711 run_test(r#"{"a": 1}"#, TrailingCommaMode::IfMultiline, r#"{"a": 1}"#);
3712 run_test(
3714 r#"{
3715 "a": 1,
3716 "b": 2,
3717 "c": [1, 2, 3],
3718 "d": [
3719 1
3720 ]
3721}"#,
3722 TrailingCommaMode::IfMultiline,
3723 r#"{
3724 "a": 1,
3725 "b": 2,
3726 "c": [1, 2, 3],
3727 "d": [
3728 1,
3729 ],
3730}"#,
3731 );
3732 run_test(
3733 r#"{
3734"a": 1,
3735"b": 2,
3736}"#,
3737 TrailingCommaMode::Never,
3738 r#"{
3739"a": 1,
3740"b": 2
3741}"#,
3742 );
3743 }
3744
3745 #[test]
3746 fn or_create_methods() {
3747 let cst = build_cst("");
3748 let obj = cst.object_value_or_create().unwrap();
3749 assert_eq!(cst.to_string(), "{}\n");
3750 assert!(cst.array_value_or_create().is_none());
3751 assert_eq!(obj.object_value_or_create("prop").unwrap().to_string(), "{}");
3752 assert!(obj.array_value_or_create("prop").is_none());
3753 assert_eq!(obj.array_value_or_create("prop2").unwrap().to_string(), "[]");
3754 assert_eq!(
3755 cst.to_string(),
3756 r#"{
3757 "prop": {},
3758 "prop2": []
3759}
3760"#
3761 );
3762 }
3763
3764 #[test]
3765 fn or_set_methods() {
3766 let cst = build_cst("");
3767 let array = cst.array_value_or_set();
3768 assert_eq!(array.to_string(), "[]");
3769 assert_eq!(cst.to_string(), "[]\n");
3770 let object = cst.object_value_or_set();
3771 assert_eq!(object.to_string(), "{}");
3772 assert_eq!(cst.to_string(), "{}\n");
3773 let value = object.array_value_or_set("test");
3774 assert_eq!(value.to_string(), "[]");
3775 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3776 let value = object.object_value_or_set("test");
3777 assert_eq!(value.to_string(), "{}");
3778 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3779 let value = object.array_value_or_set("test");
3780 assert_eq!(value.to_string(), "[]");
3781 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3782 value.append(json!(1));
3783 assert_eq!(cst.to_string(), "{\n \"test\": [1]\n}\n");
3784 let value = object.object_value_or_set("test");
3785 assert_eq!(value.to_string(), "{}");
3786 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3787 let test_prop = object.get("test").unwrap();
3788 assert!(test_prop.object_value().is_some());
3789 assert!(test_prop.array_value().is_none());
3790 test_prop.array_value_or_set();
3791 assert_eq!(cst.to_string(), "{\n \"test\": []\n}\n");
3792 assert!(test_prop.object_value().is_none());
3793 assert!(test_prop.array_value().is_some());
3794 test_prop.object_value_or_set();
3795 assert_eq!(cst.to_string(), "{\n \"test\": {}\n}\n");
3796 }
3797
3798 #[test]
3799 fn expression_properties_and_values() {
3800 #[track_caller]
3801 fn run_test(value: CstInputValue, expected: &str) {
3802 let cst = build_cst("");
3803 cst.set_value(value);
3804 assert_eq!(cst.to_string(), format!("{}\n", expected));
3805 }
3806
3807 run_test(json!(1), "1");
3808 run_test(json!("test"), "\"test\"");
3809 {
3810 let text = "test";
3811 run_test(json!(text), "\"test\"");
3812 }
3813 {
3814 let num = 1;
3815 run_test(json!(num), "1");
3816 }
3817 {
3818 let vec = vec![1, 2, 3];
3819 run_test(json!(vec), "[1, 2, 3]");
3820 }
3821 {
3822 let vec = vec![1, 2, 3];
3823 run_test(
3824 json!({
3825 "value": vec,
3826 }),
3827 r#"{
3828 "value": [1, 2, 3]
3829}"#,
3830 );
3831 }
3832 run_test(
3833 json!({
3834 notQuoted: 1,
3835 "quoted": 2,
3836 }),
3837 r#"{
3838 "notQuoted": 1,
3839 "quoted": 2
3840}"#,
3841 )
3842 }
3843
3844 #[test]
3845 fn property_index() {
3846 let cst = build_cst("{ \"prop\": 1, \"prop2\": 2, \"prop3\": 3 }");
3847 let object = cst.object_value().unwrap();
3848 for (i, prop) in object.properties().into_iter().enumerate() {
3849 assert_eq!(prop.property_index(), i);
3850 }
3851 }
3852
3853 #[test]
3854 fn element_index() {
3855 let cst = build_cst("[1, 2, true ,false]");
3856 let array = cst.array_value().unwrap();
3857 for (i, prop) in array.elements().into_iter().enumerate() {
3858 assert_eq!(prop.element_index().unwrap(), i);
3859 }
3860 }
3861
3862 #[track_caller]
3863 fn build_cst(text: &str) -> CstRootNode {
3864 CstRootNode::parse(text, &crate::ParseOptions::default()).unwrap()
3865 }
3866}