git.delta.rocks / jrsonnet / refs/commits / 016538aa1e6d

difftreelog

feat(fmt) preserve comments at root of source code

Yaroslav Bolyukin2022-06-22parent: #014057b.patch.diff
in: master

3 files changed

modifiedcmds/jrsonnet-fmt/src/children.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/children.rs
+++ b/cmds/jrsonnet-fmt/src/children.rs
@@ -1,3 +1,5 @@
+// TODO: Return errors as trivia
+
 use std::{fmt::Debug, marker::PhantomData, mem};
 
 use jrsonnet_rowan_parser::{
@@ -9,9 +11,52 @@
 
 pub type ChildTrivia = Vec<Trivia>;
 
-pub struct ChildIterator<I, T> {
-	inner: I,
-	_marker: PhantomData<T>,
+/// Node should have no non-trivia tokens before element
+pub fn trivia_before(node: SyntaxNode, end: Option<&SyntaxElement>) -> ChildTrivia {
+	let mut out = Vec::new();
+	for item in node.children_with_tokens() {
+		if Some(&item) == end {
+			break;
+		}
+
+		if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
+			out.push(trivia);
+		} else if end.is_none() {
+			break;
+		} else {
+			assert!(
+				TS![, ;].contains(item.kind()) || item.kind() == ERROR,
+				"silently eaten token: {:?}",
+				item.kind()
+			)
+		}
+	}
+	out
+}
+/// Node should have no non-trivia tokens after element
+pub fn trivia_after(node: SyntaxNode, start: Option<&SyntaxElement>) -> ChildTrivia {
+	if start.is_none() {
+		return Vec::new();
+	}
+	let mut iter = node.children_with_tokens().peekable();
+	while iter.peek() != start {
+		// println!("Skipped {}");
+		dbg!(&iter.next());
+	}
+	dbg!(&iter.next());
+	let mut out = Vec::new();
+	for item in iter {
+		if let Some(trivia) = item.as_token().cloned().and_then(Trivia::cast) {
+			out.push(trivia);
+		} else {
+			assert!(
+				TS![, ;].contains(item.kind()) || item.kind() == ERROR,
+				"silently eaten token: {:?}",
+				item.kind()
+			)
+		}
+	}
+	out
 }
 
 pub fn children_between<T: AstNode + Debug>(
@@ -20,9 +65,10 @@
 	end: Option<&SyntaxElement>,
 ) -> (Vec<Child<T>>, ChildTrivia) {
 	let mut iter = node.children_with_tokens().peekable();
-	while iter.peek() == start {
+	while iter.peek() != start {
 		iter.next();
 	}
+	iter.next();
 	children(
 		iter.take_while(|i| Some(i) != end),
 		start.is_none() || end.is_none(),
@@ -31,7 +77,7 @@
 
 pub fn should_start_with_newline(tt: &ChildTrivia) -> bool {
 	// First for previous item end
-	count_newlines_before(&tt) >= 2
+	count_newlines_before(tt) >= 2
 }
 
 fn count_newlines_before(tt: &ChildTrivia) -> usize {
modifiedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/main.rs
+++ b/cmds/jrsonnet-fmt/src/main.rs
@@ -1,6 +1,6 @@
 use std::any::type_name;
 
-use children::children_between;
+use children::{children_between, trivia_before};
 use dprint_core::formatting::{PrintItems, PrintOptions};
 use jrsonnet_rowan_parser::{
 	nodes::{
@@ -13,7 +13,7 @@
 };
 
 use crate::{
-	children::should_start_with_newline,
+	children::{should_start_with_newline, trivia_after},
 	comments::{format_comments, CommentLocation},
 };
 
@@ -463,8 +463,25 @@
 
 impl Printable for SourceFile {
 	fn print(&self) -> PrintItems {
-		assert!(self.expr().is_some());
-		self.expr().print()
+		let mut pi = p!(new:);
+		let before = trivia_before(
+			self.syntax().clone(),
+			self.expr()
+				.map(|e| e.syntax().clone())
+				.map(Into::into)
+				.as_ref(),
+		);
+		let after = trivia_after(
+			self.syntax().clone(),
+			self.expr()
+				.map(|e| e.syntax().clone())
+				.map(Into::into)
+				.as_ref(),
+		);
+		p!(pi: items(format_comments(&before, CommentLocation::AboveItem)));
+		p!(pi: {self.expr()} nl);
+		p!(pi: items(format_comments(&after, CommentLocation::EndOfItems)));
+		pi
 	}
 }
 
@@ -574,6 +591,7 @@
 		} + Template
 
 
+		// Comment after everything
 "#,
 	);
 
modifiedcrates/jrsonnet-rowan-parser/src/event.rsdiffbeforeafterboth
before · crates/jrsonnet-rowan-parser/src/event.rs
1use std::mem;23use rowan::{GreenNodeBuilder, Language};45use crate::{6	lex::Lexeme,7	nodes::Trivia,8	parser::{Parse, SyntaxError},9	AstToken, JsonnetLanguage, SyntaxKind,10};1112#[derive(Clone, Debug, PartialEq, Eq)]13pub enum Event {14	/// Used for unfinished markers15	Pending,16	/// After marker is completed, Pending event is replaced with Start17	Start {18		kind: SyntaxKind,19		/// If marker is preceded or wrapped - instead of reordering events, we20		/// insert start event in the end of events Vec instead, and store relative offset to this event here21		forward_parent: Option<usize>,22	},23	/// Eat token24	Token {25		kind: SyntaxKind,26	},27	/// Push token, but do not eat anything,28	VirtualToken {29		kind: SyntaxKind,30	},31	/// Position of finished node32	Finish {33		/// Same as forward_parent of Start, but for wrapping34		wrapper: Option<usize>,35	},36	Error(SyntaxError),37	/// Used for dropped markers and other things38	Noop,39}4041pub(super) struct Sink<'i> {42	pub builder: GreenNodeBuilder<'static>,43	lexemes: &'i [Lexeme<'i>],44	offset: usize,45	events: Vec<Event>,46	pub errors: Vec<SyntaxError>,47}4849impl<'i> Sink<'i> {50	pub(super) fn new(events: Vec<Event>, lexemes: &'i [Lexeme<'i>]) -> Self {51		Self {52			builder: GreenNodeBuilder::new(),53			lexemes,54			offset: 0,55			events,56			errors: vec![],57		}58	}5960	pub(super) fn finish(mut self) -> Parse {61		let mut eat_start_whitespace = false;62		let mut depth = 0;63		for idx in 0..self.events.len() {64			match mem::replace(&mut self.events[idx], Event::Noop) {65				Event::Start {66					kind,67					forward_parent,68				} => {69					if depth != 0 {70						self.skip_whitespace();71					}72					let mut kinds = vec![kind];7374					let mut idx = idx;75					let mut forward_parent = forward_parent;7677					// Walk through the forward parent of the forward parent, and the forward parent78					// of that, and of that, etc. until we reach a StartNode event without a forward79					// parent.80					while let Some(fp) = forward_parent {81						idx += fp;8283						forward_parent = if let Event::Start {84							kind,85							forward_parent,86						} = mem::replace(&mut self.events[idx], Event::Noop)87						{88							kinds.push(kind);89							forward_parent90						} else {91							unreachable!()92						};93					}9495					for kind in kinds.into_iter().rev() {96						self.builder.start_node(JsonnetLanguage::kind_to_raw(kind));97						depth += 1;98						if depth == 1 {99							self.skip_whitespace();100						}101					}102103					eat_start_whitespace = false;104				}105				Event::Token { kind } => {106					if eat_start_whitespace {107						self.skip_whitespace();108					}109					self.token(kind);110					eat_start_whitespace = true;111				}112				Event::VirtualToken { kind } => {113					if eat_start_whitespace {114						self.skip_whitespace();115					}116					self.virtual_token(kind);117					eat_start_whitespace = false;118				}119				Event::Finish { wrapper } => {120					self.builder.finish_node();121					depth -= 1;122					let mut idx = idx;123					let mut wrapper = wrapper;124					while let Some(w) = wrapper {125						idx += w;126						wrapper = if let Event::Finish { wrapper } =127							mem::replace(&mut self.events[idx], Event::Noop)128						{129							self.builder.finish_node();130							depth -= 1;131							wrapper132						} else {133							unreachable!()134						}135					}136					eat_start_whitespace = true;137				}138				Event::Pending => panic!("pending event should not appear in finished events"),139				Event::Noop => {}140				Event::Error(e) => {141					self.errors.push(e);142				}143			}144		}145146		Parse {147			green_node: self.builder.finish(),148			errors: self.errors,149		}150	}151	fn virtual_token(&mut self, kind: SyntaxKind) {152		self.builder.token(JsonnetLanguage::kind_to_raw(kind), "")153	}154	fn token(&mut self, kind: SyntaxKind) {155		let lexeme = self.lexemes[self.offset];156		self.builder157			.token(JsonnetLanguage::kind_to_raw(kind), lexeme.text);158		self.offset += 1;159	}160	fn skip_whitespace(&mut self) {161		while let Some(lexeme) = self.lexemes.get(self.offset) {162			if !Trivia::can_cast(lexeme.kind) {163				break;164			}165166			self.token(lexeme.kind);167		}168	}169}