difftreelog
feat(fmt) preserve comments at root of source code
in: master
3 files changed
cmds/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 {
cmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth1use std::any::type_name;1use std::any::type_name;223use children::children_between;3use children::{children_between, trivia_before};4use dprint_core::formatting::{PrintItems, PrintOptions};4use dprint_core::formatting::{PrintItems, PrintOptions};5use jrsonnet_rowan_parser::{5use jrsonnet_rowan_parser::{6 nodes::{6 nodes::{13};13};141415use crate::{15use crate::{16 children::should_start_with_newline,16 children::{should_start_with_newline, trivia_after},17 comments::{format_comments, CommentLocation},17 comments::{format_comments, CommentLocation},18};18};1919463463464impl Printable for SourceFile {464impl Printable for SourceFile {465 fn print(&self) -> PrintItems {465 fn print(&self) -> PrintItems {466 let mut pi = p!(new:);466 assert!(self.expr().is_some());467 let before = trivia_before(468 self.syntax().clone(),469 self.expr()470 .map(|e| e.syntax().clone())471 .map(Into::into)472 .as_ref(),473 );474 let after = trivia_after(475 self.syntax().clone(),467 self.expr().print()476 self.expr()477 .map(|e| e.syntax().clone())478 .map(Into::into)479 .as_ref(),480 );481 p!(pi: items(format_comments(&before, CommentLocation::AboveItem)));482 p!(pi: {self.expr()} nl);483 p!(pi: items(format_comments(&after, CommentLocation::EndOfItems)));484 pi468 }485 }469}486}470487471fn main() {488fn main() {472 let (parsed, _errors) = jrsonnet_rowan_parser::parse(489 let (parsed, _errors) = jrsonnet_rowan_parser::parse(473 r#"490 r#"474491475492476 # Edit me!493 # Edit me!477 local b = import "b.libsonnet"; # comment494 local b = import "b.libsonnet"; # comment478 local a = import "a.libsonnet";495 local a = import "a.libsonnet";479496480 local f(x,y)=x+y;497 local f(x,y)=x+y;481498482 local {a: [b, ..., c], d, ...e} = null;499 local {a: [b, ..., c], d, ...e} = null;483500484 local ass = assert false : false; false;501 local ass = assert false : false; false;485502486 local fn = function(a, b, c = 3) 4;503 local fn = function(a, b, c = 3) 4;487504488 local comp = [a for b in c if d == e];505 local comp = [a for b in c if d == e];489 local ocomp = {[k]: 1 for k in v};506 local ocomp = {[k]: 1 for k in v};490507491 local ? = skip;508 local ? = skip;492509493 local intr = $intrinsic(test);510 local intr = $intrinsic(test);494 local intrId = $intrinsicId;511 local intrId = $intrinsicId;495 local intrThisFile = $intrinsicThisFile;512 local intrThisFile = $intrinsicThisFile;496513497 local ie = a[expr];514 local ie = a[expr];498515499 local unary = !a;516 local unary = !a;500517501 local Template = {z: "foo"};518 local Template = {z: "foo"};502519503 {520 {504 local521 local505522506 h = 3,523 h = 3,507 assert self.a == 1524 assert self.a == 1508525509 : "error",526 : "error",510 "f": ((((((3)))))) ,527 "f": ((((((3)))))) ,511 "g g":528 "g g":512 f(4,2),529 f(4,2),513 arr: [[530 arr: [[514 1, 2,531 1, 2,515 ],532 ],516 3,533 3,517 {534 {518 b: {535 b: {519 c: {536 c: {520 k: [16]537 k: [16]521 }538 }522 }539 }523 }540 }524 ],541 ],525 m: a[1::],542 m: a[1::],526 m: b[::],543 m: b[::],527544528 comments: {545 comments: {529 _: '',546 _: '',530 // Plain comment547 // Plain comment531 a: '',548 a: '',532549533 # Plain comment with empty line before550 # Plain comment with empty line before534 b: '',551 b: '',535 /*Single-line multiline comment552 /*Single-line multiline comment536553537 */554 */538 c: '',555 c: '',539556540 /**Single-line multiline doc comment557 /**Single-line multiline doc comment541558542 */559 */543 c: '',560 c: '',544561545 /**multiline doc comment562 /**multiline doc comment546 s563 s547 */564 */548 c: '',565 c: '',549566550 /*567 /*551568552 Multi-line569 Multi-line553570554 comment571 comment555 */572 */556 d: '',573 d: '',557574558 e: '', // Inline comment575 e: '', // Inline comment559576560 k: '',577 k: '',561578562 // Text after everything579 // Text after everything563 },580 },564 comments2: {581 comments2: {565 k: '',582 k: '',566 // Text after everything, but no newline above583 // Text after everything, but no newline above567 },584 },568 k: if a == b then585 k: if a == b then569586570587571 2588 2572589573 else Template {}590 else Template {}574 } + Template591 } + Template575592576593594 // Comment after everything577"#,595"#,578 );596 );579597580 // dbg!(errors);598 // dbg!(errors);crates/jrsonnet-rowan-parser/src/event.rsdiffbeforeafterboth--- a/crates/jrsonnet-rowan-parser/src/event.rs
+++ b/crates/jrsonnet-rowan-parser/src/event.rs
@@ -117,6 +117,9 @@
eat_start_whitespace = false;
}
Event::Finish { wrapper } => {
+ if depth == 1 {
+ self.skip_whitespace();
+ }
self.builder.finish_node();
depth -= 1;
let mut idx = idx;
@@ -126,6 +129,9 @@
wrapper = if let Event::Finish { wrapper } =
mem::replace(&mut self.events[idx], Event::Noop)
{
+ if depth == 1 {
+ self.skip_whitespace();
+ }
self.builder.finish_node();
depth -= 1;
wrapper