jsonc_parser/cst/
mod.rs

1//! CST for manipulating JSONC.
2//!
3//! # Example
4//!
5//! ```
6//! use jsonc_parser::cst::CstRootNode;
7//! use jsonc_parser::ParseOptions;
8//! use jsonc_parser::json;
9//!
10//! let json_text = r#"{
11//!   // comment
12//!   "data": 123
13//! }"#;
14//!
15//! let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
16//! let root_obj = root.object_value_or_set();
17//!
18//! root_obj.get("data").unwrap().set_value(json!({
19//!   "nested": true
20//! }));
21//! root_obj.append("new_key", json!([456, 789, false]));
22//!
23//! assert_eq!(root.to_string(), r#"{
24//!   // comment
25//!   "data": {
26//!     "nested": true
27//!   },
28//!   "new_key": [456, 789, false]
29//! }"#);
30//! ```
31//!
32
33use 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    /// Gets the root node.
54    ///
55    /// Returns `None` if this node has become disconnected from
56    /// the tree by being removed.
57    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    /// Parent of the node.
72    ///
73    /// Returns `None` if this node has become disconnected from
74    /// the tree by being removed.
75    pub fn parent(&self) -> Option<CstContainerNode> {
76      self.parent_info().map(|p| p.parent.as_container_node())
77    }
78
79    /// An iterator of ancestors of this node.
80    pub fn ancestors(&self) -> impl Iterator<Item = CstContainerNode> {
81      AncestorIterator::new(self.clone().into())
82    }
83
84    /// Current child index of the node within the children of the
85    /// parent node.
86    pub fn child_index(&self) -> usize {
87      self.parent_info().map(|p| p.child_index).unwrap_or(0)
88    }
89
90    /// Node that comes before this one that shares the same parent.
91    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    /// Siblings coming before this node. This does not
103    /// include cousins.
104    pub fn previous_siblings(&self) -> impl Iterator<Item = CstNode> {
105      PreviousSiblingIterator::new(self.clone().into())
106    }
107
108    /// Node that comes after this one that shares the same parent.
109    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    /// Siblings coming after this node. This does not
118    /// include cousins.
119    pub fn next_siblings(&self) -> impl Iterator<Item = CstNode> {
120      NextSiblingIterator::new(self.clone().into())
121    }
122
123    /// Returns the indentation text if it can be determined.
124    pub fn indent_text(&self) -> Option<String> {
125      indent_text(&self.clone().into())
126    }
127
128    /// Gets the trailing comma token of the node, if it exists.
129    pub fn trailing_comma(&self) -> Option<CstToken> {
130      find_trailing_comma(&self.clone().into())
131    }
132
133    /// Infers if the node or appropriate ancestor uses trailing commas.
134    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          // skip over
159        }
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      /// Children of the current node.
205      pub fn children(&self) -> Vec<CstNode> {
206        self.0.borrow().value.clone()
207      }
208
209      /// Children of the current node excluding comments, whitespace, newlines, and tokens.
210      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      /// Gets the child at the specified index.
222      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          // update the index of the remaining children
234          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    // It's much better to panic here to let the developer know an ancestor has been
277    // lost due to being dropped because if we did something like returning None then
278    // it might create strange bugs that are hard to track down.
279    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/// All the different kinds of nodes that can appear in the CST.
310#[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  /// Gets if this node is comments, whitespace, newlines, or a non-literal token (ex. brace, colon).
321  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  /// Comments that become before this one on the same line.
337  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  /// Comments that come after this one on the same line.
348  ///
349  /// Only returns owned trailing comments on the same line and not if owned by the next node.
350  pub fn trailing_comments_same_line(&self) -> impl Iterator<Item = CstComment> {
351    // ensure the trailing comments are owned
352    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  /// If this node is a newline.
372  pub fn is_newline(&self) -> bool {
373    matches!(self, CstNode::Leaf(CstLeafNode::Newline(_)))
374  }
375
376  /// If this node is a comma.
377  pub fn is_comma(&self) -> bool {
378    match self {
379      CstNode::Leaf(CstLeafNode::Token(t)) => t.value() == ',',
380      _ => false,
381    }
382  }
383
384  /// If this node is a comment.
385  pub fn is_comment(&self) -> bool {
386    matches!(self, CstNode::Leaf(CstLeafNode::Comment(_)))
387  }
388
389  /// If this node is a token.
390  pub fn is_token(&self) -> bool {
391    matches!(self, CstNode::Leaf(CstLeafNode::Token(_)))
392  }
393
394  /// If this node is whitespace.
395  pub fn is_whitespace(&self) -> bool {
396    matches!(self, CstNode::Leaf(CstLeafNode::Whitespace(_)))
397  }
398
399  /// Token char of the node if it's a token.
400  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  /// Children of this node.
408  pub fn children(&self) -> Vec<CstNode> {
409    match self {
410      CstNode::Container(n) => n.children(),
411      CstNode::Leaf(_) => Vec::new(),
412    }
413  }
414
415  /// Children of the current node excluding comments, whitespace, newlines, and tokens.
416  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  /// Child at the specified index.
424  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  /// Gets the array element index of this node if its parent is an array.
432  ///
433  /// Returns `None` when the parent is not an array.
434  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  /// Node if it's the root node.
441  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  /// Node if it's an object.
449  pub fn as_object(&self) -> Option<CstObject> {
450    match self {
451      // doesn't return a reference so this is easier to use
452      CstNode::Container(CstContainerNode::Object(node)) => Some(node.clone()),
453      _ => None,
454    }
455  }
456
457  /// Node if it's an array.
458  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  /// Node if it's an object property.
466  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  /// Node if it's a boolean literal.
474  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  /// Node if it's a null keyword.
482  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  /// Node if it's a number literal.
490  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  /// Node if it's a string literal.
498  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  /// Node if it's a word literal.
506  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  /// Node if it's a token.
514  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  /// Node if it's a newline.
522  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  /// Node if it's whitespace.
530  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  /// Node if it's a comment.
538  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  /// Removes the node from the JSON.
546  ///
547  /// Note: Removing certain nodes may cause syntax errors.
548  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  /// Removes the node from the tree without making adjustments to any siblings.
570  fn remove_raw(self) {
571    let Some(parent_info) = self.parent_info() else {
572      return; // already removed
573    };
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/// Enumeration of a node that has children.
597#[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  /// If this is the root node.
610  pub fn is_root(&self) -> bool {
611    matches!(self, CstContainerNode::Root(_))
612  }
613
614  /// If this is an array node.
615  pub fn is_array(&self) -> bool {
616    matches!(self, CstContainerNode::Array(_))
617  }
618
619  /// If this is an object node.
620  pub fn is_object(&self) -> bool {
621    matches!(self, CstContainerNode::Object(_))
622  }
623
624  /// If this is an object property node.
625  pub fn is_object_prop(&self) -> bool {
626    matches!(self, CstContainerNode::ObjectProp(_))
627  }
628
629  /// Node if it's the root node.
630  pub fn as_root(&self) -> Option<CstRootNode> {
631    match self {
632      CstContainerNode::Root(node) => Some(node.clone()),
633      _ => None,
634    }
635  }
636
637  /// Node if it's an array.
638  pub fn as_array(&self) -> Option<CstArray> {
639    match self {
640      CstContainerNode::Array(node) => Some(node.clone()),
641      _ => None,
642    }
643  }
644
645  /// Node if it's an object.
646  pub fn as_object(&self) -> Option<CstObject> {
647    match self {
648      CstContainerNode::Object(node) => Some(node.clone()),
649      _ => None,
650    }
651  }
652
653  /// Node if it's an object property.
654  pub fn as_object_prop(&self) -> Option<CstObjectProp> {
655    match self {
656      CstContainerNode::ObjectProp(node) => Some(node.clone()),
657      _ => None,
658    }
659  }
660
661  /// Children of the node.
662  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  /// Children of the current node excluding comments, whitespace, newlines, and tokens.
672  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  /// Child at the specified index.
682  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  /// Removes the node from the JSON.
701  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    // update the child index of all the nodes
762    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/// Enumeration of a node that has no children.
909#[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  /// Removes the node from the JSON.
927  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/// Mode to use for trailing commas.
993#[derive(Default, Debug, Clone, Copy)]
994pub enum TrailingCommaMode {
995  /// Never use trailing commas.
996  #[default]
997  Never,
998  /// Use trailing commas when the object is on multiple lines.
999  IfMultiline,
1000}
1001
1002type CstRootNodeInner = RefCell<CstChildrenInner>;
1003
1004/// Root node in the file.
1005///
1006/// The root node contains one value, whitespace, and comments.
1007#[derive(Debug, Clone)]
1008pub struct CstRootNode(Rc<CstRootNodeInner>);
1009
1010impl_container_methods!(CstRootNode, Root);
1011
1012impl CstRootNode {
1013  /// Parses the text into a CST.
1014  ///
1015  /// WARNING: You MUST not drop the root node for the duration of using the CST
1016  /// or a panic could occur in certain scenarios. This is because the CST uses weak
1017  /// references for ancestors and if the root node is dropped then the weak reference
1018  /// will be lost and the CST will panic to prevent bugs when a descendant node
1019  /// attempts to access an ancestor that was dropped.
1020  ///
1021  /// ```
1022  /// use jsonc_parser::cst::CstRootNode;
1023  /// use jsonc_parser::ParseOptions;
1024  /// use jsonc_parser::json;
1025  ///
1026  /// let json_text = r#"{
1027  ///   // comment
1028  ///   "data": 123
1029  /// }"#;
1030  ///
1031  /// let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
1032  /// let root_obj = root.object_value_or_set();
1033  ///
1034  /// root_obj.get("data").unwrap().set_value(json!({
1035  ///   "nested": true
1036  /// }));
1037  /// root_obj.append("new_key", json!([456, 789, false]));
1038  ///
1039  /// assert_eq!(root.to_string(), r#"{
1040  ///   // comment
1041  ///   "data": {
1042  ///     "nested": true
1043  ///   },
1044  ///   "new_key": [456, 789, false]
1045  /// }"#);
1046  /// ```
1047  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  /// Computes the single indentation text of the file.
1067  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  /// Newline kind used within the JSON text.
1088  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  /// Gets the root value found in the file.
1103  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  /// Sets potentially replacing the root value found in the JSON document.
1113  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        // insert a newline if the last node before is a comment
1133        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        // insert a trailing newline
1137        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  /// Gets the root value if its an object.
1151  pub fn object_value(&self) -> Option<CstObject> {
1152    self.value()?.as_object()
1153  }
1154
1155  /// Gets or creates the root value as an object, returns `Some` if successful
1156  /// or `None` if the root value already exists and is not an object.
1157  ///
1158  /// Note: Use `.object_value_or_set()` to overwrite the root value when
1159  /// it's not an object.
1160  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  /// Gets the root value if it's an object or sets the root value as an object.
1172  ///
1173  /// Note: Use `.object_value_or_create()` to not overwrite the root value
1174  /// when it's not an object.
1175  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  /// Gets the value if its an array.
1186  pub fn array_value(&self) -> Option<CstArray> {
1187    self.value()?.as_array()
1188  }
1189
1190  /// Gets or creates the root value as an object, returns `Some` if successful
1191  /// or `None` if the root value already exists and is not an object.
1192  ///
1193  /// Note: Use `.array_value_or_set()` to overwrite the root value when
1194  /// it's not an array.
1195  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  /// Gets the root value if it's an object or sets the root value as an object.
1207  ///
1208  /// Note: Use `.array_value_or_create()` to not overwrite the root value
1209  /// when it's not an object.
1210  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  /// Ensures this object's values use trailing commas.
1221  ///
1222  /// Note: This does not cause future values to use trailing commas.
1223  /// That will always be determined based on whether the file uses
1224  /// trailing commas or not, so it's probably best to do this last.
1225  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  /// Clears all the children from the root node making it empty.
1241  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/// Text surrounded in double quotes (ex. `"my string"`).
1259#[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  /// Sets the raw value of the string INCLUDING SURROUNDING QUOTES.
1274  pub fn set_raw_value(&self, value: String) {
1275    self.0.borrow_mut().value = value;
1276  }
1277
1278  /// Gets the raw unescaped value including quotes.
1279  pub fn raw_value(&self) -> String {
1280    self.0.borrow().value.clone()
1281  }
1282
1283  /// Gets the decoded string value.
1284  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  /// Replaces this node with a new value.
1292  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1293    replace_with(self.into(), InsertValue::Value(replacement))
1294  }
1295
1296  /// Removes the node from the JSON.
1297  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/// Property key that is missing quotes (ex. `prop: 4`).
1309#[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  /// Sets the raw value of the word literal.
1320  pub fn set_raw_value(&self, value: String) {
1321    self.0.borrow_mut().value = value;
1322  }
1323
1324  /// Replaces this node with a new value.
1325  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1326    replace_with(self.into(), InsertValue::Value(replacement))
1327  }
1328
1329  /// Removes the node from the JSON.
1330  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  /// Sets the raw string value of the number literal.
1352  pub fn set_raw_value(&self, value: String) {
1353    self.0.borrow_mut().value = value;
1354  }
1355
1356  /// Replaces this node with a new value.
1357  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1358    replace_with(self.into(), InsertValue::Value(replacement))
1359  }
1360
1361  /// Removes the node from the JSON.
1362  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/// Boolean (`true` or `false`).
1374#[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  /// Gets the value of the boolean literal.
1385  pub fn value(&self) -> bool {
1386    self.0.borrow().value
1387  }
1388
1389  /// Sets the value of the boolean literal.
1390  pub fn set_value(&self, value: bool) {
1391    self.0.borrow_mut().value = value;
1392  }
1393
1394  /// Replaces this node with a new value.
1395  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1396    replace_with(self.into(), InsertValue::Value(replacement))
1397  }
1398
1399  /// Removes the node from the JSON.
1400  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/// Null keyword (`null`).
1416#[derive(Debug, Clone)]
1417pub struct CstNullKeyword(Rc<RefCell<CstValueInner<()>>>);
1418
1419impl CstNullKeyword {
1420  fn new() -> Self {
1421    Self(CstValueInner::new(()))
1422  }
1423
1424  /// Replaces this node with a new value.
1425  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1426    replace_with(self.into(), InsertValue::Value(replacement))
1427  }
1428
1429  /// Removes the node from the JSON.
1430  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/// Object literal that may contain properties (ex. `{}`, `{ "prop": 4 }`).
1446#[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  /// Array property by name.
1466  ///
1467  /// Returns `None` if the property doesn't exist or is not an array.
1468  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  /// Ensures a property exists with an array value returning the array.
1476  ///
1477  /// Returns `None` if the property value exists, but is not an array.
1478  ///
1479  /// Note: Use `.array_value_or_set(..)` to overwrite an existing
1480  /// non-array property value.
1481  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  /// Ensures a property exists with an array value returning the array.
1495  ///
1496  /// Note: Use `.array_value_or_create(..)` to not overwrite an existing
1497  /// non-array property value.
1498  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  /// Object property by name.
1526  ///
1527  /// Returns `None` if the property doesn't exist or is not an object.
1528  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  /// Ensures a property exists with an object value returning the object.
1536  ///
1537  /// Returns `None` if the property value exists, but is not an object.
1538  ///
1539  /// Note: Use `.object_value_or_set(..)` to overwrite an existing
1540  /// non-array property value.
1541  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  /// Ensures a property exists with an object value returning the object.
1555  ///
1556  /// Note: Use `.object_value_or_create(..)` to not overwrite an existing
1557  /// non-object property value.
1558  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  /// Property by name.
1586  ///
1587  /// Returns `None` if the property doesn't exist.
1588  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  /// Properties of the object.
1606  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  /// Appends a property to the object.
1620  ///
1621  /// Returns the inserted object property.
1622  pub fn append(&self, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1623    self.insert_or_append(None, prop_name, value)
1624  }
1625
1626  /// Inserts a property at the specified index.
1627  ///
1628  /// Returns the inserted object property.
1629  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  /// Replaces this node with a new value.
1646  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1647    replace_with(self.into(), InsertValue::Value(replacement))
1648  }
1649
1650  /// Ensures this object and all its descendants use trailing commas.
1651  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  /// Ensures the object spans multiple lines.
1660  pub fn ensure_multiline(&self) {
1661    ensure_multiline(&self.clone().into());
1662  }
1663
1664  /// Removes the node from the JSON.
1665  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/// Property in an object (ex. `"prop": 5`).
1682#[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  /// Name of the object property.
1695  ///
1696  /// Returns `None` if the name doesn't exist.
1697  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          // someone may have manipulated this object such that this is no longer there
1704        }
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  /// Value of the object property.
1744  ///
1745  /// Returns `None` if the value doesn't exist.
1746  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    // first, skip over the colon token
1753    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    // now find the value
1762    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            // ignore
1772          }
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  /// Gets the value if its an object.
1785  pub fn object_value(&self) -> Option<CstObject> {
1786    self.value()?.as_object()
1787  }
1788
1789  /// Gets the value if it's an object or sets the value as an object.
1790  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  /// Gets the value if its an array.
1801  pub fn array_value(&self) -> Option<CstArray> {
1802    self.value()?.as_array()
1803  }
1804
1805  /// Gets the value if it's an object or sets the value as an object.
1806  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  /// Sibling object property coming before this one.
1817  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  /// Sibling object property coming after this one.
1827  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  /// Replaces this node with a new value.
1837  pub fn replace_with(self, key: &str, replacement: CstInputValue) -> Option<CstNode> {
1838    replace_with(self.into(), InsertValue::Property(key, replacement))
1839  }
1840
1841  /// Removes the node from the JSON.
1842  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/// An object property name that may or may not be in quotes (ex. `"prop"` in `"prop": 5`).
1857#[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  /// Object property name if it's a string literal.
1868  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  /// Object property name if it's a word literal (no quotes).
1876  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  /// Decoded value of the string.
1884  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/// Represents an array that may contain elements (ex. `[]`, `[1, 2, 3]`).
1911#[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  /// Elements of the array.
1931  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  /// Appends an element to the end of the array.
1955  ///
1956  /// Returns the appended node.
1957  pub fn append(&self, value: CstInputValue) -> CstNode {
1958    self.insert_or_append(None, value)
1959  }
1960
1961  /// Inserts an element at the specified index.
1962  ///
1963  /// Returns the inserted node.
1964  pub fn insert(&self, index: usize, value: CstInputValue) -> CstNode {
1965    self.insert_or_append(Some(index), value)
1966  }
1967
1968  /// Ensures the array spans multiple lines.
1969  pub fn ensure_multiline(&self) {
1970    ensure_multiline(&self.clone().into());
1971  }
1972
1973  /// Ensures this array and all its descendants use trailing commas.
1974  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  /// Replaces this node with a new value.
1988  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1989    replace_with(self.into(), InsertValue::Value(replacement))
1990  }
1991
1992  /// Removes the node from the JSON.
1993  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/// Insigificant token found in the file (ex. colon, comma, brace, etc.).
2008#[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  /// Sets the char value of the token.
2019  pub fn set_value(&self, value: char) {
2020    self.0.borrow_mut().value = value;
2021  }
2022
2023  /// Char value of the token.
2024  pub fn value(&self) -> char {
2025    self.0.borrow().value
2026  }
2027
2028  /// Removes the node from the JSON.
2029  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/// Blank space excluding newlines.
2041#[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  /// Sets the whitespace value.
2052  pub fn set_value(&self, value: String) {
2053    self.0.borrow_mut().value = value;
2054  }
2055
2056  /// Whitespace value of the node.
2057  pub fn value(&self) -> String {
2058    self.0.borrow().value.clone()
2059  }
2060
2061  /// Removes the node from the JSON.
2062  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/// Kind of newline.
2074#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
2075pub enum CstNewlineKind {
2076  #[default]
2077  LineFeed,
2078  CarriageReturnLineFeed,
2079}
2080
2081/// Newline character (Lf or crlf).
2082#[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  /// Whether this is a line feed (LF) or carriage return line feed (CRLF).
2093  pub fn kind(&self) -> CstNewlineKind {
2094    self.0.borrow().value
2095  }
2096
2097  /// Sets the newline kind.
2098  pub fn set_kind(&self, kind: CstNewlineKind) {
2099    self.0.borrow_mut().value = kind;
2100  }
2101
2102  /// Removes the node from the JSON.
2103  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)] // better to be explicit
2112      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  /// Whether this is a line comment.
2129  pub fn is_line_comment(&self) -> bool {
2130    self.0.borrow().value.starts_with("//")
2131  }
2132
2133  /// Sets the raw value of the comment.
2134  ///
2135  /// This SHOULD include `//` or be surrounded in `/* ... */` or
2136  /// else you'll be inserting a syntax error.
2137  pub fn set_raw_value(&self, value: String) {
2138    self.0.borrow_mut().value = value;
2139  }
2140
2141  /// Raw value of the comment including `//` or `/* ... */`.
2142  pub fn raw_value(&self) -> String {
2143    self.0.borrow().value.clone()
2144  }
2145
2146  /// Removes the node from the JSON.
2147  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(); // move past the \n
2321      } 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            // keep going
2364          }
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  // remove up to the trailing comma
2396  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  // remove up to the newline
2414  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 // default to false
2524}
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    // handle last element
2691    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    // handle children
2703    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    // try to find the first newline
2719    for child in children.by_ref() {
2720      if child.is_whitespace() {
2721        // keep searching
2722      } else if child.is_newline() {
2723        break; // found
2724      } else {
2725        return; // stop, no leading blank lines
2726      }
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; // should never happen because this should only be called for array and object
2749  }
2750
2751  // remove blank lines from the front and back
2752  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  // insert a newline at the start of every part
2772  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      // insert a newline
2781      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      // current node
2788      index += 1;
2789
2790      // consume the next tokens until the next comma
2791      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  // insert the last newline
2811  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  // try to discover the single indent level by looking at the root node's children
2882  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  // assume two space indentation
2894  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  // pre-emptively store the next ancestor in case
2903  // the currently returned sibling is removed
2904  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  // pre-emptively store the next sibling in case
2927  // the currently returned sibling is removed
2928  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  // pre-emptively store the previous sibling in case
2951  // the currently returned sibling is removed
2952  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      // this is fine... people doing stupid things
3149      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    // inserting before first prop
3182    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    // inserting before first prop with leading comment
3196    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    // inserting after last prop with trailing comment
3212    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    // maintain trailing comma
3230    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    // insert when is on a single line
3244    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    // insert when is on a single line with trailing comma
3256    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    // only comment
3392    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    // blank line
3409    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    // existing
3500    {
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    // empty file
3506    {
3507      let cst = build_cst(r#""#);
3508      cst.object_value_or_create().unwrap();
3509      assert_eq!(cst.to_string(), "{}\n");
3510    }
3511    // comment
3512    {
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    // comment and newline
3518    {
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    // empty
3528    {
3529      let cst = build_cst(r#"[]"#);
3530      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3531      assert_eq!(cst.to_string(), "[\n]");
3532    }
3533    // whitespace only
3534    {
3535      let cst = build_cst(r#"[   ]"#);
3536      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3537      assert_eq!(cst.to_string(), "[\n]");
3538    }
3539    // comments only
3540    {
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    // elements
3546    {
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    // elements deep
3559    {
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    // \r\n newlines
3599    {
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    // empty
3609    {
3610      let cst = build_cst(r#"{}"#);
3611      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3612      assert_eq!(cst.to_string(), "{\n}");
3613    }
3614    // whitespace only
3615    {
3616      let cst = build_cst(r#"{   }"#);
3617      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3618      assert_eq!(cst.to_string(), "{\n}");
3619    }
3620    // comments only
3621    {
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    // elements
3627    {
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    // elements deep
3640    {
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    // empty object
3692    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    // single-line object
3710    run_test(r#"{"a": 1}"#, TrailingCommaMode::Never, r#"{"a": 1}"#);
3711    run_test(r#"{"a": 1}"#, TrailingCommaMode::IfMultiline, r#"{"a": 1}"#);
3712    // multiline object
3713    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}