1use std::{fmt::Debug, marker::PhantomData, mem};23use jrsonnet_rowan_parser::{4 nodes::{Trivia, TriviaKind},5 AstNode, AstToken, SyntaxElement,6 SyntaxKind::*,7 SyntaxNode, TS,8};910pub type ChildTrivia = Vec<Trivia>;1112pub struct ChildIterator<I, T> {13 inner: I,14 _marker: PhantomData<T>,15}1617pub fn children_between<T: AstNode + Debug>(18 node: SyntaxNode,19 start: Option<&SyntaxElement>,20 end: Option<&SyntaxElement>,21) -> (Vec<Child<T>>, ChildTrivia) {22 let mut iter = node.children_with_tokens().peekable();23 while iter.peek() == start {24 iter.next();25 }26 children(27 iter.take_while(|i| Some(i) != end),28 start.is_none() || end.is_none(),29 )30}3132pub fn should_start_with_newline(tt: &ChildTrivia) -> bool {33 34 count_newlines_before(&tt) >= 235}3637fn count_newlines_before(tt: &ChildTrivia) -> usize {38 let mut nl_count = 0;39 for t in tt {40 match t.kind() {41 TriviaKind::Whitespace => {42 nl_count += t.text().bytes().filter(|b| *b == b'\n').count();43 }44 _ => break,45 }46 }47 nl_count48}49fn count_newlines_after(tt: &ChildTrivia) -> usize {50 let mut nl_count = 0;51 for t in tt.iter().rev() {52 match t.kind() {53 TriviaKind::Whitespace => {54 nl_count += t.text().bytes().filter(|b| *b == b'\n').count();55 }56 TriviaKind::SingleLineHashComment => {57 nl_count += 1;58 break;59 }60 TriviaKind::SingleLineSlashComment => {61 nl_count += 1;62 break;63 }64 _ => {}65 }66 }67 nl_count68}6970pub fn children<'a, T: AstNode + Debug>(71 items: impl Iterator<Item = SyntaxElement>,72 loose: bool,73) -> (Vec<Child<T>>, ChildTrivia) {74 let mut out = Vec::new();75 let mut current_child = None::<Child<T>>;76 let mut next = ChildTrivia::new();77 78 let mut started_next = false;79 let mut had_some = false;8081 for item in items {82 if let Some(value) = item.as_node().cloned().and_then(T::cast) {83 let before_trivia = mem::take(&mut next);84 let last_child = current_child.replace(Child {85 newlines_above: if had_some {86 count_newlines_before(&before_trivia)87 + current_child88 .as_ref()89 .map(|c| count_newlines_after(&c.inline_trivia))90 .unwrap_or_default()91 } else {92 093 },94 before_trivia,95 value,96 inline_trivia: Vec::new(),97 });98 if let Some(last_child) = last_child {99 out.push(last_child)100 }101 had_some = true;102 started_next = false;103 } else if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {104 let is_single_line_comment = trivia.kind() == TriviaKind::SingleLineHashComment105 || trivia.kind() == TriviaKind::SingleLineSlashComment;106 if started_next107 || current_child.is_none()108 || trivia.text().contains('\n') && !is_single_line_comment109 {110 next.push(trivia.clone());111 started_next = true;112 } else {113 let cur = current_child.as_mut().expect("checked not none");114 cur.inline_trivia.push(trivia);115 if is_single_line_comment {116 started_next = true;117 }118 }119 had_some = true;120 } else if loose {121 if had_some {122 break;123 }124 started_next = true;125 } else {126 assert!(127 TS![, ;].contains(item.kind()) || item.kind() == ERROR,128 "silently eaten token: {:?}",129 item.kind()130 )131 }132 }133134 if let Some(current_child) = current_child {135 out.push(current_child);136 }137138 (out, next)139}140141#[derive(Debug)]142pub struct Child<T> {143 newlines_above: usize,144 145 146 147 148 149 150 pub before_trivia: ChildTrivia,151 pub value: T,152 153 154 155 156 157 158 159 pub inline_trivia: ChildTrivia,160}161162impl<T> Child<T> {163 164 pub fn needs_newline_above(&self) -> bool {165 166 self.newlines_above >= 2167 }168}