diff --git a/cmds/jrsonnet-fmt/src/comments.rs b/cmds/jrsonnet-fmt/src/comments.rs index 5084219e..744c6624 100644 --- a/cmds/jrsonnet-fmt/src/comments.rs +++ b/cmds/jrsonnet-fmt/src/comments.rs @@ -12,22 +12,19 @@ pub enum CommentLocation { EndOfItems, } -#[must_use] -pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintItems { - let mut pi = p!(new:); - +pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation, out: &mut PrintItems) { for c in comments { let Ok(c) = c else { let mut text = c.as_ref().unwrap_err() as &str; while !text.is_empty() { let pos = text.find(|c| c == '\n' || c == '\t').unwrap_or(text.len()); let sliced = &text[..pos]; - p!(pi: string(sliced.to_string())); + p!(out, string(sliced.to_string())); text = &text[pos..]; if !text.is_empty() { match text.as_bytes()[0] { - b'\n' => p!(pi: nl), - b'\t' => p!(pi: tab), + b'\n' => p!(out, nl), + b'\t' => p!(out, tab), _ => unreachable!(), } text = &text[1..]; @@ -70,9 +67,9 @@ pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintIte } if lines.len() == 1 && !doc { if matches!(loc, CommentLocation::ItemInline) { - p!(pi: str(" ")); + p!(out, str(" ")); } - p!(pi: str("/* ") string(lines[0].trim().to_string()) str(" */") nl) + p!(out, str("/* ") string(lines[0].trim().to_string()) str(" */") nl) } else if !lines.is_empty() { fn common_ws_prefix<'a>(a: &'a str, b: &str) -> &'a str { let offset = a @@ -107,36 +104,36 @@ pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintIte .to_string(); } - p!(pi: str("/*")); + p!(out, str("/*")); if doc { - p!(pi: str("*")); + p!(out, str("*")); } - p!(pi: nl); + p!(out, nl); for mut line in lines { if doc { - p!(pi: str(" *")); + p!(out, str(" *")); } if line.is_empty() { - p!(pi: nl); + p!(out, nl); } else { if doc { - p!(pi: str(" ")); + p!(out, str(" ")); } while let Some(new_line) = line.strip_prefix('\t') { if doc { - p!(pi: str(" ")); + p!(out, str(" ")); } else { - p!(pi: tab); + p!(out, tab); } line = new_line.to_string(); } - p!(pi: string(line.to_string()) nl) + p!(out, string(line.to_string()) nl) } } if doc { - p!(pi: str(" ")); + p!(out, str(" ")); } - p!(pi: str("*/") nl) + p!(out, str("*/") nl) } } // TODO: Keep common padding for multiple continous lines of single-line comments @@ -157,27 +154,25 @@ pub fn format_comments(comments: &ChildTrivia, loc: CommentLocation) -> PrintIte // ``` TriviaKind::SingleLineHashComment => { if matches!(loc, CommentLocation::ItemInline) { - p!(pi: str(" ")) + p!(out, str(" ")) } - p!(pi: str("# ") string(c.text().strip_prefix('#').expect("hash comment starts with #").trim().to_string())); + p!(out, str("# ") string(c.text().strip_prefix('#').expect("hash comment starts with #").trim().to_string())); if !matches!(loc, CommentLocation::ItemInline) { - p!(pi: nl) + p!(out, nl) } } TriviaKind::SingleLineSlashComment => { if matches!(loc, CommentLocation::ItemInline) { - p!(pi: str(" ")) + p!(out, str(" ")) } - p!(pi: str("// ") string(c.text().strip_prefix("//").expect("comment starts with //").trim().to_string())); + p!(out, str("// ") string(c.text().strip_prefix("//").expect("comment starts with //").trim().to_string())); if !matches!(loc, CommentLocation::ItemInline) { - p!(pi: nl) + p!(out, nl) } } // Garbage in - garbage out - TriviaKind::ErrorCommentTooShort => p!(pi: str("/*/")), - TriviaKind::ErrorCommentUnterminated => p!(pi: string(c.text().to_string())), + TriviaKind::ErrorCommentTooShort => p!(out, str("/*/")), + TriviaKind::ErrorCommentUnterminated => p!(out, string(c.text().to_string())), } } - - pi } diff --git a/cmds/jrsonnet-fmt/src/main.rs b/cmds/jrsonnet-fmt/src/main.rs index db115a3c..ad9e10ed 100644 --- a/cmds/jrsonnet-fmt/src/main.rs +++ b/cmds/jrsonnet-fmt/src/main.rs @@ -16,7 +16,7 @@ use jrsonnet_rowan_parser::{ Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix, Text, UnaryOperator, Visibility, }, - AstNode, AstToken, SyntaxToken, + AstNode, AstToken as _, SyntaxToken, }; use crate::{ @@ -30,7 +30,7 @@ mod comments; mod tests; pub trait Printable { - fn print(&self) -> PrintItems; + fn print(&self, out: &mut PrintItems); } macro_rules! pi { @@ -65,7 +65,7 @@ macro_rules! pi { pi!(@s; $o: $($t)*); }}; (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{ - $o.extend($expr.print()); + $expr.print($o); pi!(@s; $o: $($t)*); }}; (@s; $o:ident: items($expr:expr) $($t:tt)*) => {{ @@ -89,10 +89,7 @@ macro_rules! pi { (@s; $i:ident:) => {} } macro_rules! p { - (new: $($t:tt)*) => { - pi!(@i; $($t)*) - }; - ($o:ident: $($t:tt)*) => { + ($o:ident, $($t:tt)*) => { pi!(@s; $o: $($t)*) }; } @@ -103,205 +100,199 @@ impl
Printable for Option
where P: Printable, { - fn print(&self) -> PrintItems { + fn print(&self, out: &mut PrintItems) { if let Some(v) = self { - v.print() + v.print(out) } else { - p!(new: string( - format!( + p!( + out, + string(format!( "/*missing {}*/", type_name::
().replace("jrsonnet_rowan_parser::generated::nodes::", "")
- ),
- ))
+ ),)
+ )
}
}
}
impl Printable for SyntaxToken {
- fn print(&self) -> PrintItems {
- p!(new: string(self.to_string()))
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, string(self.to_string()))
}
}
impl Printable for Text {
- fn print(&self) -> PrintItems {
- p!(new: string(format!("{}", self)))
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, string(format!("{}", self)))
}
}
impl Printable for Number {
- fn print(&self) -> PrintItems {
- p!(new: string(format!("{}", self)))
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, string(format!("{}", self)))
}
}
impl Printable for Name {
- fn print(&self) -> PrintItems {
- p!(new: {self.ident_lit()})
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, { self.ident_lit() })
}
}
impl Printable for DestructRest {
- fn print(&self) -> PrintItems {
- let mut pi = p!(new: str("..."));
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("..."));
if let Some(name) = self.into() {
- p!(pi: {name});
+ p!(out, { name });
}
- pi
}
}
impl Printable for Destruct {
- fn print(&self) -> PrintItems {
- let mut pi = p!(new:);
+ fn print(&self, out: &mut PrintItems) {
match self {
Destruct::DestructFull(f) => {
- p!(pi: {f.name()})
+ p!(out, { f.name() })
}
- Destruct::DestructSkip(_) => p!(pi: str("?")),
+ Destruct::DestructSkip(_) => p!(out, str("?")),
Destruct::DestructArray(a) => {
- p!(pi: str("[") >i nl);
+ p!(out, str("[") >i nl);
for el in a.destruct_array_parts() {
match el {
DestructArrayPart::DestructArrayElement(e) => {
- p!(pi: {e.destruct()} str(",") nl)
+ p!(out, {e.destruct()} str(",") nl)
}
DestructArrayPart::DestructRest(d) => {
- p!(pi: {d} str(",") nl)
+ p!(out, {d} str(",") nl)
}
}
}
- p!(pi: {
- p!(pi: str("{") >i nl);
+ p!(out, str("{") >i nl);
for item in o.destruct_object_fields() {
- p!(pi: {item.field()});
+ p!(out, { item.field() });
if let Some(des) = item.destruct() {
- p!(pi: str(": ") {des})
+ p!(out, str(": ") {des})
}
if let Some(def) = item.expr() {
- p!(pi: str(" = ") {def});
+ p!(out, str(" = ") {def});
}
- p!(pi: str(",") nl);
+ p!(out, str(",") nl);
}
if let Some(rest) = o.destruct_rest() {
- p!(pi: {rest} nl)
+ p!(out, {rest} nl)
}
- p!(pi: PrintItems {
+ fn print(&self, out: &mut PrintItems) {
match self {
FieldName::FieldNameFixed(f) => {
if let Some(id) = f.id() {
- p!(new: {id})
+ p!(out, { id })
} else if let Some(str) = f.text() {
- p!(new: {str})
+ p!(out, { str })
} else {
- p!(new: str("/*missing FieldName*/"))
+ p!(out, str("/*missing FieldName*/"))
}
}
FieldName::FieldNameDynamic(d) => {
- p!(new: str("[") {d.expr()} str("]"))
+ p!(out, str("[") {d.expr()} str("]"))
}
}
}
}
impl Printable for Visibility {
- fn print(&self) -> PrintItems {
- p!(new: string(self.to_string()))
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, string(self.to_string()))
}
}
impl Printable for ObjLocal {
- fn print(&self) -> PrintItems {
- p!(new: str("local ") {self.bind()})
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("local ") {self.bind()})
}
}
impl Printable for Assertion {
- fn print(&self) -> PrintItems {
- let mut pi = p!(new: str("assert ") {self.condition()});
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("assert ") {self.condition()});
if self.colon_token().is_some() || self.message().is_some() {
- p!(pi: str(": ") {self.message()})
+ p!(out, str(": ") {self.message()})
}
- pi
}
}
impl Printable for ParamsDesc {
- fn print(&self) -> PrintItems {
- let mut pi = p!(new: str("(") >i nl);
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("(") >i nl);
for param in self.params() {
- p!(pi: {param.destruct()});
+ p!(out, { param.destruct() });
if param.assign_token().is_some() || param.expr().is_some() {
- p!(pi: str(" = ") {param.expr()})
+ p!(out, str(" = ") {param.expr()})
}
- p!(pi: str(",") nl)
+ p!(out, str(",") nl)
}
- p!(pi: PrintItems {
- let mut pi = p!(new: str("(") >i nl);
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("(") >i nl);
for arg in self.args() {
if arg.name().is_some() || arg.assign_token().is_some() {
- p!(pi: {arg.name()} str(" = "));
+ p!(out, {arg.name()} str(" = "));
}
- p!(pi: {arg.expr()} str(",") nl)
+ p!(out, {arg.expr()} str(",") nl)
}
- p!(pi: PrintItems {
- let mut pi = p!(new: str("["));
+ fn print(&self, out: &mut PrintItems) {
+ p!(out, str("["));
if self.from().is_some() {
- p!(pi: {self.from()});
+ p!(out, { self.from() });
}
- p!(pi: str(":"));
+ p!(out, str(":"));
if self.end().is_some() {
- p!(pi: {self.end().map(|e|e.expr())})
+ p!(out, { self.end().map(|e| e.expr()) })
}
// Keep only one : in case if we don't need step
if self.step().is_some() {
- p!(pi: str(":") {self.step().map(|e|e.expr())});
+ p!(out, str(":") {self.step().map(|e|e.expr())});
}
- p!(pi: str("]"));
- pi
+ p!(out, str("]"));
}
}
impl Printable for Member {
- fn print(&self) -> PrintItems {
+ fn print(&self, out: &mut PrintItems) {
match self {
Member::MemberBindStmt(b) => {
- p!(new: {b.obj_local()})
+ p!(out, { b.obj_local() })
}
Member::MemberAssertStmt(ass) => {
- p!(new: {ass.assertion()})
+ p!(out, { ass.assertion() })
}
Member::MemberFieldNormal(n) => {
- p!(new: {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})
+ p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})
}
Member::MemberFieldMethod(m) => {
- p!(new: {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})
+ p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})
}
}
}
}
impl Printable for ObjBody {
- fn print(&self) -> PrintItems {
+ fn print(&self, out: &mut PrintItems) {
match self {
ObjBody::ObjBodyComp(l) => {
let (children, mut end_comments) = children_between::