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::ParseOptions;
42use crate::ast;
43use crate::errors::ParseError;
44use crate::parse_to_ast;
45use crate::string::ParseStringErrorKind;
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  /// Converts a CST node to a `serde_json::Value`.
581  ///
582  /// This method extracts the actual value from the CST node, ignoring
583  /// trivia (comments, whitespace, etc.).
584  ///
585  /// Returns `None` if the node is trivia or cannot be converted to a value.
586  ///
587  /// # Example
588  ///
589  /// ```
590  /// use jsonc_parser::cst::CstRootNode;
591  /// use jsonc_parser::ParseOptions;
592  ///
593  /// let json_text = r#"{ "test": 5 } // comment"#;
594  /// let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
595  ///
596  /// if let Some(value_node) = root.value() {
597  ///   let json_value = value_node.to_serde_value().unwrap();
598  ///   println!("{}", json_value);
599  /// }
600  /// ```
601  #[cfg(feature = "serde")]
602  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
603    match self {
604      CstNode::Container(container) => container.to_serde_value(),
605      CstNode::Leaf(leaf) => leaf.to_serde_value(),
606    }
607  }
608}
609
610impl Display for CstNode {
611  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
612    match self {
613      CstNode::Container(node) => node.fmt(f),
614      CstNode::Leaf(node) => node.fmt(f),
615    }
616  }
617}
618
619#[derive(Default, Debug, Clone)]
620struct StyleInfo {
621  pub uses_trailing_commas: bool,
622  pub newline_kind: CstNewlineKind,
623}
624
625/// Enumeration of a node that has children.
626#[derive(Debug, Clone)]
627pub enum CstContainerNode {
628  Root(CstRootNode),
629  Array(CstArray),
630  Object(CstObject),
631  ObjectProp(CstObjectProp),
632}
633
634impl CstContainerNode {
635  add_parent_info_methods!();
636  add_root_node_method!();
637
638  /// If this is the root node.
639  pub fn is_root(&self) -> bool {
640    matches!(self, CstContainerNode::Root(_))
641  }
642
643  /// If this is an array node.
644  pub fn is_array(&self) -> bool {
645    matches!(self, CstContainerNode::Array(_))
646  }
647
648  /// If this is an object node.
649  pub fn is_object(&self) -> bool {
650    matches!(self, CstContainerNode::Object(_))
651  }
652
653  /// If this is an object property node.
654  pub fn is_object_prop(&self) -> bool {
655    matches!(self, CstContainerNode::ObjectProp(_))
656  }
657
658  /// Node if it's the root node.
659  pub fn as_root(&self) -> Option<CstRootNode> {
660    match self {
661      CstContainerNode::Root(node) => Some(node.clone()),
662      _ => None,
663    }
664  }
665
666  /// Node if it's an array.
667  pub fn as_array(&self) -> Option<CstArray> {
668    match self {
669      CstContainerNode::Array(node) => Some(node.clone()),
670      _ => None,
671    }
672  }
673
674  /// Node if it's an object.
675  pub fn as_object(&self) -> Option<CstObject> {
676    match self {
677      CstContainerNode::Object(node) => Some(node.clone()),
678      _ => None,
679    }
680  }
681
682  /// Node if it's an object property.
683  pub fn as_object_prop(&self) -> Option<CstObjectProp> {
684    match self {
685      CstContainerNode::ObjectProp(node) => Some(node.clone()),
686      _ => None,
687    }
688  }
689
690  /// Children of the node.
691  pub fn children(&self) -> Vec<CstNode> {
692    match self {
693      CstContainerNode::Root(n) => n.children(),
694      CstContainerNode::Object(n) => n.children(),
695      CstContainerNode::ObjectProp(n) => n.children(),
696      CstContainerNode::Array(n) => n.children(),
697    }
698  }
699
700  /// Children of the current node excluding comments, whitespace, newlines, and tokens.
701  pub fn children_exclude_trivia_and_tokens(&self) -> Vec<CstNode> {
702    match self {
703      CstContainerNode::Root(n) => n.children_exclude_trivia_and_tokens(),
704      CstContainerNode::Object(n) => n.children_exclude_trivia_and_tokens(),
705      CstContainerNode::ObjectProp(n) => n.children_exclude_trivia_and_tokens(),
706      CstContainerNode::Array(n) => n.children_exclude_trivia_and_tokens(),
707    }
708  }
709
710  /// Child at the specified index.
711  pub fn child_at_index(&self, index: usize) -> Option<CstNode> {
712    match self {
713      CstContainerNode::Root(node) => node.child_at_index(index),
714      CstContainerNode::Object(node) => node.child_at_index(index),
715      CstContainerNode::ObjectProp(node) => node.child_at_index(index),
716      CstContainerNode::Array(node) => node.child_at_index(index),
717    }
718  }
719
720  fn remove_child_set_no_parent(&self, index: usize) {
721    match self {
722      CstContainerNode::Root(n) => n.remove_child_set_no_parent(index),
723      CstContainerNode::Object(n) => n.remove_child_set_no_parent(index),
724      CstContainerNode::ObjectProp(n) => n.remove_child_set_no_parent(index),
725      CstContainerNode::Array(n) => n.remove_child_set_no_parent(index),
726    }
727  }
728
729  /// Removes the node from the JSON.
730  pub fn remove(self) {
731    match self {
732      CstContainerNode::Root(n) => n.clear_children(),
733      CstContainerNode::Object(n) => n.remove(),
734      CstContainerNode::ObjectProp(n) => n.remove(),
735      CstContainerNode::Array(n) => n.remove(),
736    }
737  }
738
739  fn parent_info(&self) -> Option<ParentInfo> {
740    match self {
741      CstContainerNode::Root(node) => node.parent_info(),
742      CstContainerNode::Object(node) => node.parent_info(),
743      CstContainerNode::ObjectProp(node) => node.parent_info(),
744      CstContainerNode::Array(node) => node.parent_info(),
745    }
746  }
747
748  fn set_parent(&self, parent: Option<ParentInfo>) {
749    match self {
750      CstContainerNode::Root(node) => node.set_parent(parent),
751      CstContainerNode::Object(node) => node.set_parent(parent),
752      CstContainerNode::ObjectProp(node) => node.set_parent(parent),
753      CstContainerNode::Array(node) => node.set_parent(parent),
754    }
755  }
756
757  #[inline(always)]
758  fn raw_append_child(&self, child: CstNode) {
759    self.raw_insert_child(None, child);
760  }
761
762  #[inline(always)]
763  fn raw_insert_child(&self, index: Option<&mut usize>, child: CstNode) {
764    self.raw_insert_children(index, vec![child]);
765  }
766
767  #[inline(always)]
768  fn raw_append_children(&self, children: Vec<CstNode>) {
769    self.raw_insert_children(None, children);
770  }
771
772  fn raw_insert_children(&self, index: Option<&mut usize>, children: Vec<CstNode>) {
773    if children.is_empty() {
774      return;
775    }
776
777    let weak_parent = WeakParent::from_container(self);
778    let mut container = match self {
779      CstContainerNode::Root(node) => node.0.borrow_mut(),
780      CstContainerNode::Object(node) => node.0.borrow_mut(),
781      CstContainerNode::ObjectProp(node) => node.0.borrow_mut(),
782      CstContainerNode::Array(node) => node.0.borrow_mut(),
783    };
784    let insert_index = index.as_ref().map(|i| **i).unwrap_or(container.value.len());
785    if let Some(i) = index {
786      *i += children.len();
787    }
788    container.value.splice(insert_index..insert_index, children);
789
790    // update the child index of all the nodes
791    for (i, child) in container.value.iter().enumerate().skip(insert_index) {
792      child.set_parent(Some(ParentInfo {
793        parent: weak_parent.clone(),
794        child_index: i,
795      }));
796    }
797  }
798
799  fn raw_insert_value_with_internal_indent(
800    &self,
801    insert_index: Option<&mut usize>,
802    value: InsertValue,
803    style_info: &StyleInfo,
804    indents: &Indents,
805  ) {
806    match value {
807      InsertValue::Value(value) => {
808        let is_multiline = value.force_multiline();
809        match value {
810          CstInputValue::Null => {
811            self.raw_insert_child(insert_index, CstLeafNode::NullKeyword(CstNullKeyword::new()).into());
812          }
813          CstInputValue::Bool(value) => {
814            self.raw_insert_child(insert_index, CstLeafNode::BooleanLit(CstBooleanLit::new(value)).into());
815          }
816          CstInputValue::Number(value) => {
817            self.raw_insert_child(insert_index, CstLeafNode::NumberLit(CstNumberLit::new(value)).into());
818          }
819          CstInputValue::String(value) => {
820            self.raw_insert_child(
821              insert_index,
822              CstLeafNode::StringLit(CstStringLit::new_escaped(&value)).into(),
823            );
824          }
825          CstInputValue::Array(elements) => {
826            let array_node: CstContainerNode = CstArray::new_no_tokens().into();
827            self.raw_insert_child(insert_index, array_node.clone().into());
828
829            array_node.raw_append_child(CstToken::new('[').into());
830            if !elements.is_empty() {
831              let indents = indents.indent();
832              let mut elements = elements.into_iter().peekable();
833              while let Some(value) = elements.next() {
834                if is_multiline {
835                  array_node.raw_insert_children(
836                    None,
837                    vec![
838                      CstNewline::new(style_info.newline_kind).into(),
839                      CstWhitespace::new(indents.current_indent.clone()).into(),
840                    ],
841                  );
842                }
843
844                array_node.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, &indents);
845
846                if style_info.uses_trailing_commas && is_multiline || elements.peek().is_some() {
847                  if is_multiline {
848                    array_node.raw_append_child(CstToken::new(',').into());
849                  } else {
850                    array_node.raw_insert_children(
851                      None,
852                      vec![CstToken::new(',').into(), CstWhitespace::new(" ".to_string()).into()],
853                    );
854                  }
855                }
856              }
857            }
858
859            if is_multiline {
860              array_node.raw_append_children(vec![
861                CstNewline::new(style_info.newline_kind).into(),
862                CstWhitespace::new(indents.current_indent.clone()).into(),
863              ]);
864            }
865
866            array_node.raw_append_child(CstToken::new(']').into());
867          }
868          CstInputValue::Object(properties) => {
869            let object_node: CstContainerNode = CstObject::new_no_tokens().into();
870            self.raw_insert_child(insert_index, object_node.clone().into());
871
872            object_node.raw_append_child(CstToken::new('{').into());
873
874            if !properties.is_empty() {
875              {
876                let indents = indents.indent();
877                let mut properties = properties.into_iter().peekable();
878                while let Some((prop_name, value)) = properties.next() {
879                  object_node.raw_append_child(CstNewline::new(style_info.newline_kind).into());
880                  object_node.raw_append_child(CstWhitespace::new(indents.current_indent.clone()).into());
881                  object_node.raw_insert_value_with_internal_indent(
882                    None,
883                    InsertValue::Property(&prop_name, value),
884                    style_info,
885                    &indents,
886                  );
887                  if style_info.uses_trailing_commas || properties.peek().is_some() {
888                    object_node.raw_append_child(CstToken::new(',').into());
889                  }
890                }
891              }
892
893              object_node.raw_append_children(vec![
894                CstNewline::new(style_info.newline_kind).into(),
895                CstWhitespace::new(indents.current_indent.clone()).into(),
896              ]);
897            }
898
899            object_node.raw_append_child(CstToken::new('}').into());
900          }
901        }
902      }
903      InsertValue::Property(prop_name, value) => {
904        let prop = CstContainerNode::ObjectProp(CstObjectProp::new());
905        self.raw_insert_child(insert_index, prop.clone().into());
906        prop.raw_insert_children(
907          None,
908          vec![
909            CstStringLit::new_escaped(prop_name).into(),
910            CstToken::new(':').into(),
911            CstWhitespace::new(" ".to_string()).into(),
912          ],
913        );
914        prop.raw_insert_value_with_internal_indent(None, InsertValue::Value(value), style_info, indents);
915      }
916    }
917  }
918
919  /// Converts a CST container node to a `serde_json::Value`.
920  ///
921  /// Returns `None` if the node cannot be converted to a value.
922  #[cfg(feature = "serde")]
923  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
924    match self {
925      CstContainerNode::Root(node) => node.to_serde_value(),
926      CstContainerNode::Array(node) => node.to_serde_value(),
927      CstContainerNode::Object(node) => node.to_serde_value(),
928      CstContainerNode::ObjectProp(node) => node.to_serde_value(),
929    }
930  }
931}
932
933impl From<CstContainerNode> for CstNode {
934  fn from(value: CstContainerNode) -> Self {
935    CstNode::Container(value)
936  }
937}
938
939impl Display for CstContainerNode {
940  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
941    match self {
942      CstContainerNode::Root(node) => node.fmt(f),
943      CstContainerNode::Object(node) => node.fmt(f),
944      CstContainerNode::ObjectProp(node) => node.fmt(f),
945      CstContainerNode::Array(node) => node.fmt(f),
946    }
947  }
948}
949
950/// Enumeration of a node that has no children.
951#[derive(Debug, Clone)]
952pub enum CstLeafNode {
953  BooleanLit(CstBooleanLit),
954  NullKeyword(CstNullKeyword),
955  NumberLit(CstNumberLit),
956  StringLit(CstStringLit),
957  WordLit(CstWordLit),
958  Token(CstToken),
959  Whitespace(CstWhitespace),
960  Newline(CstNewline),
961  Comment(CstComment),
962}
963
964impl CstLeafNode {
965  add_parent_info_methods!();
966  add_root_node_method!();
967
968  /// Removes the node from the JSON.
969  pub fn remove(self) {
970    match self {
971      CstLeafNode::BooleanLit(n) => n.remove(),
972      CstLeafNode::NullKeyword(n) => n.remove(),
973      CstLeafNode::NumberLit(n) => n.remove(),
974      CstLeafNode::StringLit(n) => n.remove(),
975      CstLeafNode::WordLit(n) => n.remove(),
976      CstLeafNode::Token(n) => n.remove(),
977      CstLeafNode::Whitespace(n) => n.remove(),
978      CstLeafNode::Newline(n) => n.remove(),
979      CstLeafNode::Comment(n) => n.remove(),
980    }
981  }
982
983  fn parent_info(&self) -> Option<ParentInfo> {
984    match self {
985      CstLeafNode::BooleanLit(node) => node.parent_info(),
986      CstLeafNode::NullKeyword(node) => node.parent_info(),
987      CstLeafNode::NumberLit(node) => node.parent_info(),
988      CstLeafNode::StringLit(node) => node.parent_info(),
989      CstLeafNode::WordLit(node) => node.parent_info(),
990      CstLeafNode::Token(node) => node.parent_info(),
991      CstLeafNode::Whitespace(node) => node.parent_info(),
992      CstLeafNode::Newline(node) => node.parent_info(),
993      CstLeafNode::Comment(node) => node.parent_info(),
994    }
995  }
996
997  fn set_parent(&self, parent: Option<ParentInfo>) {
998    match self {
999      CstLeafNode::BooleanLit(node) => node.set_parent(parent),
1000      CstLeafNode::NullKeyword(node) => node.set_parent(parent),
1001      CstLeafNode::NumberLit(node) => node.set_parent(parent),
1002      CstLeafNode::StringLit(node) => node.set_parent(parent),
1003      CstLeafNode::WordLit(node) => node.set_parent(parent),
1004      CstLeafNode::Token(node) => node.set_parent(parent),
1005      CstLeafNode::Whitespace(node) => node.set_parent(parent),
1006      CstLeafNode::Newline(node) => node.set_parent(parent),
1007      CstLeafNode::Comment(node) => node.set_parent(parent),
1008    }
1009  }
1010
1011  /// Converts a CST leaf node to a `serde_json::Value`.
1012  ///
1013  /// Returns `None` if the node is trivia or cannot be converted to a value.
1014  #[cfg(feature = "serde")]
1015  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1016    match self {
1017      CstLeafNode::BooleanLit(node) => node.to_serde_value(),
1018      CstLeafNode::NullKeyword(node) => node.to_serde_value(),
1019      CstLeafNode::NumberLit(node) => node.to_serde_value(),
1020      CstLeafNode::StringLit(node) => node.to_serde_value(),
1021      CstLeafNode::WordLit(_)
1022      | CstLeafNode::Token(_)
1023      | CstLeafNode::Whitespace(_)
1024      | CstLeafNode::Newline(_)
1025      | CstLeafNode::Comment(_) => None,
1026    }
1027  }
1028}
1029
1030impl Display for CstLeafNode {
1031  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1032    match self {
1033      CstLeafNode::BooleanLit(node) => node.fmt(f),
1034      CstLeafNode::NullKeyword(node) => node.fmt(f),
1035      CstLeafNode::NumberLit(node) => node.fmt(f),
1036      CstLeafNode::StringLit(node) => node.fmt(f),
1037      CstLeafNode::WordLit(node) => node.fmt(f),
1038      CstLeafNode::Token(node) => node.fmt(f),
1039      CstLeafNode::Whitespace(node) => node.fmt(f),
1040      CstLeafNode::Newline(node) => node.fmt(f),
1041      CstLeafNode::Comment(node) => node.fmt(f),
1042    }
1043  }
1044}
1045
1046impl From<CstLeafNode> for CstNode {
1047  fn from(value: CstLeafNode) -> Self {
1048    CstNode::Leaf(value)
1049  }
1050}
1051
1052/// Mode to use for trailing commas.
1053#[derive(Default, Debug, Clone, Copy)]
1054pub enum TrailingCommaMode {
1055  /// Never use trailing commas.
1056  #[default]
1057  Never,
1058  /// Use trailing commas when the object is on multiple lines.
1059  IfMultiline,
1060}
1061
1062type CstRootNodeInner = RefCell<CstChildrenInner>;
1063
1064/// Root node in the file.
1065///
1066/// The root node contains one value, whitespace, and comments.
1067#[derive(Debug, Clone)]
1068pub struct CstRootNode(Rc<CstRootNodeInner>);
1069
1070impl_container_methods!(CstRootNode, Root);
1071
1072impl CstRootNode {
1073  /// Parses the text into a CST.
1074  ///
1075  /// WARNING: You MUST not drop the root node for the duration of using the CST
1076  /// or a panic could occur in certain scenarios. This is because the CST uses weak
1077  /// references for ancestors and if the root node is dropped then the weak reference
1078  /// will be lost and the CST will panic to prevent bugs when a descendant node
1079  /// attempts to access an ancestor that was dropped.
1080  ///
1081  /// ```
1082  /// use jsonc_parser::cst::CstRootNode;
1083  /// use jsonc_parser::ParseOptions;
1084  /// use jsonc_parser::json;
1085  ///
1086  /// let json_text = r#"{
1087  ///   // comment
1088  ///   "data": 123
1089  /// }"#;
1090  ///
1091  /// let root = CstRootNode::parse(json_text, &ParseOptions::default()).unwrap();
1092  /// let root_obj = root.object_value_or_set();
1093  ///
1094  /// root_obj.get("data").unwrap().set_value(json!({
1095  ///   "nested": true
1096  /// }));
1097  /// root_obj.append("new_key", json!([456, 789, false]));
1098  ///
1099  /// assert_eq!(root.to_string(), r#"{
1100  ///   // comment
1101  ///   "data": {
1102  ///     "nested": true
1103  ///   },
1104  ///   "new_key": [456, 789, false]
1105  /// }"#);
1106  /// ```
1107  pub fn parse(text: &str, parse_options: &ParseOptions) -> Result<Self, ParseError> {
1108    let parse_result = parse_to_ast(
1109      text,
1110      &crate::CollectOptions {
1111        comments: crate::CommentCollectionStrategy::AsTokens,
1112        tokens: true,
1113      },
1114      parse_options,
1115    )?;
1116
1117    Ok(
1118      CstBuilder {
1119        text,
1120        tokens: parse_result.tokens.unwrap().into_iter().collect(),
1121      }
1122      .build(parse_result.value),
1123    )
1124  }
1125
1126  /// Computes the single indentation text of the file.
1127  pub fn single_indent_text(&self) -> Option<String> {
1128    let root_value = self.value()?;
1129    let first_non_trivia_child = root_value.children_exclude_trivia_and_tokens().first()?.clone();
1130    let mut last_whitespace = None;
1131    for previous_trivia in first_non_trivia_child.previous_siblings() {
1132      match previous_trivia {
1133        CstNode::Leaf(CstLeafNode::Whitespace(whitespace)) => {
1134          last_whitespace = Some(whitespace);
1135        }
1136        CstNode::Leaf(CstLeafNode::Newline(_)) => {
1137          return last_whitespace.map(|whitespace| whitespace.0.borrow().value.clone());
1138        }
1139        _ => {
1140          last_whitespace = None;
1141        }
1142      }
1143    }
1144    None
1145  }
1146
1147  /// Newline kind used within the JSON text.
1148  pub fn newline_kind(&self) -> CstNewlineKind {
1149    let mut current_children: VecDeque<CstContainerNode> = VecDeque::from([self.clone().into()]);
1150    while let Some(child) = current_children.pop_front() {
1151      for child in child.children() {
1152        if let CstNode::Container(child) = child {
1153          current_children.push_back(child);
1154        } else if let CstNode::Leaf(CstLeafNode::Newline(node)) = child {
1155          return node.kind();
1156        }
1157      }
1158    }
1159    CstNewlineKind::LineFeed
1160  }
1161
1162  /// Gets the root value found in the file.
1163  pub fn value(&self) -> Option<CstNode> {
1164    for child in &self.0.borrow().value {
1165      if !child.is_trivia() {
1166        return Some(child.clone());
1167      }
1168    }
1169    None
1170  }
1171
1172  /// Sets potentially replacing the root value found in the JSON document.
1173  pub fn set_value(&self, root_value: CstInputValue) {
1174    let container: CstContainerNode = self.clone().into();
1175    let style_info = StyleInfo {
1176      newline_kind: self.newline_kind(),
1177      uses_trailing_commas: uses_trailing_commas(self.clone().into()),
1178    };
1179    let indents = compute_indents(&self.clone().into());
1180    let mut insert_index = if let Some(root_value) = self.value() {
1181      let index = root_value.child_index();
1182      root_value.remove_raw();
1183      index
1184    } else {
1185      let children = self.children();
1186      let mut index = match children.last() {
1187        Some(CstNode::Leaf(CstLeafNode::Newline(_))) => children.len() - 1,
1188        _ => children.len(),
1189      };
1190      let previous_node = if index == 0 { None } else { children.get(index - 1) };
1191      if let Some(CstNode::Leaf(CstLeafNode::Comment(_))) = previous_node {
1192        // insert a newline if the last node before is a comment
1193        container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1194      }
1195      if self.child_at_index(index).is_none() {
1196        // insert a trailing newline
1197        container.raw_insert_child(Some(&mut index), CstNewline::new(style_info.newline_kind).into());
1198        index -= 1;
1199      }
1200      index
1201    };
1202    container.raw_insert_value_with_internal_indent(
1203      Some(&mut insert_index),
1204      InsertValue::Value(root_value),
1205      &style_info,
1206      &indents,
1207    );
1208  }
1209
1210  /// Gets the root value if its an object.
1211  pub fn object_value(&self) -> Option<CstObject> {
1212    self.value()?.as_object()
1213  }
1214
1215  /// Gets or creates the root value as an object, returns `Some` if successful
1216  /// or `None` if the root value already exists and is not an object.
1217  ///
1218  /// Note: Use `.object_value_or_set()` to overwrite the root value when
1219  /// it's not an object.
1220  pub fn object_value_or_create(&self) -> Option<CstObject> {
1221    match self.value() {
1222      Some(CstNode::Container(CstContainerNode::Object(node))) => Some(node),
1223      Some(_) => None,
1224      None => {
1225        self.set_value(CstInputValue::Object(Vec::new()));
1226        self.object_value()
1227      }
1228    }
1229  }
1230
1231  /// Gets the root value if it's an object or sets the root value as an object.
1232  ///
1233  /// Note: Use `.object_value_or_create()` to not overwrite the root value
1234  /// when it's not an object.
1235  pub fn object_value_or_set(&self) -> CstObject {
1236    match self.value() {
1237      Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1238      _ => {
1239        self.set_value(CstInputValue::Object(Vec::new()));
1240        self.object_value().unwrap()
1241      }
1242    }
1243  }
1244
1245  /// Gets the value if its an array.
1246  pub fn array_value(&self) -> Option<CstArray> {
1247    self.value()?.as_array()
1248  }
1249
1250  /// Gets or creates the root value as an object, returns `Some` if successful
1251  /// or `None` if the root value already exists and is not an object.
1252  ///
1253  /// Note: Use `.array_value_or_set()` to overwrite the root value when
1254  /// it's not an array.
1255  pub fn array_value_or_create(&self) -> Option<CstArray> {
1256    match self.value() {
1257      Some(CstNode::Container(CstContainerNode::Array(node))) => Some(node),
1258      Some(_) => None,
1259      None => {
1260        self.set_value(CstInputValue::Array(Vec::new()));
1261        self.array_value()
1262      }
1263    }
1264  }
1265
1266  /// Gets the root value if it's an object or sets the root value as an object.
1267  ///
1268  /// Note: Use `.array_value_or_create()` to not overwrite the root value
1269  /// when it's not an object.
1270  pub fn array_value_or_set(&self) -> CstArray {
1271    match self.value() {
1272      Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1273      _ => {
1274        self.set_value(CstInputValue::Array(Vec::new()));
1275        self.array_value().unwrap()
1276      }
1277    }
1278  }
1279
1280  /// Ensures this object's values use trailing commas.
1281  ///
1282  /// Note: This does not cause future values to use trailing commas.
1283  /// That will always be determined based on whether the file uses
1284  /// trailing commas or not, so it's probably best to do this last.
1285  pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1286    let Some(value) = self.value() else {
1287      return;
1288    };
1289
1290    match value {
1291      CstNode::Container(container) => match container {
1292        CstContainerNode::Array(n) => n.set_trailing_commas(mode),
1293        CstContainerNode::Object(n) => n.set_trailing_commas(mode),
1294        _ => {}
1295      },
1296      CstNode::Leaf(_) => {}
1297    }
1298  }
1299
1300  /// Clears all the children from the root node making it empty.
1301  pub fn clear_children(&self) {
1302    let children = std::mem::take(&mut self.0.borrow_mut().value);
1303    for child in children {
1304      child.set_parent(None);
1305    }
1306  }
1307
1308  /// Converts the root CST node to a `serde_json::Value`.
1309  ///
1310  /// Returns `None` if the root has no value node.
1311  #[cfg(feature = "serde")]
1312  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1313    self.value()?.to_serde_value()
1314  }
1315}
1316
1317impl Display for CstRootNode {
1318  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1319    for child in &self.0.borrow().value {
1320      write!(f, "{}", child)?;
1321    }
1322    Ok(())
1323  }
1324}
1325
1326/// Text surrounded in double quotes (ex. `"my string"`).
1327#[derive(Debug, Clone)]
1328pub struct CstStringLit(Rc<RefCell<CstValueInner<String>>>);
1329
1330impl_leaf_methods!(CstStringLit, StringLit);
1331
1332impl CstStringLit {
1333  fn new(value: String) -> Self {
1334    Self(CstValueInner::new(value))
1335  }
1336
1337  fn new_escaped(value: &str) -> Self {
1338    Self::new(format!("\"{}\"", value.replace("\"", "\\\"")))
1339  }
1340
1341  /// Sets the raw value of the string INCLUDING SURROUNDING QUOTES.
1342  pub fn set_raw_value(&self, value: String) {
1343    self.0.borrow_mut().value = value;
1344  }
1345
1346  /// Gets the raw unescaped value including quotes.
1347  pub fn raw_value(&self) -> String {
1348    self.0.borrow().value.clone()
1349  }
1350
1351  /// Gets the decoded string value.
1352  pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
1353    let inner = self.0.borrow();
1354    crate::string::parse_string(&inner.value)
1355      .map(|value| value.into_owned())
1356      .map_err(|err| err.kind)
1357  }
1358
1359  /// Replaces this node with a new value.
1360  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1361    replace_with(self.into(), InsertValue::Value(replacement))
1362  }
1363
1364  /// Removes the node from the JSON.
1365  pub fn remove(self) {
1366    remove_comma_separated(self.into())
1367  }
1368
1369  /// Converts a CST string literal to a `serde_json::Value`.
1370  #[cfg(feature = "serde")]
1371  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1372    self.decoded_value().ok().map(serde_json::Value::String)
1373  }
1374}
1375
1376impl Display for CstStringLit {
1377  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1378    write!(f, "{}", self.0.borrow().value)
1379  }
1380}
1381
1382/// Property key that is missing quotes (ex. `prop: 4`).
1383#[derive(Debug, Clone)]
1384pub struct CstWordLit(Rc<RefCell<CstValueInner<String>>>);
1385
1386impl_leaf_methods!(CstWordLit, WordLit);
1387
1388impl CstWordLit {
1389  fn new(value: String) -> Self {
1390    Self(CstValueInner::new(value))
1391  }
1392
1393  /// Sets the raw value of the word literal.
1394  pub fn set_raw_value(&self, value: String) {
1395    self.0.borrow_mut().value = value;
1396  }
1397
1398  /// Replaces this node with a new value.
1399  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1400    replace_with(self.into(), InsertValue::Value(replacement))
1401  }
1402
1403  /// Removes the node from the JSON.
1404  pub fn remove(self) {
1405    remove_comma_separated(self.into())
1406  }
1407}
1408
1409impl Display for CstWordLit {
1410  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1411    write!(f, "{}", self.0.borrow().value)
1412  }
1413}
1414
1415#[derive(Debug, Clone)]
1416pub struct CstNumberLit(Rc<RefCell<CstValueInner<String>>>);
1417
1418impl_leaf_methods!(CstNumberLit, NumberLit);
1419
1420impl CstNumberLit {
1421  fn new(value: String) -> Self {
1422    Self(CstValueInner::new(value))
1423  }
1424
1425  /// Sets the raw string value of the number literal.
1426  pub fn set_raw_value(&self, value: String) {
1427    self.0.borrow_mut().value = value;
1428  }
1429
1430  /// Replaces this node with a new value.
1431  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1432    replace_with(self.into(), InsertValue::Value(replacement))
1433  }
1434
1435  /// Removes the node from the JSON.
1436  pub fn remove(self) {
1437    remove_comma_separated(self.into())
1438  }
1439
1440  /// Converts a CST number literal to a `serde_json::Value`.
1441  #[cfg(feature = "serde")]
1442  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1443    use std::str::FromStr;
1444    let raw = self.0.borrow().value.clone();
1445
1446    // check if this is a hexadecimal literal (0x or 0X prefix)
1447    let num_str = raw.trim_start_matches(['-', '+']);
1448    if num_str.len() > 2 && (num_str.starts_with("0x") || num_str.starts_with("0X")) {
1449      // parse hexadecimal and convert to decimal
1450      let hex_part = &num_str[2..];
1451      match i64::from_str_radix(hex_part, 16) {
1452        Ok(decimal_value) => {
1453          let final_value = if raw.starts_with('-') {
1454            -decimal_value
1455          } else {
1456            decimal_value
1457          };
1458          Some(serde_json::Value::Number(serde_json::Number::from(final_value)))
1459        }
1460        Err(_) => Some(serde_json::Value::String(raw)),
1461      }
1462    } else {
1463      // standard decimal number - strip leading + if present (serde_json doesn't accept it)
1464      let num_for_parsing = raw.trim_start_matches('+');
1465      match serde_json::Number::from_str(num_for_parsing) {
1466        Ok(number) => Some(serde_json::Value::Number(number)),
1467        // if the number is invalid, return it as a string (same behavior as AST conversion)
1468        Err(_) => Some(serde_json::Value::String(raw)),
1469      }
1470    }
1471  }
1472}
1473
1474impl Display for CstNumberLit {
1475  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1476    write!(f, "{}", self.0.borrow().value)
1477  }
1478}
1479
1480/// Boolean (`true` or `false`).
1481#[derive(Debug, Clone)]
1482pub struct CstBooleanLit(Rc<RefCell<CstValueInner<bool>>>);
1483
1484impl_leaf_methods!(CstBooleanLit, BooleanLit);
1485
1486impl CstBooleanLit {
1487  fn new(value: bool) -> Self {
1488    Self(CstValueInner::new(value))
1489  }
1490
1491  /// Gets the value of the boolean literal.
1492  pub fn value(&self) -> bool {
1493    self.0.borrow().value
1494  }
1495
1496  /// Sets the value of the boolean literal.
1497  pub fn set_value(&self, value: bool) {
1498    self.0.borrow_mut().value = value;
1499  }
1500
1501  /// Replaces this node with a new value.
1502  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1503    replace_with(self.into(), InsertValue::Value(replacement))
1504  }
1505
1506  /// Removes the node from the JSON.
1507  pub fn remove(self) {
1508    remove_comma_separated(self.into())
1509  }
1510
1511  /// Converts a CST boolean literal to a `serde_json::Value`.
1512  #[cfg(feature = "serde")]
1513  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1514    Some(serde_json::Value::Bool(self.value()))
1515  }
1516}
1517
1518impl Display for CstBooleanLit {
1519  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1520    if self.0.borrow().value {
1521      write!(f, "true")
1522    } else {
1523      write!(f, "false")
1524    }
1525  }
1526}
1527
1528/// Null keyword (`null`).
1529#[derive(Debug, Clone)]
1530pub struct CstNullKeyword(Rc<RefCell<CstValueInner<()>>>);
1531
1532impl CstNullKeyword {
1533  fn new() -> Self {
1534    Self(CstValueInner::new(()))
1535  }
1536
1537  /// Replaces this node with a new value.
1538  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1539    replace_with(self.into(), InsertValue::Value(replacement))
1540  }
1541
1542  /// Removes the node from the JSON.
1543  pub fn remove(self) {
1544    remove_comma_separated(self.into())
1545  }
1546
1547  /// Converts a CST null keyword to a `serde_json::Value`.
1548  #[cfg(feature = "serde")]
1549  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1550    Some(serde_json::Value::Null)
1551  }
1552}
1553
1554impl_leaf_methods!(CstNullKeyword, NullKeyword);
1555
1556impl Display for CstNullKeyword {
1557  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1558    write!(f, "null")
1559  }
1560}
1561
1562type CstObjectInner = RefCell<CstChildrenInner>;
1563
1564/// Object literal that may contain properties (ex. `{}`, `{ "prop": 4 }`).
1565#[derive(Debug, Clone)]
1566pub struct CstObject(Rc<CstObjectInner>);
1567
1568impl_container_methods!(CstObject, Object);
1569
1570impl CstObject {
1571  add_root_node_method!();
1572
1573  fn new_no_tokens() -> Self {
1574    Self(CstValueInner::new(Vec::new()))
1575  }
1576
1577  fn new_with_tokens() -> Self {
1578    let object = CstObject::new_no_tokens();
1579    let container: CstContainerNode = object.clone().into();
1580    container.raw_append_children(vec![CstToken::new('{').into(), CstToken::new('}').into()]);
1581    object
1582  }
1583
1584  /// Array property by name.
1585  ///
1586  /// Returns `None` if the property doesn't exist or is not an array.
1587  pub fn array_value(&self, name: &str) -> Option<CstArray> {
1588    match self.get(name)?.value()? {
1589      CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1590      _ => None,
1591    }
1592  }
1593
1594  /// Ensures a property exists with an array value returning the array.
1595  ///
1596  /// Returns `None` if the property value exists, but is not an array.
1597  ///
1598  /// Note: Use `.array_value_or_set(..)` to overwrite an existing
1599  /// non-array property value.
1600  pub fn array_value_or_create(&self, name: &str) -> Option<CstArray> {
1601    match self.get(name) {
1602      Some(prop) => match prop.value()? {
1603        CstNode::Container(CstContainerNode::Array(node)) => Some(node),
1604        _ => None,
1605      },
1606      None => {
1607        self.append(name, CstInputValue::Array(Vec::new()));
1608        self.array_value(name)
1609      }
1610    }
1611  }
1612
1613  /// Ensures a property exists with an array value returning the array.
1614  ///
1615  /// Note: Use `.array_value_or_create(..)` to not overwrite an existing
1616  /// non-array property value.
1617  pub fn array_value_or_set(&self, name: &str) -> CstArray {
1618    match self.get(name) {
1619      Some(prop) => match prop.value() {
1620        Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1621        Some(node) => {
1622          let mut index = node.child_index();
1623          node.remove_raw();
1624          let container: CstContainerNode = prop.clone().into();
1625          let array = CstArray::new_with_tokens();
1626          container.raw_insert_child(Some(&mut index), array.clone().into());
1627          array
1628        }
1629        _ => {
1630          let mut index = prop.children().len();
1631          let container: CstContainerNode = prop.clone().into();
1632          let array = CstArray::new_with_tokens();
1633          container.raw_insert_child(Some(&mut index), array.clone().into());
1634          array
1635        }
1636      },
1637      None => {
1638        self.append(name, CstInputValue::Array(Vec::new()));
1639        self.array_value(name).unwrap()
1640      }
1641    }
1642  }
1643
1644  /// Object property by name.
1645  ///
1646  /// Returns `None` if the property doesn't exist or is not an object.
1647  pub fn object_value(&self, name: &str) -> Option<CstObject> {
1648    match self.get(name)?.value()? {
1649      CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1650      _ => None,
1651    }
1652  }
1653
1654  /// Ensures a property exists with an object value returning the object.
1655  ///
1656  /// Returns `None` if the property value exists, but is not an object.
1657  ///
1658  /// Note: Use `.object_value_or_set(..)` to overwrite an existing
1659  /// non-array property value.
1660  pub fn object_value_or_create(&self, name: &str) -> Option<CstObject> {
1661    match self.get(name) {
1662      Some(prop) => match prop.value()? {
1663        CstNode::Container(CstContainerNode::Object(node)) => Some(node),
1664        _ => None,
1665      },
1666      None => {
1667        self.append(name, CstInputValue::Object(Vec::new()));
1668        self.object_value(name)
1669      }
1670    }
1671  }
1672
1673  /// Ensures a property exists with an object value returning the object.
1674  ///
1675  /// Note: Use `.object_value_or_create(..)` to not overwrite an existing
1676  /// non-object property value.
1677  pub fn object_value_or_set(&self, name: &str) -> CstObject {
1678    match self.get(name) {
1679      Some(prop) => match prop.value() {
1680        Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1681        Some(node) => {
1682          let mut index = node.child_index();
1683          node.remove_raw();
1684          let container: CstContainerNode = prop.clone().into();
1685          let object = CstObject::new_with_tokens();
1686          container.raw_insert_child(Some(&mut index), object.clone().into());
1687          object
1688        }
1689        _ => {
1690          let mut index = prop.children().len();
1691          let container: CstContainerNode = prop.clone().into();
1692          let object = CstObject::new_with_tokens();
1693          container.raw_insert_child(Some(&mut index), object.clone().into());
1694          object
1695        }
1696      },
1697      None => {
1698        self.append(name, CstInputValue::Object(Vec::new()));
1699        self.object_value(name).unwrap()
1700      }
1701    }
1702  }
1703
1704  /// Property by name.
1705  ///
1706  /// Returns `None` if the property doesn't exist.
1707  pub fn get(&self, name: &str) -> Option<CstObjectProp> {
1708    for child in &self.0.borrow().value {
1709      if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = child {
1710        let Some(prop_name) = prop.name() else {
1711          continue;
1712        };
1713        let Ok(prop_name_str) = prop_name.decoded_value() else {
1714          continue;
1715        };
1716        if prop_name_str == name {
1717          return Some(prop.clone());
1718        }
1719      }
1720    }
1721    None
1722  }
1723
1724  /// Properties of the object.
1725  pub fn properties(&self) -> Vec<CstObjectProp> {
1726    self
1727      .0
1728      .borrow()
1729      .value
1730      .iter()
1731      .filter_map(|child| match child {
1732        CstNode::Container(CstContainerNode::ObjectProp(prop)) => Some(prop.clone()),
1733        _ => None,
1734      })
1735      .collect()
1736  }
1737
1738  /// Appends a property to the object.
1739  ///
1740  /// Returns the inserted object property.
1741  pub fn append(&self, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1742    self.insert_or_append(None, prop_name, value)
1743  }
1744
1745  /// Inserts a property at the specified index.
1746  ///
1747  /// Returns the inserted object property.
1748  pub fn insert(&self, index: usize, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1749    self.insert_or_append(Some(index), prop_name, value)
1750  }
1751
1752  fn insert_or_append(&self, index: Option<usize>, prop_name: &str, value: CstInputValue) -> CstObjectProp {
1753    self.ensure_multiline();
1754    insert_or_append_to_container(
1755      &CstContainerNode::Object(self.clone()),
1756      self.properties().into_iter().map(|c| c.into()).collect(),
1757      index,
1758      InsertValue::Property(prop_name, value),
1759    )
1760    .as_object_prop()
1761    .unwrap()
1762  }
1763
1764  /// Replaces this node with a new value.
1765  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
1766    replace_with(self.into(), InsertValue::Value(replacement))
1767  }
1768
1769  /// Ensures this object and all its descendants use trailing commas.
1770  pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
1771    set_trailing_commas(
1772      mode,
1773      &self.clone().into(),
1774      self.properties().into_iter().map(|c| c.into()),
1775    );
1776  }
1777
1778  /// Ensures the object spans multiple lines.
1779  pub fn ensure_multiline(&self) {
1780    ensure_multiline(&self.clone().into());
1781  }
1782
1783  /// Removes the node from the JSON.
1784  pub fn remove(self) {
1785    remove_comma_separated(self.into())
1786  }
1787
1788  /// Converts a CST object to a `serde_json::Value`.
1789  #[cfg(feature = "serde")]
1790  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1791    let mut map = serde_json::map::Map::new();
1792    for prop in self.properties() {
1793      if let (Some(name), Some(value)) = (prop.name_decoded(), prop.to_serde_value()) {
1794        map.insert(name, value);
1795      }
1796    }
1797    Some(serde_json::Value::Object(map))
1798  }
1799}
1800
1801impl Display for CstObject {
1802  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1803    for child in &self.0.borrow().value {
1804      write!(f, "{}", child)?;
1805    }
1806    Ok(())
1807  }
1808}
1809
1810type CstObjectPropInner = RefCell<CstChildrenInner>;
1811
1812/// Property in an object (ex. `"prop": 5`).
1813#[derive(Debug, Clone)]
1814pub struct CstObjectProp(Rc<CstObjectPropInner>);
1815
1816impl_container_methods!(CstObjectProp, ObjectProp);
1817
1818impl CstObjectProp {
1819  add_root_node_method!();
1820
1821  fn new() -> Self {
1822    Self(CstValueInner::new(Vec::new()))
1823  }
1824
1825  /// Name of the object property.
1826  ///
1827  /// Returns `None` if the name doesn't exist.
1828  pub fn name(&self) -> Option<ObjectPropName> {
1829    for child in &self.0.borrow().value {
1830      match child {
1831        CstNode::Leaf(CstLeafNode::StringLit(node)) => return Some(ObjectPropName::String(node.clone())),
1832        CstNode::Leaf(CstLeafNode::WordLit(node)) => return Some(ObjectPropName::Word(node.clone())),
1833        _ => {
1834          // someone may have manipulated this object such that this is no longer there
1835        }
1836      }
1837    }
1838    None
1839  }
1840
1841  pub fn property_index(&self) -> usize {
1842    let child_index = self.child_index();
1843    let Some(parent) = self.parent().and_then(|p| p.as_object()) else {
1844      return 0;
1845    };
1846    parent
1847      .properties()
1848      .iter()
1849      .position(|p| p.child_index() == child_index)
1850      .unwrap_or(0)
1851  }
1852
1853  pub fn set_value(&self, replacement: CstInputValue) {
1854    let maybe_value = self.value();
1855    let mut value_index = maybe_value
1856      .as_ref()
1857      .map(|v| v.child_index())
1858      .unwrap_or_else(|| self.children().len());
1859    let container: CstContainerNode = self.clone().into();
1860    let indents = compute_indents(&container.clone().into());
1861    let style_info = &StyleInfo {
1862      newline_kind: container.root_node().map(|v| v.newline_kind()).unwrap_or_default(),
1863      uses_trailing_commas: uses_trailing_commas(maybe_value.unwrap_or_else(|| container.clone().into())),
1864    };
1865    self.remove_child_set_no_parent(value_index);
1866    container.raw_insert_value_with_internal_indent(
1867      Some(&mut value_index),
1868      InsertValue::Value(replacement),
1869      style_info,
1870      &indents,
1871    );
1872  }
1873
1874  /// Value of the object property.
1875  ///
1876  /// Returns `None` if the value doesn't exist.
1877  pub fn value(&self) -> Option<CstNode> {
1878    let name = self.name()?;
1879    let parent_info = name.parent_info()?;
1880    let children = &self.0.borrow().value;
1881    let mut children = children[parent_info.child_index + 1..].iter();
1882
1883    // first, skip over the colon token
1884    for child in children.by_ref() {
1885      if let CstNode::Leaf(CstLeafNode::Token(token)) = child
1886        && token.value() == ':'
1887      {
1888        break;
1889      }
1890    }
1891
1892    // now find the value
1893    for child in children {
1894      match child {
1895        CstNode::Leaf(leaf) => match leaf {
1896          CstLeafNode::BooleanLit(_)
1897          | CstLeafNode::NullKeyword(_)
1898          | CstLeafNode::NumberLit(_)
1899          | CstLeafNode::StringLit(_)
1900          | CstLeafNode::WordLit(_) => return Some(child.clone()),
1901          CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
1902            // ignore
1903          }
1904        },
1905        CstNode::Container(container) => match container {
1906          CstContainerNode::Object(_) | CstContainerNode::Array(_) => return Some(child.clone()),
1907          CstContainerNode::Root(_) | CstContainerNode::ObjectProp(_) => return None,
1908        },
1909      }
1910    }
1911
1912    None
1913  }
1914
1915  /// Gets the value if its an object.
1916  pub fn object_value(&self) -> Option<CstObject> {
1917    self.value()?.as_object()
1918  }
1919
1920  /// Gets the value if it's an object or sets the value as an object.
1921  pub fn object_value_or_set(&self) -> CstObject {
1922    match self.value() {
1923      Some(CstNode::Container(CstContainerNode::Object(node))) => node,
1924      _ => {
1925        self.set_value(CstInputValue::Object(Vec::new()));
1926        self.object_value().unwrap()
1927      }
1928    }
1929  }
1930
1931  /// Gets the value if its an array.
1932  pub fn array_value(&self) -> Option<CstArray> {
1933    self.value()?.as_array()
1934  }
1935
1936  /// Gets the value if it's an object or sets the value as an object.
1937  pub fn array_value_or_set(&self) -> CstArray {
1938    match self.value() {
1939      Some(CstNode::Container(CstContainerNode::Array(node))) => node,
1940      _ => {
1941        self.set_value(CstInputValue::Array(Vec::new()));
1942        self.array_value().unwrap()
1943      }
1944    }
1945  }
1946
1947  /// Sibling object property coming before this one.
1948  pub fn previous_property(&self) -> Option<CstObjectProp> {
1949    for sibling in self.previous_siblings() {
1950      if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1951        return Some(prop);
1952      }
1953    }
1954    None
1955  }
1956
1957  /// Sibling object property coming after this one.
1958  pub fn next_property(&self) -> Option<CstObjectProp> {
1959    for sibling in self.next_siblings() {
1960      if let CstNode::Container(CstContainerNode::ObjectProp(prop)) = sibling {
1961        return Some(prop);
1962      }
1963    }
1964    None
1965  }
1966
1967  /// Replaces this node with a new value.
1968  pub fn replace_with(self, key: &str, replacement: CstInputValue) -> Option<CstNode> {
1969    replace_with(self.into(), InsertValue::Property(key, replacement))
1970  }
1971
1972  /// Removes the node from the JSON.
1973  pub fn remove(self) {
1974    remove_comma_separated(self.into())
1975  }
1976
1977  /// Converts a CST object property to a `serde_json::Value`.
1978  ///
1979  /// Returns the value of the property, or `None` if it has no value.
1980  #[cfg(feature = "serde")]
1981  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
1982    self.value()?.to_serde_value()
1983  }
1984
1985  #[cfg(feature = "serde")]
1986  fn name_decoded(&self) -> Option<String> {
1987    match self.name()? {
1988      ObjectPropName::String(s) => s.decoded_value().ok(),
1989      ObjectPropName::Word(w) => Some(w.0.borrow().value.clone()),
1990    }
1991  }
1992}
1993
1994impl Display for CstObjectProp {
1995  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
1996    for child in &self.0.borrow().value {
1997      write!(f, "{}", child)?;
1998    }
1999    Ok(())
2000  }
2001}
2002
2003/// An object property name that may or may not be in quotes (ex. `"prop"` in `"prop": 5`).
2004#[derive(Debug, Clone)]
2005pub enum ObjectPropName {
2006  String(CstStringLit),
2007  Word(CstWordLit),
2008}
2009
2010impl ObjectPropName {
2011  add_root_node_method!();
2012  add_parent_info_methods!();
2013
2014  /// Object property name if it's a string literal.
2015  pub fn as_string_lit(&self) -> Option<CstStringLit> {
2016    match self {
2017      ObjectPropName::String(n) => Some(n.clone()),
2018      ObjectPropName::Word(_) => None,
2019    }
2020  }
2021
2022  /// Object property name if it's a word literal (no quotes).
2023  pub fn as_word_lit(&self) -> Option<CstWordLit> {
2024    match self {
2025      ObjectPropName::String(_) => None,
2026      ObjectPropName::Word(n) => Some(n.clone()),
2027    }
2028  }
2029
2030  /// Decoded value of the string.
2031  pub fn decoded_value(&self) -> Result<String, ParseStringErrorKind> {
2032    match self {
2033      ObjectPropName::String(n) => n.decoded_value(),
2034      ObjectPropName::Word(n) => Ok(n.0.borrow().value.clone()),
2035    }
2036  }
2037
2038  fn parent_info(&self) -> Option<ParentInfo> {
2039    match self {
2040      ObjectPropName::String(n) => n.parent_info(),
2041      ObjectPropName::Word(n) => n.parent_info(),
2042    }
2043  }
2044}
2045
2046impl From<ObjectPropName> for CstNode {
2047  fn from(value: ObjectPropName) -> Self {
2048    match value {
2049      ObjectPropName::String(n) => n.into(),
2050      ObjectPropName::Word(n) => n.into(),
2051    }
2052  }
2053}
2054
2055type CstArrayInner = RefCell<CstChildrenInner>;
2056
2057/// Represents an array that may contain elements (ex. `[]`, `[1, 2, 3]`).
2058#[derive(Debug, Clone)]
2059pub struct CstArray(Rc<CstArrayInner>);
2060
2061impl_container_methods!(CstArray, Array);
2062
2063impl CstArray {
2064  add_root_node_method!();
2065
2066  fn new_no_tokens() -> Self {
2067    Self(CstValueInner::new(Vec::new()))
2068  }
2069
2070  fn new_with_tokens() -> Self {
2071    let array = CstArray::new_no_tokens();
2072    let container: CstContainerNode = array.clone().into();
2073    container.raw_append_children(vec![CstToken::new('[').into(), CstToken::new(']').into()]);
2074    array
2075  }
2076
2077  /// Elements of the array.
2078  pub fn elements(&self) -> Vec<CstNode> {
2079    self
2080      .0
2081      .borrow()
2082      .value
2083      .iter()
2084      .filter(|child| match child {
2085        CstNode::Container(_) => true,
2086        CstNode::Leaf(leaf) => match leaf {
2087          CstLeafNode::BooleanLit(_)
2088          | CstLeafNode::NullKeyword(_)
2089          | CstLeafNode::NumberLit(_)
2090          | CstLeafNode::StringLit(_)
2091          | CstLeafNode::WordLit(_) => true,
2092          CstLeafNode::Token(_) | CstLeafNode::Whitespace(_) | CstLeafNode::Newline(_) | CstLeafNode::Comment(_) => {
2093            false
2094          }
2095        },
2096      })
2097      .cloned()
2098      .collect()
2099  }
2100
2101  /// Appends an element to the end of the array.
2102  ///
2103  /// Returns the appended node.
2104  pub fn append(&self, value: CstInputValue) -> CstNode {
2105    self.insert_or_append(None, value)
2106  }
2107
2108  /// Inserts an element at the specified index.
2109  ///
2110  /// Returns the inserted node.
2111  pub fn insert(&self, index: usize, value: CstInputValue) -> CstNode {
2112    self.insert_or_append(Some(index), value)
2113  }
2114
2115  /// Ensures the array spans multiple lines.
2116  pub fn ensure_multiline(&self) {
2117    ensure_multiline(&self.clone().into());
2118  }
2119
2120  /// Ensures this array and all its descendants use trailing commas.
2121  pub fn set_trailing_commas(&self, mode: TrailingCommaMode) {
2122    set_trailing_commas(mode, &self.clone().into(), self.elements().into_iter());
2123  }
2124
2125  fn insert_or_append(&self, index: Option<usize>, value: CstInputValue) -> CstNode {
2126    insert_or_append_to_container(
2127      &CstContainerNode::Array(self.clone()),
2128      self.elements(),
2129      index,
2130      InsertValue::Value(value),
2131    )
2132  }
2133
2134  /// Replaces this node with a new value.
2135  pub fn replace_with(self, replacement: CstInputValue) -> Option<CstNode> {
2136    replace_with(self.into(), InsertValue::Value(replacement))
2137  }
2138
2139  /// Removes the node from the JSON.
2140  pub fn remove(self) {
2141    remove_comma_separated(self.into())
2142  }
2143
2144  /// Converts a CST array to a `serde_json::Value`.
2145  #[cfg(feature = "serde")]
2146  pub fn to_serde_value(&self) -> Option<serde_json::Value> {
2147    let elements: Vec<serde_json::Value> = self
2148      .elements()
2149      .into_iter()
2150      .filter_map(|element| element.to_serde_value())
2151      .collect();
2152    Some(serde_json::Value::Array(elements))
2153  }
2154}
2155
2156impl Display for CstArray {
2157  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2158    for child in &self.0.borrow().value {
2159      write!(f, "{}", child)?;
2160    }
2161    Ok(())
2162  }
2163}
2164
2165/// Insigificant token found in the file (ex. colon, comma, brace, etc.).
2166#[derive(Debug, Clone)]
2167pub struct CstToken(Rc<RefCell<CstValueInner<char>>>);
2168
2169impl_leaf_methods!(CstToken, Token);
2170
2171impl CstToken {
2172  fn new(value: char) -> Self {
2173    Self(CstValueInner::new(value))
2174  }
2175
2176  /// Sets the char value of the token.
2177  pub fn set_value(&self, value: char) {
2178    self.0.borrow_mut().value = value;
2179  }
2180
2181  /// Char value of the token.
2182  pub fn value(&self) -> char {
2183    self.0.borrow().value
2184  }
2185
2186  /// Removes the node from the JSON.
2187  pub fn remove(self) {
2188    Into::<CstNode>::into(self).remove_raw()
2189  }
2190}
2191
2192impl Display for CstToken {
2193  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2194    write!(f, "{}", self.0.borrow().value)
2195  }
2196}
2197
2198/// Blank space excluding newlines.
2199#[derive(Debug, Clone)]
2200pub struct CstWhitespace(Rc<RefCell<CstValueInner<String>>>);
2201
2202impl_leaf_methods!(CstWhitespace, Whitespace);
2203
2204impl CstWhitespace {
2205  fn new(value: String) -> Self {
2206    Self(CstValueInner::new(value))
2207  }
2208
2209  /// Sets the whitespace value.
2210  pub fn set_value(&self, value: String) {
2211    self.0.borrow_mut().value = value;
2212  }
2213
2214  /// Whitespace value of the node.
2215  pub fn value(&self) -> String {
2216    self.0.borrow().value.clone()
2217  }
2218
2219  /// Removes the node from the JSON.
2220  pub fn remove(self) {
2221    Into::<CstNode>::into(self).remove_raw()
2222  }
2223}
2224
2225impl Display for CstWhitespace {
2226  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2227    write!(f, "{}", self.0.borrow().value)
2228  }
2229}
2230
2231/// Kind of newline.
2232#[derive(Default, Debug, Clone, Copy, PartialEq, Eq)]
2233pub enum CstNewlineKind {
2234  #[default]
2235  LineFeed,
2236  CarriageReturnLineFeed,
2237}
2238
2239/// Newline character (Lf or crlf).
2240#[derive(Debug, Clone)]
2241pub struct CstNewline(Rc<RefCell<CstValueInner<CstNewlineKind>>>);
2242
2243impl_leaf_methods!(CstNewline, Newline);
2244
2245impl CstNewline {
2246  fn new(kind: CstNewlineKind) -> Self {
2247    Self(CstValueInner::new(kind))
2248  }
2249
2250  /// Whether this is a line feed (LF) or carriage return line feed (CRLF).
2251  pub fn kind(&self) -> CstNewlineKind {
2252    self.0.borrow().value
2253  }
2254
2255  /// Sets the newline kind.
2256  pub fn set_kind(&self, kind: CstNewlineKind) {
2257    self.0.borrow_mut().value = kind;
2258  }
2259
2260  /// Removes the node from the JSON.
2261  pub fn remove(self) {
2262    Into::<CstNode>::into(self).remove_raw()
2263  }
2264}
2265
2266impl Display for CstNewline {
2267  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2268    match self.0.borrow().value {
2269      #[allow(clippy::write_with_newline)] // better to be explicit
2270      CstNewlineKind::LineFeed => write!(f, "\n"),
2271      CstNewlineKind::CarriageReturnLineFeed => write!(f, "\r\n"),
2272    }
2273  }
2274}
2275
2276#[derive(Debug, Clone)]
2277pub struct CstComment(Rc<RefCell<CstValueInner<String>>>);
2278
2279impl_leaf_methods!(CstComment, Comment);
2280
2281impl CstComment {
2282  fn new(value: String) -> Self {
2283    Self(CstValueInner::new(value))
2284  }
2285
2286  /// Whether this is a line comment.
2287  pub fn is_line_comment(&self) -> bool {
2288    self.0.borrow().value.starts_with("//")
2289  }
2290
2291  /// Sets the raw value of the comment.
2292  ///
2293  /// This SHOULD include `//` or be surrounded in `/* ... */` or
2294  /// else you'll be inserting a syntax error.
2295  pub fn set_raw_value(&self, value: String) {
2296    self.0.borrow_mut().value = value;
2297  }
2298
2299  /// Raw value of the comment including `//` or `/* ... */`.
2300  pub fn raw_value(&self) -> String {
2301    self.0.borrow().value.clone()
2302  }
2303
2304  /// Removes the node from the JSON.
2305  pub fn remove(self) {
2306    if self.is_line_comment() {
2307      for node in self.previous_siblings() {
2308        if node.is_whitespace() {
2309          node.remove_raw();
2310        } else {
2311          if node.is_newline() {
2312            node.remove_raw();
2313          }
2314          break;
2315        }
2316      }
2317    }
2318
2319    Into::<CstNode>::into(self).remove_raw()
2320  }
2321}
2322
2323impl Display for CstComment {
2324  fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
2325    write!(f, "{}", self.0.borrow().value)
2326  }
2327}
2328
2329struct CstBuilder<'a> {
2330  pub text: &'a str,
2331  pub tokens: VecDeque<crate::tokens::TokenAndRange<'a>>,
2332}
2333
2334impl<'a> CstBuilder<'a> {
2335  pub fn build(&mut self, ast_value: Option<crate::ast::Value<'a>>) -> CstRootNode {
2336    let root_node = CstContainerNode::Root(CstRootNode(Rc::new(RefCell::new(CstChildrenInner {
2337      parent: None,
2338      value: Vec::new(),
2339    }))));
2340
2341    if let Some(ast_value) = ast_value {
2342      let range = ast_value.range();
2343      self.scan_from_to(&root_node, 0, range.start);
2344      self.build_value(&root_node, ast_value);
2345      self.scan_from_to(&root_node, range.end, self.text.len());
2346    } else {
2347      self.scan_from_to(&root_node, 0, self.text.len());
2348    }
2349
2350    match root_node {
2351      CstContainerNode::Root(node) => node,
2352      _ => unreachable!(),
2353    }
2354  }
2355
2356  fn scan_from_to(&mut self, container: &CstContainerNode, from: usize, to: usize) {
2357    if from == to {
2358      return;
2359    }
2360
2361    let mut last_from = from;
2362    while let Some(token) = self.tokens.front() {
2363      if token.range.end <= from {
2364        self.tokens.pop_front();
2365      } else if token.range.start < to {
2366        if token.range.start > last_from {
2367          self.build_whitespace(container, &self.text[last_from..token.range.start]);
2368        }
2369        let token = self.tokens.pop_front().unwrap();
2370        match token.token {
2371          crate::tokens::Token::OpenBrace
2372          | crate::tokens::Token::CloseBrace
2373          | crate::tokens::Token::OpenBracket
2374          | crate::tokens::Token::CloseBracket
2375          | crate::tokens::Token::Comma
2376          | crate::tokens::Token::Colon => {
2377            self.build_token(container, token.token.as_str().chars().next().unwrap());
2378          }
2379          crate::tokens::Token::Null
2380          | crate::tokens::Token::String(_)
2381          | crate::tokens::Token::Word(_)
2382          | crate::tokens::Token::Boolean(_)
2383          | crate::tokens::Token::Number(_) => unreachable!(
2384            "programming error parsing cst {:?} scanning {} to {}",
2385            token.token, from, to
2386          ),
2387          crate::tokens::Token::CommentLine(_) | crate::tokens::Token::CommentBlock(_) => {
2388            container
2389              .raw_append_child(CstComment::new(self.text[token.range.start..token.range.end].to_string()).into());
2390          }
2391        }
2392        last_from = token.range.end;
2393      } else {
2394        break;
2395      }
2396    }
2397
2398    if last_from < to {
2399      self.build_whitespace(container, &self.text[last_from..to]);
2400    }
2401  }
2402
2403  fn build_value(&mut self, container: &CstContainerNode, ast_value: ast::Value<'_>) {
2404    match ast_value {
2405      ast::Value::StringLit(string_lit) => self.build_string_lit(container, string_lit),
2406      ast::Value::NumberLit(number_lit) => {
2407        container.raw_append_child(CstNumberLit::new(number_lit.value.to_string()).into())
2408      }
2409      ast::Value::BooleanLit(boolean_lit) => container.raw_append_child(CstBooleanLit::new(boolean_lit.value).into()),
2410      ast::Value::Object(object) => {
2411        let object = self.build_object(object);
2412        container.raw_append_child(object.into())
2413      }
2414      ast::Value::Array(array) => {
2415        let array = self.build_array(array);
2416        container.raw_append_child(array.into())
2417      }
2418      ast::Value::NullKeyword(_) => container.raw_append_child(CstNullKeyword::new().into()),
2419    }
2420  }
2421
2422  fn build_object(&mut self, object: ast::Object<'_>) -> CstContainerNode {
2423    let container = CstContainerNode::Object(CstObject::new_no_tokens());
2424    let mut last_range_end = object.range.start;
2425    for prop in object.properties {
2426      self.scan_from_to(&container, last_range_end, prop.range.start);
2427      last_range_end = prop.range.end;
2428      let object_prop = self.build_object_prop(prop);
2429      container.raw_append_child(CstNode::Container(object_prop));
2430    }
2431    self.scan_from_to(&container, last_range_end, object.range.end);
2432
2433    container
2434  }
2435
2436  fn build_object_prop(&mut self, prop: ast::ObjectProp<'_>) -> CstContainerNode {
2437    let container = CstContainerNode::ObjectProp(CstObjectProp::new());
2438    let name_range = prop.name.range();
2439    let value_range = prop.value.range();
2440
2441    match prop.name {
2442      ast::ObjectPropName::String(string_lit) => {
2443        self.build_string_lit(&container, string_lit);
2444      }
2445      ast::ObjectPropName::Word(word_lit) => {
2446        container.raw_append_child(CstWordLit::new(word_lit.value.to_string()).into());
2447      }
2448    }
2449
2450    self.scan_from_to(&container, name_range.end, value_range.start);
2451    self.build_value(&container, prop.value);
2452
2453    container
2454  }
2455
2456  fn build_token(&self, container: &CstContainerNode, value: char) {
2457    container.raw_append_child(CstToken::new(value).into());
2458  }
2459
2460  fn build_whitespace(&self, container: &CstContainerNode, value: &str) {
2461    if value.is_empty() {
2462      return;
2463    }
2464
2465    let mut last_found_index = 0;
2466    let mut chars = value.char_indices().peekable();
2467    let maybe_add_previous_text = |from: usize, to: usize| {
2468      let text = &value[from..to];
2469      if !text.is_empty() {
2470        container.raw_append_child(CstWhitespace::new(text.to_string()).into());
2471      }
2472    };
2473    while let Some((i, c)) = chars.next() {
2474      if c == '\r' && chars.peek().map(|(_, c)| *c) == Some('\n') {
2475        maybe_add_previous_text(last_found_index, i);
2476        container.raw_append_child(CstNewline::new(CstNewlineKind::CarriageReturnLineFeed).into());
2477        last_found_index = i + 2;
2478        chars.next(); // move past the \n
2479      } else if c == '\n' {
2480        maybe_add_previous_text(last_found_index, i);
2481        container.raw_append_child(CstNewline::new(CstNewlineKind::LineFeed).into());
2482        last_found_index = i + 1;
2483      }
2484    }
2485
2486    maybe_add_previous_text(last_found_index, value.len());
2487  }
2488
2489  fn build_string_lit(&self, container: &CstContainerNode, lit: ast::StringLit<'_>) {
2490    container.raw_append_child(CstStringLit::new(self.text[lit.range.start..lit.range.end].to_string()).into());
2491  }
2492
2493  fn build_array(&mut self, array: ast::Array<'_>) -> CstContainerNode {
2494    let container = CstContainerNode::Array(CstArray::new_no_tokens());
2495    let mut last_range_end = array.range.start;
2496    for element in array.elements {
2497      let element_range = element.range();
2498      self.scan_from_to(&container, last_range_end, element_range.start);
2499      self.build_value(&container, element);
2500      last_range_end = element_range.end;
2501    }
2502    self.scan_from_to(&container, last_range_end, array.range.end);
2503
2504    container
2505  }
2506}
2507
2508fn remove_comma_separated(node: CstNode) {
2509  fn check_next_node_same_line(trailing_comma: &CstToken) -> bool {
2510    for sibling in trailing_comma.next_siblings() {
2511      match sibling {
2512        CstNode::Container(_) => return true,
2513        CstNode::Leaf(n) => match n {
2514          CstLeafNode::BooleanLit(_)
2515          | CstLeafNode::NullKeyword(_)
2516          | CstLeafNode::NumberLit(_)
2517          | CstLeafNode::StringLit(_)
2518          | CstLeafNode::WordLit(_)
2519          | CstLeafNode::Token(_) => return true,
2520          CstLeafNode::Whitespace(_) | CstLeafNode::Comment(_) => {
2521            // keep going
2522          }
2523          CstLeafNode::Newline(_) => return false,
2524        },
2525      }
2526    }
2527
2528    true
2529  }
2530
2531  let parent = node.parent();
2532  let trailing_comma = node.trailing_comma();
2533  let is_in_array_or_obj = parent
2534    .as_ref()
2535    .map(|p| matches!(p, CstContainerNode::Array(_) | CstContainerNode::Object(_)))
2536    .unwrap_or(false);
2537  let remove_up_to_next_line = trailing_comma
2538    .as_ref()
2539    .map(|c| !check_next_node_same_line(c))
2540    .unwrap_or(true);
2541
2542  for previous in node.previous_siblings() {
2543    if previous.is_trivia() && !previous.is_newline() {
2544      previous.remove_raw();
2545    } else {
2546      break;
2547    }
2548  }
2549
2550  let mut found_newline = false;
2551
2552  // remove up to the trailing comma
2553  if trailing_comma.is_some() {
2554    let mut next_siblings = node.next_siblings();
2555    for next in next_siblings.by_ref() {
2556      let is_comma = next.is_comma();
2557      if next.is_newline() {
2558        found_newline = true;
2559      }
2560      next.remove_raw();
2561      if is_comma {
2562        break;
2563      }
2564    }
2565  } else if is_in_array_or_obj && let Some(previous_comma) = node.previous_siblings().find(|n| n.is_comma()) {
2566    previous_comma.remove();
2567  }
2568
2569  // remove up to the newline
2570  if remove_up_to_next_line && !found_newline {
2571    let mut next_siblings = node.next_siblings().peekable();
2572    while let Some(sibling) = next_siblings.next() {
2573      if sibling.is_trivia() {
2574        if sibling.is_newline() {
2575          sibling.remove_raw();
2576          break;
2577        } else if sibling.is_whitespace()
2578          && next_siblings
2579            .peek()
2580            .map(|n| !n.is_whitespace() && !n.is_newline() && !n.is_comment())
2581            .unwrap_or(false)
2582        {
2583          break;
2584        }
2585        sibling.remove_raw();
2586      } else {
2587        break;
2588      }
2589    }
2590  }
2591
2592  node.remove_raw();
2593
2594  if let Some(parent) = parent {
2595    match parent {
2596      CstContainerNode::Root(n) => {
2597        if n.children().iter().all(|c| c.is_whitespace() || c.is_newline()) {
2598          n.clear_children();
2599        }
2600      }
2601      CstContainerNode::Object(_) | CstContainerNode::Array(_) => {
2602        let children = parent.children();
2603        if children
2604          .iter()
2605          .skip(1)
2606          .take(children.len() - 2)
2607          .all(|c| c.is_whitespace() || c.is_newline())
2608        {
2609          for c in children {
2610            if c.is_whitespace() || c.is_newline() {
2611              c.remove();
2612            }
2613          }
2614        }
2615      }
2616      CstContainerNode::ObjectProp(_) => {}
2617    }
2618  }
2619}
2620
2621fn indent_text(node: &CstNode) -> Option<String> {
2622  let mut last_whitespace: Option<String> = None;
2623  for previous_sibling in node.previous_siblings() {
2624    match previous_sibling {
2625      CstNode::Container(_) => return None,
2626      CstNode::Leaf(leaf) => match leaf {
2627        CstLeafNode::Newline(_) => {
2628          return last_whitespace;
2629        }
2630        CstLeafNode::Whitespace(whitespace) => {
2631          last_whitespace = match last_whitespace {
2632            Some(last_whitespace) => Some(format!("{}{}", whitespace.value(), last_whitespace)),
2633            None => Some(whitespace.value()),
2634          };
2635        }
2636        CstLeafNode::Comment(_) => {
2637          last_whitespace = None;
2638        }
2639        _ => return None,
2640      },
2641    }
2642  }
2643  last_whitespace
2644}
2645
2646fn uses_trailing_commas(node: CstNode) -> bool {
2647  let node = match node {
2648    CstNode::Container(node) => node,
2649    CstNode::Leaf(_) => return false,
2650  };
2651  let mut pending_nodes: VecDeque<CstContainerNode> = VecDeque::from([node.clone()]);
2652  while let Some(node) = pending_nodes.pop_front() {
2653    let children = node.children();
2654    if !node.is_root() {
2655      if let Some(object) = node.as_object() {
2656        if children.iter().any(|c| c.is_whitespace()) {
2657          let properties = object.properties();
2658          if let Some(last_property) = properties.last() {
2659            return last_property.trailing_comma().is_some();
2660          }
2661        }
2662      } else if let Some(object) = node.as_array()
2663        && children.iter().any(|c| c.is_whitespace())
2664      {
2665        let elements = object.elements();
2666        if let Some(last_property) = elements.last() {
2667          return last_property.trailing_comma().is_some();
2668        }
2669      }
2670    }
2671
2672    for child in children {
2673      if let CstNode::Container(child) = child {
2674        pending_nodes.push_back(child);
2675      }
2676    }
2677  }
2678
2679  false // default to false
2680}
2681
2682fn replace_with(node: CstNode, replacement: InsertValue) -> Option<CstNode> {
2683  let mut child_index = node.child_index();
2684  let parent = node.parent()?;
2685  let indents = compute_indents(&parent.clone().into());
2686  let style_info = StyleInfo {
2687    newline_kind: parent.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2688    uses_trailing_commas: uses_trailing_commas(parent.clone().into()),
2689  };
2690  parent.remove_child_set_no_parent(child_index);
2691  parent.raw_insert_value_with_internal_indent(Some(&mut child_index), replacement, &style_info, &indents);
2692  parent.child_at_index(child_index - 1)
2693}
2694
2695enum InsertValue<'a> {
2696  Value(CstInputValue),
2697  Property(&'a str, CstInputValue),
2698}
2699
2700fn insert_or_append_to_container(
2701  container: &CstContainerNode,
2702  elements: Vec<CstNode>,
2703  index: Option<usize>,
2704  value: InsertValue,
2705) -> CstNode {
2706  fn has_separating_newline(siblings: impl Iterator<Item = CstNode>) -> bool {
2707    for sibling in siblings {
2708      if sibling.is_newline() {
2709        return true;
2710      } else if sibling.is_trivia() {
2711        continue;
2712      } else {
2713        break;
2714      }
2715    }
2716    false
2717  }
2718
2719  trim_inner_start_and_end_blanklines(container);
2720
2721  let children = container.children();
2722  let index = index.unwrap_or(elements.len());
2723  let index = std::cmp::min(index, elements.len());
2724  let next_node = elements.get(index);
2725  let previous_node = if index == 0 { None } else { elements.get(index - 1) };
2726  let style_info = StyleInfo {
2727    newline_kind: container.root_node().map(|r| r.newline_kind()).unwrap_or_default(),
2728    uses_trailing_commas: uses_trailing_commas(container.clone().into()),
2729  };
2730  let indents = compute_indents(&container.clone().into());
2731  let child_indents = elements
2732    .first()
2733    .map(compute_indents)
2734    .unwrap_or_else(|| indents.indent());
2735  let has_newline = children.iter().any(|child| child.is_newline());
2736  let force_multiline = has_newline
2737    || match &value {
2738      InsertValue::Value(v) => v.force_multiline(),
2739      InsertValue::Property(..) => true,
2740    };
2741  let mut insert_index: usize;
2742  let inserted_node: CstNode;
2743  if let Some(previous_node) = previous_node {
2744    if previous_node.trailing_comma().is_none() {
2745      let mut index = previous_node.child_index() + 1;
2746      container.raw_insert_child(Some(&mut index), CstToken::new(',').into());
2747    }
2748
2749    let trailing_comma: CstNode = previous_node.trailing_comma().unwrap().into();
2750    insert_index = trailing_comma
2751      .trailing_comments_same_line()
2752      .last()
2753      .map(|t| t.child_index())
2754      .unwrap_or_else(|| trailing_comma.child_index())
2755      + 1;
2756    if force_multiline {
2757      container.raw_insert_children(
2758        Some(&mut insert_index),
2759        vec![
2760          CstNewline::new(style_info.newline_kind).into(),
2761          CstStringLit::new(child_indents.current_indent.clone()).into(),
2762        ],
2763      );
2764      container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2765      inserted_node = container.child_at_index(insert_index - 1).unwrap();
2766    } else {
2767      container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2768      container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2769      inserted_node = container.child_at_index(insert_index - 1).unwrap();
2770    }
2771  } else {
2772    insert_index = if elements.is_empty() {
2773      children
2774        .iter()
2775        .rev()
2776        .skip(1)
2777        .take_while(|t| t.is_whitespace() || t.is_newline())
2778        .last()
2779        .unwrap_or_else(|| children.last().unwrap())
2780        .child_index()
2781    } else {
2782      children.first().unwrap().child_index() + 1
2783    };
2784    if force_multiline {
2785      container.raw_insert_children(
2786        Some(&mut insert_index),
2787        vec![
2788          CstNewline::new(style_info.newline_kind).into(),
2789          CstStringLit::new(child_indents.current_indent.clone()).into(),
2790        ],
2791      );
2792      container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2793      inserted_node = container.child_at_index(insert_index - 1).unwrap();
2794      if next_node.is_none()
2795        && !has_separating_newline(container.child_at_index(insert_index - 1).unwrap().next_siblings())
2796      {
2797        container.raw_insert_children(
2798          Some(&mut insert_index),
2799          vec![
2800            CstNewline::new(style_info.newline_kind).into(),
2801            CstStringLit::new(indents.current_indent.clone()).into(),
2802          ],
2803        );
2804      }
2805    } else {
2806      container.raw_insert_value_with_internal_indent(Some(&mut insert_index), value, &style_info, &child_indents);
2807      inserted_node = container.child_at_index(insert_index - 1).unwrap();
2808    }
2809  }
2810
2811  if next_node.is_some() {
2812    container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2813
2814    if force_multiline {
2815      let comma_token = container.child_at_index(insert_index - 1).unwrap();
2816      if !has_separating_newline(comma_token.next_siblings()) {
2817        container.raw_insert_children(
2818          Some(&mut insert_index),
2819          vec![
2820            CstNewline::new(style_info.newline_kind).into(),
2821            CstStringLit::new(indents.current_indent.clone()).into(),
2822          ],
2823        );
2824      }
2825    } else {
2826      container.raw_insert_child(Some(&mut insert_index), CstWhitespace::new(" ".to_string()).into());
2827    }
2828  } else if style_info.uses_trailing_commas && force_multiline {
2829    container.raw_insert_children(Some(&mut insert_index), vec![CstToken::new(',').into()]);
2830  }
2831
2832  inserted_node
2833}
2834
2835fn set_trailing_commas(
2836  mode: TrailingCommaMode,
2837  parent: &CstContainerNode,
2838  elems_or_props: impl Iterator<Item = CstNode>,
2839) {
2840  let mut elems_or_props = elems_or_props.peekable();
2841  let use_trailing_commas = match mode {
2842    TrailingCommaMode::Never => false,
2843    TrailingCommaMode::IfMultiline => true,
2844  };
2845  while let Some(element) = elems_or_props.next() {
2846    // handle last element
2847    if elems_or_props.peek().is_none() {
2848      if use_trailing_commas {
2849        if element.trailing_comma().is_none() && parent.children().iter().any(|c| c.is_newline()) {
2850          let mut insert_index = element.child_index() + 1;
2851          parent.raw_insert_child(Some(&mut insert_index), CstToken::new(',').into());
2852        }
2853      } else if let Some(trailing_comma) = element.trailing_comma() {
2854        trailing_comma.remove();
2855      }
2856    }
2857
2858    // handle children
2859    let maybe_prop_value = element.as_object_prop().and_then(|p| p.value());
2860    match maybe_prop_value.unwrap_or(element) {
2861      CstNode::Container(CstContainerNode::Array(array)) => {
2862        array.set_trailing_commas(mode);
2863      }
2864      CstNode::Container(CstContainerNode::Object(object)) => {
2865        object.set_trailing_commas(mode);
2866      }
2867      _ => {}
2868    }
2869  }
2870}
2871
2872fn trim_inner_start_and_end_blanklines(node: &CstContainerNode) {
2873  fn remove_blank_lines_after_first(children: &mut Peekable<impl Iterator<Item = CstNode>>) {
2874    // try to find the first newline
2875    for child in children.by_ref() {
2876      if child.is_whitespace() {
2877        // keep searching
2878      } else if child.is_newline() {
2879        break; // found
2880      } else {
2881        return; // stop, no leading blank lines
2882      }
2883    }
2884
2885    let mut pending = Vec::new();
2886    for child in children.by_ref() {
2887      if child.is_whitespace() {
2888        pending.push(child);
2889      } else if child.is_newline() {
2890        child.remove();
2891        for child in pending.drain(..) {
2892          child.remove();
2893        }
2894      } else {
2895        break;
2896      }
2897    }
2898  }
2899
2900  let children = node.children();
2901  let len = children.len();
2902
2903  if len < 2 {
2904    return; // should never happen because this should only be called for array and object
2905  }
2906
2907  // remove blank lines from the front and back
2908  let mut children = children.into_iter().skip(1).take(len - 2).peekable();
2909  remove_blank_lines_after_first(&mut children);
2910  let mut children = children.rev().peekable();
2911  remove_blank_lines_after_first(&mut children);
2912}
2913
2914fn ensure_multiline(container: &CstContainerNode) {
2915  let children = container.children();
2916  if children.iter().any(|c| c.is_newline()) {
2917    return;
2918  }
2919
2920  let indents = compute_indents(&container.clone().into());
2921  let child_indents = indents.indent();
2922  let newline_kind = container
2923    .root_node()
2924    .map(|r| r.newline_kind())
2925    .unwrap_or(CstNewlineKind::LineFeed);
2926
2927  // insert a newline at the start of every part
2928  let children_len = children.len();
2929  let mut children = children.into_iter().skip(1).peekable().take(children_len - 2);
2930  let mut index = 1;
2931  while let Some(child) = children.next() {
2932    if child.is_whitespace() {
2933      child.remove();
2934      continue;
2935    } else {
2936      // insert a newline
2937      container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2938      container.raw_insert_child(
2939        Some(&mut index),
2940        CstWhitespace::new(child_indents.current_indent.clone()).into(),
2941      );
2942
2943      // current node
2944      index += 1;
2945
2946      // consume the next tokens until the next comma
2947      let mut trailing_whitespace = Vec::new();
2948      for next_child in children.by_ref() {
2949        if next_child.is_whitespace() {
2950          trailing_whitespace.push(next_child);
2951        } else {
2952          index += 1 + trailing_whitespace.len();
2953          trailing_whitespace.clear();
2954          if next_child.token_char() == Some(',') {
2955            break;
2956          }
2957        }
2958      }
2959
2960      for trailing_whitespace in trailing_whitespace {
2961        trailing_whitespace.remove();
2962      }
2963    }
2964  }
2965
2966  // insert the last newline
2967  container.raw_insert_child(Some(&mut index), CstNewline::new(newline_kind).into());
2968  if !indents.current_indent.is_empty() {
2969    container.raw_insert_child(Some(&mut index), CstWhitespace::new(indents.current_indent).into());
2970  }
2971}
2972
2973#[derive(Debug)]
2974struct Indents {
2975  current_indent: String,
2976  single_indent: String,
2977}
2978
2979impl Indents {
2980  pub fn indent(&self) -> Indents {
2981    Indents {
2982      current_indent: format!("{}{}", self.current_indent, self.single_indent),
2983      single_indent: self.single_indent.clone(),
2984    }
2985  }
2986}
2987
2988fn compute_indents(node: &CstNode) -> Indents {
2989  let mut indent_level = 0;
2990  let mut stored_last_indent = node.indent_text();
2991  let mut ancestors = node.ancestors().peekable();
2992
2993  while ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
2994    ancestors.next();
2995  }
2996
2997  while let Some(ancestor) = ancestors.next() {
2998    if ancestor.is_root() {
2999      break;
3000    }
3001
3002    if ancestors.peek().and_then(|p| p.as_object_prop()).is_some() {
3003      continue;
3004    }
3005
3006    indent_level += 1;
3007
3008    if let Some(indent_text) = ancestor.indent_text() {
3009      match stored_last_indent {
3010        Some(last_indent) => {
3011          if let Some(single_indent_text) = last_indent.strip_prefix(&indent_text) {
3012            return Indents {
3013              current_indent: format!("{}{}", last_indent, single_indent_text.repeat(indent_level - 1)),
3014              single_indent: single_indent_text.to_string(),
3015            };
3016          }
3017          stored_last_indent = None;
3018        }
3019        None => {
3020          stored_last_indent = Some(indent_text);
3021        }
3022      }
3023    } else {
3024      stored_last_indent = None;
3025    }
3026  }
3027
3028  if indent_level == 1
3029    && let Some(indent_text) = node.indent_text()
3030  {
3031    return Indents {
3032      current_indent: indent_text.clone(),
3033      single_indent: indent_text,
3034    };
3035  }
3036
3037  // try to discover the single indent level by looking at the root node's children
3038  if let Some(root_value) = node.root_node().and_then(|r| r.value()) {
3039    for child in root_value.children() {
3040      if let Some(single_indent) = child.indent_text() {
3041        return Indents {
3042          current_indent: single_indent.repeat(indent_level),
3043          single_indent,
3044        };
3045      }
3046    }
3047  }
3048
3049  // assume two space indentation
3050  let single_indent = "  ";
3051  Indents {
3052    current_indent: single_indent.repeat(indent_level),
3053    single_indent: single_indent.to_string(),
3054  }
3055}
3056
3057struct AncestorIterator {
3058  // pre-emptively store the next ancestor in case
3059  // the currently returned sibling is removed
3060  next: Option<CstContainerNode>,
3061}
3062
3063impl AncestorIterator {
3064  pub fn new(node: CstNode) -> Self {
3065    Self {
3066      next: node.parent_info().map(|i| i.parent.as_container_node()),
3067    }
3068  }
3069}
3070
3071impl Iterator for AncestorIterator {
3072  type Item = CstContainerNode;
3073
3074  fn next(&mut self) -> Option<Self::Item> {
3075    let next = self.next.take()?;
3076    self.next = next.parent_info().map(|i| i.parent.as_container_node());
3077    Some(next)
3078  }
3079}
3080
3081struct NextSiblingIterator {
3082  // pre-emptively store the next sibling in case
3083  // the currently returned sibling is removed
3084  next: Option<CstNode>,
3085}
3086
3087impl NextSiblingIterator {
3088  pub fn new(node: CstNode) -> Self {
3089    Self {
3090      next: node.next_sibling(),
3091    }
3092  }
3093}
3094
3095impl Iterator for NextSiblingIterator {
3096  type Item = CstNode;
3097
3098  fn next(&mut self) -> Option<Self::Item> {
3099    let next_sibling = self.next.take()?;
3100    self.next = next_sibling.next_sibling();
3101    Some(next_sibling)
3102  }
3103}
3104
3105struct PreviousSiblingIterator {
3106  // pre-emptively store the previous sibling in case
3107  // the currently returned sibling is removed
3108  previous: Option<CstNode>,
3109}
3110
3111impl PreviousSiblingIterator {
3112  pub fn new(node: CstNode) -> Self {
3113    Self {
3114      previous: node.previous_sibling(),
3115    }
3116  }
3117}
3118
3119impl Iterator for PreviousSiblingIterator {
3120  type Item = CstNode;
3121
3122  fn next(&mut self) -> Option<Self::Item> {
3123    let previous_sibling = self.previous.take()?;
3124    self.previous = previous_sibling.previous_sibling();
3125    Some(previous_sibling)
3126  }
3127}
3128
3129#[cfg(test)]
3130mod test {
3131  use pretty_assertions::assert_eq;
3132
3133  use crate::cst::CstInputValue;
3134  use crate::cst::TrailingCommaMode;
3135  use crate::json;
3136
3137  use super::CstRootNode;
3138
3139  #[test]
3140  fn single_indent_text() {
3141    let cases = [
3142      (
3143        "  ",
3144        r#"
3145{
3146  "prop": {
3147    "nested": 4
3148  }
3149}
3150    "#,
3151      ),
3152      (
3153        "  ",
3154        r#"
3155{
3156  /* test */ "prop": {}
3157}
3158    "#,
3159      ),
3160      (
3161        "    ",
3162        r#"
3163{
3164    /* test */  "prop": {}
3165}
3166    "#,
3167      ),
3168      (
3169        "\t",
3170        "
3171{
3172\t/* test */  \"prop\": {}
3173}
3174    ",
3175      ),
3176    ];
3177    for (expected, text) in cases {
3178      let root = build_cst(text);
3179      assert_eq!(root.single_indent_text(), Some(expected.to_string()), "Text: {}", text);
3180    }
3181  }
3182
3183  #[test]
3184  fn modify_values() {
3185    let cst = build_cst(
3186      r#"{
3187    "value": 5,
3188    // comment
3189    "value2": "hello",
3190    value3: true
3191}"#,
3192    );
3193
3194    let root_value = cst.value().unwrap();
3195    let root_obj = root_value.as_object().unwrap();
3196    {
3197      let prop = root_obj.get("value").unwrap();
3198      prop
3199        .value()
3200        .unwrap()
3201        .as_number_lit()
3202        .unwrap()
3203        .set_raw_value("10".to_string());
3204      assert!(prop.trailing_comma().is_some());
3205      assert!(prop.previous_property().is_none());
3206      assert_eq!(
3207        prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3208        "value2"
3209      );
3210      assert_eq!(prop.indent_text().unwrap(), "    ");
3211    }
3212    {
3213      let prop = root_obj.get("value2").unwrap();
3214      prop
3215        .value()
3216        .unwrap()
3217        .as_string_lit()
3218        .unwrap()
3219        .set_raw_value("\"5\"".to_string());
3220      assert!(prop.trailing_comma().is_some());
3221      assert_eq!(
3222        prop
3223          .previous_property()
3224          .unwrap()
3225          .name()
3226          .unwrap()
3227          .decoded_value()
3228          .unwrap(),
3229        "value"
3230      );
3231      assert_eq!(
3232        prop.next_property().unwrap().name().unwrap().decoded_value().unwrap(),
3233        "value3"
3234      );
3235    }
3236    {
3237      let prop = root_obj.get("value3").unwrap();
3238      prop.value().unwrap().as_boolean_lit().unwrap().set_value(false);
3239      prop
3240        .name()
3241        .unwrap()
3242        .as_word_lit()
3243        .unwrap()
3244        .set_raw_value("value4".to_string());
3245      assert!(prop.trailing_comma().is_none());
3246      assert_eq!(
3247        prop
3248          .previous_property()
3249          .unwrap()
3250          .name()
3251          .unwrap()
3252          .decoded_value()
3253          .unwrap(),
3254        "value2"
3255      );
3256      assert!(prop.next_property().is_none());
3257    }
3258
3259    assert_eq!(
3260      cst.to_string(),
3261      r#"{
3262    "value": 10,
3263    // comment
3264    "value2": "5",
3265    value4: false
3266}"#
3267    );
3268  }
3269
3270  #[test]
3271  fn remove_properties() {
3272    fn run_test(prop_name: &str, json: &str, expected: &str) {
3273      let cst = build_cst(json);
3274      let root_value = cst.value().unwrap();
3275      let root_obj = root_value.as_object().unwrap();
3276      let prop = root_obj.get(prop_name).unwrap();
3277      prop.remove();
3278      assert_eq!(cst.to_string(), expected);
3279    }
3280
3281    run_test(
3282      "value2",
3283      r#"{
3284    "value": 5,
3285    // comment
3286    "value2": "hello",
3287    value3: true
3288}"#,
3289      r#"{
3290    "value": 5,
3291    // comment
3292    value3: true
3293}"#,
3294    );
3295
3296    run_test(
3297      "value2",
3298      r#"{
3299    "value": 5,
3300    // comment
3301    "value2": "hello"
3302    ,value3: true
3303}"#,
3304      // this is fine... people doing stupid things
3305      r#"{
3306    "value": 5,
3307    // comment
3308value3: true
3309}"#,
3310    );
3311
3312    run_test("value", r#"{ "value": 5 }"#, r#"{}"#);
3313    run_test("value", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value2": 6 }"#);
3314    run_test("value2", r#"{ "value": 5, "value2": 6 }"#, r#"{ "value": 5 }"#);
3315  }
3316
3317  #[test]
3318  fn insert_properties() {
3319    fn run_test(index: usize, prop_name: &str, value: CstInputValue, json: &str, expected: &str) {
3320      let cst = build_cst(json);
3321      let root_value = cst.value().unwrap();
3322      let root_obj = root_value.as_object().unwrap();
3323      root_obj.insert(index, prop_name, value);
3324      assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3325    }
3326
3327    run_test(
3328      0,
3329      "propName",
3330      json!([1]),
3331      r#"{}"#,
3332      r#"{
3333  "propName": [1]
3334}"#,
3335    );
3336
3337    // inserting before first prop
3338    run_test(
3339      0,
3340      "value0",
3341      json!([1]),
3342      r#"{
3343    "value1": 5
3344}"#,
3345      r#"{
3346    "value0": [1],
3347    "value1": 5
3348}"#,
3349    );
3350
3351    // inserting before first prop with leading comment
3352    run_test(
3353      0,
3354      "value0",
3355      json!([1]),
3356      r#"{
3357    // some comment
3358    "value1": 5
3359}"#,
3360      r#"{
3361    "value0": [1],
3362    // some comment
3363    "value1": 5
3364}"#,
3365    );
3366
3367    // inserting after last prop with trailing comment
3368    run_test(
3369      1,
3370      "value1",
3371      json!({
3372        "value": 1
3373      }),
3374      r#"{
3375    "value0": 5 // comment
3376}"#,
3377      r#"{
3378    "value0": 5, // comment
3379    "value1": {
3380        "value": 1
3381    }
3382}"#,
3383    );
3384
3385    // maintain trailing comma
3386    run_test(
3387      1,
3388      "propName",
3389      json!(true),
3390      r#"{
3391  "value": 4,
3392}"#,
3393      r#"{
3394  "value": 4,
3395  "propName": true,
3396}"#,
3397    );
3398
3399    // insert when is on a single line
3400    run_test(
3401      1,
3402      "propName",
3403      json!(true),
3404      r#"{ "value": 4 }"#,
3405      r#"{
3406  "value": 4,
3407  "propName": true
3408}"#,
3409    );
3410
3411    // insert when is on a single line with trailing comma
3412    run_test(
3413      1,
3414      "propName",
3415      json!(true),
3416      r#"{ "value": 4, }"#,
3417      r#"{
3418  "value": 4,
3419  "propName": true,
3420}"#,
3421    );
3422  }
3423
3424  #[test]
3425  fn remove_array_elements() {
3426    fn run_test(index: usize, json: &str, expected: &str) {
3427      let cst = build_cst(json);
3428      let root_value = cst.value().unwrap();
3429      let root_array = root_value.as_array().unwrap();
3430      let element = root_array.elements().get(index).unwrap().clone();
3431      element.remove();
3432      assert_eq!(cst.to_string(), expected);
3433    }
3434
3435    run_test(
3436      0,
3437      r#"[
3438      1,
3439]"#,
3440      r#"[]"#,
3441    );
3442    run_test(
3443      0,
3444      r#"[
3445      1,
3446      2,
3447]"#,
3448      r#"[
3449      2,
3450]"#,
3451    );
3452    run_test(
3453      0,
3454      r#"[
3455      1,
3456      2,
3457]"#,
3458      r#"[
3459      2,
3460]"#,
3461    );
3462
3463    run_test(
3464      1,
3465      r#"[
3466      1, // other comment
3467      2, // trailing comment
3468]"#,
3469      r#"[
3470      1, // other comment
3471]"#,
3472    );
3473
3474    run_test(
3475      1,
3476      r#"[
3477      1, // comment
3478      2
3479]"#,
3480      r#"[
3481      1 // comment
3482]"#,
3483    );
3484
3485    run_test(1, r#"[1, 2]"#, r#"[1]"#);
3486    run_test(1, r#"[ 1, 2 /* test */ ]"#, r#"[ 1 ]"#);
3487    run_test(1, r#"[1, /* test */ 2]"#, r#"[1]"#);
3488    run_test(
3489      1,
3490      r#"[1 /* a */, /* b */ 2 /* c */, /* d */ true]"#,
3491      r#"[1 /* a */, /* d */ true]"#,
3492    );
3493  }
3494
3495  #[test]
3496  fn insert_array_element() {
3497    #[track_caller]
3498    fn run_test(index: usize, value: CstInputValue, json: &str, expected: &str) {
3499      let cst = build_cst(json);
3500      let root_value = cst.value().unwrap();
3501      let root_array = root_value.as_array().unwrap();
3502      root_array.insert(index, value);
3503      assert_eq!(cst.to_string(), expected, "Initial text: {}", json);
3504    }
3505
3506    run_test(0, json!([1]), r#"[]"#, r#"[[1]]"#);
3507    run_test(0, json!([1, true, false, {}]), r#"[]"#, r#"[[1, true, false, {}]]"#);
3508    run_test(0, json!(10), r#"[]"#, r#"[10]"#);
3509    run_test(0, json!(10), r#"[1]"#, r#"[10, 1]"#);
3510    run_test(1, json!(10), r#"[1]"#, r#"[1, 10]"#);
3511    run_test(
3512      0,
3513      json!(10),
3514      r#"[
3515    1
3516]"#,
3517      r#"[
3518    10,
3519    1
3520]"#,
3521    );
3522    run_test(
3523      0,
3524      json!(10),
3525      r#"[
3526    /* test */ 1
3527]"#,
3528      r#"[
3529    10,
3530    /* test */ 1
3531]"#,
3532    );
3533
3534    run_test(
3535      0,
3536      json!({
3537        "value": 1,
3538      }),
3539      r#"[]"#,
3540      r#"[
3541  {
3542    "value": 1
3543  }
3544]"#,
3545    );
3546
3547    // only comment
3548    run_test(
3549      0,
3550      json!({
3551        "value": 1,
3552      }),
3553      r#"[
3554    // comment
3555]"#,
3556      r#"[
3557    // comment
3558    {
3559        "value": 1
3560    }
3561]"#,
3562    );
3563
3564    // blank line
3565    run_test(
3566      0,
3567      json!({
3568        "value": 1,
3569      }),
3570      r#"[
3571
3572]"#,
3573      r#"[
3574  {
3575    "value": 1
3576  }
3577]"#,
3578    );
3579  }
3580
3581  #[test]
3582  fn insert_array_element_trailing_commas() {
3583    let cst = build_cst(
3584      r#"{
3585    "prop": [
3586      1,
3587      2,
3588    ]
3589}"#,
3590    );
3591    cst
3592      .object_value_or_create()
3593      .unwrap()
3594      .array_value("prop")
3595      .unwrap()
3596      .append(json!(3));
3597    assert_eq!(
3598      cst.to_string(),
3599      r#"{
3600    "prop": [
3601      1,
3602      2,
3603      3,
3604    ]
3605}"#
3606    );
3607  }
3608
3609  #[test]
3610  fn remove_comment() {
3611    fn run_test(json: &str, expected: &str) {
3612      let cst = build_cst(json);
3613      let root_value = cst.value().unwrap();
3614      let root_obj = root_value.as_object().unwrap();
3615      root_obj
3616        .children()
3617        .into_iter()
3618        .filter_map(|c| c.as_comment())
3619        .next()
3620        .unwrap()
3621        .remove();
3622      assert_eq!(cst.to_string(), expected);
3623    }
3624
3625    run_test(
3626      r#"{
3627    "value": 5,
3628    // comment
3629    "value2": "hello",
3630    value3: true
3631}"#,
3632      r#"{
3633    "value": 5,
3634    "value2": "hello",
3635    value3: true
3636}"#,
3637    );
3638
3639    run_test(
3640      r#"{
3641    "value": 5,  // comment
3642    "value2": "hello",
3643    value3: true
3644}"#,
3645      r#"{
3646    "value": 5,
3647    "value2": "hello",
3648    value3: true
3649}"#,
3650    );
3651  }
3652
3653  #[test]
3654  fn object_value_or_create() {
3655    // existing
3656    {
3657      let cst = build_cst(r#"{ "value": 1 }"#);
3658      let obj = cst.object_value_or_create().unwrap();
3659      assert!(obj.get("value").is_some());
3660    }
3661    // empty file
3662    {
3663      let cst = build_cst(r#""#);
3664      cst.object_value_or_create().unwrap();
3665      assert_eq!(cst.to_string(), "{}\n");
3666    }
3667    // comment
3668    {
3669      let cst = build_cst("// Copyright something");
3670      cst.object_value_or_create().unwrap();
3671      assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3672    }
3673    // comment and newline
3674    {
3675      let cst = build_cst("// Copyright something\n");
3676      cst.object_value_or_create().unwrap();
3677      assert_eq!(cst.to_string(), "// Copyright something\n{}\n");
3678    }
3679  }
3680
3681  #[test]
3682  fn array_ensure_multiline() {
3683    // empty
3684    {
3685      let cst = build_cst(r#"[]"#);
3686      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3687      assert_eq!(cst.to_string(), "[\n]");
3688    }
3689    // whitespace only
3690    {
3691      let cst = build_cst(r#"[   ]"#);
3692      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3693      assert_eq!(cst.to_string(), "[\n]");
3694    }
3695    // comments only
3696    {
3697      let cst = build_cst(r#"[  /* test */  ]"#);
3698      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3699      assert_eq!(cst.to_string(), "[\n  /* test */\n]");
3700    }
3701    // elements
3702    {
3703      let cst = build_cst(r#"[  1,   2, /* test */ 3  ]"#);
3704      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3705      assert_eq!(
3706        cst.to_string(),
3707        r#"[
3708  1,
3709  2,
3710  /* test */ 3
3711]"#
3712      );
3713    }
3714    // elements deep
3715    {
3716      let cst = build_cst(
3717        r#"{
3718  "prop": {
3719    "value": [  1,   2, /* test */ 3  ]
3720  }
3721}"#,
3722      );
3723      cst
3724        .value()
3725        .unwrap()
3726        .as_object()
3727        .unwrap()
3728        .get("prop")
3729        .unwrap()
3730        .value()
3731        .unwrap()
3732        .as_object()
3733        .unwrap()
3734        .get("value")
3735        .unwrap()
3736        .value()
3737        .unwrap()
3738        .as_array()
3739        .unwrap()
3740        .ensure_multiline();
3741      assert_eq!(
3742        cst.to_string(),
3743        r#"{
3744  "prop": {
3745    "value": [
3746      1,
3747      2,
3748      /* test */ 3
3749    ]
3750  }
3751}"#
3752      );
3753    }
3754    // \r\n newlines
3755    {
3756      let cst = build_cst("[  1,   2, /* test */ 3  ]\r\n");
3757      cst.value().unwrap().as_array().unwrap().ensure_multiline();
3758      assert_eq!(cst.to_string(), "[\r\n  1,\r\n  2,\r\n  /* test */ 3\r\n]\r\n");
3759    }
3760  }
3761
3762  #[test]
3763  fn object_ensure_multiline() {
3764    // empty
3765    {
3766      let cst = build_cst(r#"{}"#);
3767      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3768      assert_eq!(cst.to_string(), "{\n}");
3769    }
3770    // whitespace only
3771    {
3772      let cst = build_cst(r#"{   }"#);
3773      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3774      assert_eq!(cst.to_string(), "{\n}");
3775    }
3776    // comments only
3777    {
3778      let cst = build_cst(r#"{  /* test */  }"#);
3779      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3780      assert_eq!(cst.to_string(), "{\n  /* test */\n}");
3781    }
3782    // elements
3783    {
3784      let cst = build_cst(r#"{  prop: 1,   prop2: 2, /* test */ prop3: 3  }"#);
3785      cst.value().unwrap().as_object().unwrap().ensure_multiline();
3786      assert_eq!(
3787        cst.to_string(),
3788        r#"{
3789  prop: 1,
3790  prop2: 2,
3791  /* test */ prop3: 3
3792}"#
3793      );
3794    }
3795    // elements deep
3796    {
3797      let cst = build_cst(
3798        r#"{
3799  "prop": {
3800    "value": {  prop: 1,   prop2: 2, /* test */ prop3: 3  }
3801  }
3802}"#,
3803      );
3804      cst
3805        .value()
3806        .unwrap()
3807        .as_object()
3808        .unwrap()
3809        .get("prop")
3810        .unwrap()
3811        .value()
3812        .unwrap()
3813        .as_object()
3814        .unwrap()
3815        .get("value")
3816        .unwrap()
3817        .value()
3818        .unwrap()
3819        .as_object()
3820        .unwrap()
3821        .ensure_multiline();
3822      assert_eq!(
3823        cst.to_string(),
3824        r#"{
3825  "prop": {
3826    "value": {
3827      prop: 1,
3828      prop2: 2,
3829      /* test */ prop3: 3
3830    }
3831  }
3832}"#
3833      );
3834    }
3835  }
3836
3837  #[test]
3838  fn sets_trailing_commas() {
3839    fn run_test(input: &str, mode: crate::cst::TrailingCommaMode, expected: &str) {
3840      let cst = build_cst(input);
3841      let root_value = cst.value().unwrap();
3842      let root_obj = root_value.as_object().unwrap();
3843      root_obj.set_trailing_commas(mode);
3844      assert_eq!(cst.to_string(), expected);
3845    }
3846
3847    // empty object
3848    run_test(
3849      r#"{
3850}"#,
3851      TrailingCommaMode::Never,
3852      r#"{
3853}"#,
3854    );
3855    run_test(
3856      r#"{
3857    // test
3858}"#,
3859      TrailingCommaMode::IfMultiline,
3860      r#"{
3861    // test
3862}"#,
3863    );
3864
3865    // single-line object
3866    run_test(r#"{"a": 1}"#, TrailingCommaMode::Never, r#"{"a": 1}"#);
3867    run_test(r#"{"a": 1}"#, TrailingCommaMode::IfMultiline, r#"{"a": 1}"#);
3868    // multiline object
3869    run_test(
3870      r#"{
3871  "a": 1,
3872  "b": 2,
3873  "c": [1, 2, 3],
3874  "d": [
3875      1
3876  ]
3877}"#,
3878      TrailingCommaMode::IfMultiline,
3879      r#"{
3880  "a": 1,
3881  "b": 2,
3882  "c": [1, 2, 3],
3883  "d": [
3884      1,
3885  ],
3886}"#,
3887    );
3888    run_test(
3889      r#"{
3890"a": 1,
3891"b": 2,
3892}"#,
3893      TrailingCommaMode::Never,
3894      r#"{
3895"a": 1,
3896"b": 2
3897}"#,
3898    );
3899  }
3900
3901  #[test]
3902  fn or_create_methods() {
3903    let cst = build_cst("");
3904    let obj = cst.object_value_or_create().unwrap();
3905    assert_eq!(cst.to_string(), "{}\n");
3906    assert!(cst.array_value_or_create().is_none());
3907    assert_eq!(obj.object_value_or_create("prop").unwrap().to_string(), "{}");
3908    assert!(obj.array_value_or_create("prop").is_none());
3909    assert_eq!(obj.array_value_or_create("prop2").unwrap().to_string(), "[]");
3910    assert_eq!(
3911      cst.to_string(),
3912      r#"{
3913  "prop": {},
3914  "prop2": []
3915}
3916"#
3917    );
3918  }
3919
3920  #[test]
3921  fn or_set_methods() {
3922    let cst = build_cst("");
3923    let array = cst.array_value_or_set();
3924    assert_eq!(array.to_string(), "[]");
3925    assert_eq!(cst.to_string(), "[]\n");
3926    let object = cst.object_value_or_set();
3927    assert_eq!(object.to_string(), "{}");
3928    assert_eq!(cst.to_string(), "{}\n");
3929    let value = object.array_value_or_set("test");
3930    assert_eq!(value.to_string(), "[]");
3931    assert_eq!(cst.to_string(), "{\n  \"test\": []\n}\n");
3932    let value = object.object_value_or_set("test");
3933    assert_eq!(value.to_string(), "{}");
3934    assert_eq!(cst.to_string(), "{\n  \"test\": {}\n}\n");
3935    let value = object.array_value_or_set("test");
3936    assert_eq!(value.to_string(), "[]");
3937    assert_eq!(cst.to_string(), "{\n  \"test\": []\n}\n");
3938    value.append(json!(1));
3939    assert_eq!(cst.to_string(), "{\n  \"test\": [1]\n}\n");
3940    let value = object.object_value_or_set("test");
3941    assert_eq!(value.to_string(), "{}");
3942    assert_eq!(cst.to_string(), "{\n  \"test\": {}\n}\n");
3943    let test_prop = object.get("test").unwrap();
3944    assert!(test_prop.object_value().is_some());
3945    assert!(test_prop.array_value().is_none());
3946    test_prop.array_value_or_set();
3947    assert_eq!(cst.to_string(), "{\n  \"test\": []\n}\n");
3948    assert!(test_prop.object_value().is_none());
3949    assert!(test_prop.array_value().is_some());
3950    test_prop.object_value_or_set();
3951    assert_eq!(cst.to_string(), "{\n  \"test\": {}\n}\n");
3952  }
3953
3954  #[test]
3955  fn expression_properties_and_values() {
3956    #[track_caller]
3957    fn run_test(value: CstInputValue, expected: &str) {
3958      let cst = build_cst("");
3959      cst.set_value(value);
3960      assert_eq!(cst.to_string(), format!("{}\n", expected));
3961    }
3962
3963    run_test(json!(1), "1");
3964    run_test(json!("test"), "\"test\"");
3965    {
3966      let text = "test";
3967      run_test(json!(text), "\"test\"");
3968    }
3969    {
3970      let num = 1;
3971      run_test(json!(num), "1");
3972    }
3973    {
3974      let vec = vec![1, 2, 3];
3975      run_test(json!(vec), "[1, 2, 3]");
3976    }
3977    {
3978      let vec = vec![1, 2, 3];
3979      run_test(
3980        json!({
3981          "value": vec,
3982        }),
3983        r#"{
3984  "value": [1, 2, 3]
3985}"#,
3986      );
3987    }
3988    run_test(
3989      json!({
3990        notQuoted: 1,
3991        "quoted": 2,
3992      }),
3993      r#"{
3994  "notQuoted": 1,
3995  "quoted": 2
3996}"#,
3997    )
3998  }
3999
4000  #[test]
4001  fn property_index() {
4002    let cst = build_cst("{ \"prop\": 1, \"prop2\": 2, \"prop3\": 3 }");
4003    let object = cst.object_value().unwrap();
4004    for (i, prop) in object.properties().into_iter().enumerate() {
4005      assert_eq!(prop.property_index(), i);
4006    }
4007  }
4008
4009  #[test]
4010  fn element_index() {
4011    let cst = build_cst("[1, 2, true ,false]");
4012    let array = cst.array_value().unwrap();
4013    for (i, prop) in array.elements().into_iter().enumerate() {
4014      assert_eq!(prop.element_index().unwrap(), i);
4015    }
4016  }
4017
4018  #[track_caller]
4019  fn build_cst(text: &str) -> CstRootNode {
4020    CstRootNode::parse(text, &crate::ParseOptions::default()).unwrap()
4021  }
4022
4023  #[cfg(feature = "serde")]
4024  mod serde_tests {
4025    use super::build_cst;
4026    use serde_json::Value as SerdeValue;
4027    use std::str::FromStr;
4028
4029    #[test]
4030    fn test_cst_to_serde_value_primitives() {
4031      let root = build_cst(r#"42"#);
4032      let value = root.to_serde_value().unwrap();
4033      assert_eq!(value, SerdeValue::Number(serde_json::Number::from_str("42").unwrap()));
4034
4035      let root = build_cst(r#""hello""#);
4036      let value = root.to_serde_value().unwrap();
4037      assert_eq!(value, SerdeValue::String("hello".to_string()));
4038
4039      let root = build_cst(r#"true"#);
4040      let value = root.to_serde_value().unwrap();
4041      assert_eq!(value, SerdeValue::Bool(true));
4042
4043      let root = build_cst(r#"false"#);
4044      let value = root.to_serde_value().unwrap();
4045      assert_eq!(value, SerdeValue::Bool(false));
4046
4047      let root = build_cst(r#"null"#);
4048      let value = root.to_serde_value().unwrap();
4049      assert_eq!(value, SerdeValue::Null);
4050    }
4051
4052    #[test]
4053    fn test_cst_to_serde_value_array() {
4054      let root = build_cst(r#"[1, 2, 3]"#);
4055      let value = root.to_serde_value().unwrap();
4056      let expected = SerdeValue::Array(vec![
4057        SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4058        SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4059        SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4060      ]);
4061      assert_eq!(value, expected);
4062    }
4063
4064    #[test]
4065    fn test_cst_to_serde_value_array_with_comments() {
4066      let root = build_cst(
4067        r#"[
4068        // comment 1
4069        1,
4070        2, // comment 2
4071        3
4072      ]"#,
4073      );
4074      let value = root.to_serde_value().unwrap();
4075      let expected = SerdeValue::Array(vec![
4076        SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4077        SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4078        SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4079      ]);
4080      assert_eq!(value, expected);
4081    }
4082
4083    #[test]
4084    fn test_cst_to_serde_value_object() {
4085      let root = build_cst(
4086        r#"{
4087        "name": "Alice",
4088        "age": 30,
4089        "active": true
4090      }"#,
4091      );
4092      let value = root.to_serde_value().unwrap();
4093
4094      let mut expected_map = serde_json::map::Map::new();
4095      expected_map.insert("name".to_string(), SerdeValue::String("Alice".to_string()));
4096      expected_map.insert(
4097        "age".to_string(),
4098        SerdeValue::Number(serde_json::Number::from_str("30").unwrap()),
4099      );
4100      expected_map.insert("active".to_string(), SerdeValue::Bool(true));
4101
4102      assert_eq!(value, SerdeValue::Object(expected_map));
4103    }
4104
4105    #[test]
4106    fn test_cst_to_serde_value_object_with_comments() {
4107      let root = build_cst(
4108        r#"{
4109        // This is a name
4110        "name": "Bob",
4111        /* age field */
4112        "age": 25
4113      }"#,
4114      );
4115      let value = root.to_serde_value().unwrap();
4116
4117      let mut expected_map = serde_json::map::Map::new();
4118      expected_map.insert("name".to_string(), SerdeValue::String("Bob".to_string()));
4119      expected_map.insert(
4120        "age".to_string(),
4121        SerdeValue::Number(serde_json::Number::from_str("25").unwrap()),
4122      );
4123
4124      assert_eq!(value, SerdeValue::Object(expected_map));
4125    }
4126
4127    #[test]
4128    fn test_cst_to_serde_value_nested() {
4129      let root = build_cst(
4130        r#"{
4131        "person": {
4132          "name": "Charlie",
4133          "hobbies": ["reading", "gaming"]
4134        },
4135        "count": 42
4136      }"#,
4137      );
4138      let value = root.to_serde_value().unwrap();
4139
4140      let mut hobbies = Vec::new();
4141      hobbies.push(SerdeValue::String("reading".to_string()));
4142      hobbies.push(SerdeValue::String("gaming".to_string()));
4143
4144      let mut person_map = serde_json::map::Map::new();
4145      person_map.insert("name".to_string(), SerdeValue::String("Charlie".to_string()));
4146      person_map.insert("hobbies".to_string(), SerdeValue::Array(hobbies));
4147
4148      let mut expected_map = serde_json::map::Map::new();
4149      expected_map.insert("person".to_string(), SerdeValue::Object(person_map));
4150      expected_map.insert(
4151        "count".to_string(),
4152        SerdeValue::Number(serde_json::Number::from_str("42").unwrap()),
4153      );
4154
4155      assert_eq!(value, SerdeValue::Object(expected_map));
4156    }
4157
4158    #[test]
4159    fn test_cst_to_serde_value_with_trailing_comma() {
4160      let root = build_cst(
4161        r#"{
4162        "a": 1,
4163        "b": 2,
4164      }"#,
4165      );
4166      let value = root.to_serde_value().unwrap();
4167
4168      let mut expected_map = serde_json::map::Map::new();
4169      expected_map.insert(
4170        "a".to_string(),
4171        SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4172      );
4173      expected_map.insert(
4174        "b".to_string(),
4175        SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4176      );
4177
4178      assert_eq!(value, SerdeValue::Object(expected_map));
4179    }
4180
4181    #[test]
4182    fn test_cst_to_serde_value_empty_structures() {
4183      let root = build_cst(r#"{}"#);
4184      let value = root.to_serde_value().unwrap();
4185      assert_eq!(value, SerdeValue::Object(serde_json::map::Map::new()));
4186
4187      let root = build_cst(r#"[]"#);
4188      let value = root.to_serde_value().unwrap();
4189      assert_eq!(value, SerdeValue::Array(Vec::new()));
4190    }
4191
4192    #[test]
4193    fn test_cst_to_serde_value_scientific_notation() {
4194      let root = build_cst(r#"0.3e+025"#);
4195      let value = root.to_serde_value().unwrap();
4196      assert_eq!(
4197        value,
4198        SerdeValue::Number(serde_json::Number::from_str("0.3e+025").unwrap())
4199      );
4200    }
4201
4202    #[test]
4203    fn test_cst_node_to_serde_value() {
4204      let root = build_cst(r#"{ "test": 123 }"#);
4205      let value_node = root.value().unwrap();
4206      let json_value = value_node.to_serde_value().unwrap();
4207
4208      let mut expected_map = serde_json::map::Map::new();
4209      expected_map.insert(
4210        "test".to_string(),
4211        SerdeValue::Number(serde_json::Number::from_str("123").unwrap()),
4212      );
4213
4214      assert_eq!(json_value, SerdeValue::Object(expected_map));
4215    }
4216
4217    #[test]
4218    fn test_cst_object_prop_to_serde_value() {
4219      let root = build_cst(r#"{ "key": [1, 2, 3] }"#);
4220      let obj = root.value().unwrap().as_object().unwrap();
4221      let prop = obj.get("key").unwrap();
4222      let prop_value = prop.to_serde_value().unwrap();
4223
4224      let expected = SerdeValue::Array(vec![
4225        SerdeValue::Number(serde_json::Number::from_str("1").unwrap()),
4226        SerdeValue::Number(serde_json::Number::from_str("2").unwrap()),
4227        SerdeValue::Number(serde_json::Number::from_str("3").unwrap()),
4228      ]);
4229
4230      assert_eq!(prop_value, expected);
4231    }
4232  }
4233}