git.delta.rocks / jrsonnet / refs/commits / 8193aabb1831

difftreelog

refactor remove p!(new:) constructor from macros

Yaroslav Bolyukin2024-03-03parent: #da1c5af.patch.diff
in: master

2 files changed

modifiedcmds/jrsonnet-fmt/src/comments.rsdiffbeforeafterboth
--- a/cmds/jrsonnet-fmt/src/comments.rs
+++ b/cmds/jrsonnet-fmt/src/comments.rs
@@ -12,22 +12,19 @@
 	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 @@
 				}
 				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 @@
 							.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 @@
 			// ```
 			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
 }
modifiedcmds/jrsonnet-fmt/src/main.rsdiffbeforeafterboth
16 Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix, Text,16 Name, Number, ObjBody, ObjLocal, ParamsDesc, SliceDesc, SourceFile, Stmt, Suffix, Text,
17 UnaryOperator, Visibility,17 UnaryOperator, Visibility,
18 },18 },
19 AstNode, AstToken, SyntaxToken,19 AstNode, AstToken as _, SyntaxToken,
20};20};
2121
22use crate::{22use crate::{
30mod tests;30mod tests;
3131
32pub trait Printable {32pub trait Printable {
33 fn print(&self) -> PrintItems;33 fn print(&self, out: &mut PrintItems);
34}34}
3535
36macro_rules! pi {36macro_rules! pi {
65 pi!(@s; $o: $($t)*);65 pi!(@s; $o: $($t)*);
66 }};66 }};
67 (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{67 (@s; $o:ident: {$expr:expr} $($t:tt)*) => {{
68 $o.extend($expr.print());68 $expr.print($o);
69 pi!(@s; $o: $($t)*);69 pi!(@s; $o: $($t)*);
70 }};70 }};
71 (@s; $o:ident: items($expr:expr) $($t:tt)*) => {{71 (@s; $o:ident: items($expr:expr) $($t:tt)*) => {{
89 (@s; $i:ident:) => {}89 (@s; $i:ident:) => {}
90}90}
91macro_rules! p {91macro_rules! p {
92 (new: $($t:tt)*) => {92 ($o:ident, $($t:tt)*) => {
93 pi!(@i; $($t)*)
94 };
95 ($o:ident: $($t:tt)*) => {
96 pi!(@s; $o: $($t)*)93 pi!(@s; $o: $($t)*)
97 };94 };
98}95}
103where100where
104 P: Printable,101 P: Printable,
105{102{
106 fn print(&self) -> PrintItems {103 fn print(&self, out: &mut PrintItems) {
107 if let Some(v) = self {104 if let Some(v) = self {
108 v.print()105 v.print(out)
109 } else {106 } else {
110 p!(new: string(107 p!(
111 format!(108 out,
109 string(format!(
112 "/*missing {}*/",110 "/*missing {}*/",
113 type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")111 type_name::<P>().replace("jrsonnet_rowan_parser::generated::nodes::", "")
114 ),112 ),)
115 ))113 )
116 }114 }
117 }115 }
118}116}
119117
120impl Printable for SyntaxToken {118impl Printable for SyntaxToken {
121 fn print(&self) -> PrintItems {119 fn print(&self, out: &mut PrintItems) {
122 p!(new: string(self.to_string()))120 p!(out, string(self.to_string()))
123 }121 }
124}122}
125123
126impl Printable for Text {124impl Printable for Text {
127 fn print(&self) -> PrintItems {125 fn print(&self, out: &mut PrintItems) {
128 p!(new: string(format!("{}", self)))126 p!(out, string(format!("{}", self)))
129 }127 }
130}128}
131impl Printable for Number {129impl Printable for Number {
132 fn print(&self) -> PrintItems {130 fn print(&self, out: &mut PrintItems) {
133 p!(new: string(format!("{}", self)))131 p!(out, string(format!("{}", self)))
134 }132 }
135}133}
136134
137impl Printable for Name {135impl Printable for Name {
138 fn print(&self) -> PrintItems {136 fn print(&self, out: &mut PrintItems) {
139 p!(new: {self.ident_lit()})137 p!(out, { self.ident_lit() })
140 }138 }
141}139}
142140
143impl Printable for DestructRest {141impl Printable for DestructRest {
144 fn print(&self) -> PrintItems {142 fn print(&self, out: &mut PrintItems) {
145 let mut pi = p!(new: str("..."));143 p!(out, str("..."));
146 if let Some(name) = self.into() {144 if let Some(name) = self.into() {
147 p!(pi: {name});145 p!(out, { name });
148 }146 }
149 pi
150 }147 }
151}148}
152149
153impl Printable for Destruct {150impl Printable for Destruct {
154 fn print(&self) -> PrintItems {151 fn print(&self, out: &mut PrintItems) {
155 let mut pi = p!(new:);
156 match self {152 match self {
157 Destruct::DestructFull(f) => {153 Destruct::DestructFull(f) => {
158 p!(pi: {f.name()})154 p!(out, { f.name() })
159 }155 }
160 Destruct::DestructSkip(_) => p!(pi: str("?")),156 Destruct::DestructSkip(_) => p!(out, str("?")),
161 Destruct::DestructArray(a) => {157 Destruct::DestructArray(a) => {
162 p!(pi: str("[") >i nl);158 p!(out, str("[") >i nl);
163 for el in a.destruct_array_parts() {159 for el in a.destruct_array_parts() {
164 match el {160 match el {
165 DestructArrayPart::DestructArrayElement(e) => {161 DestructArrayPart::DestructArrayElement(e) => {
166 p!(pi: {e.destruct()} str(",") nl)162 p!(out, {e.destruct()} str(",") nl)
167 }163 }
168 DestructArrayPart::DestructRest(d) => {164 DestructArrayPart::DestructRest(d) => {
169 p!(pi: {d} str(",") nl)165 p!(out, {d} str(",") nl)
170 }166 }
171 }167 }
172 }168 }
173 p!(pi: <i str("]"));169 p!(out, <i str("]"));
174 }170 }
175 Destruct::DestructObject(o) => {171 Destruct::DestructObject(o) => {
176 p!(pi: str("{") >i nl);172 p!(out, str("{") >i nl);
177 for item in o.destruct_object_fields() {173 for item in o.destruct_object_fields() {
178 p!(pi: {item.field()});174 p!(out, { item.field() });
179 if let Some(des) = item.destruct() {175 if let Some(des) = item.destruct() {
180 p!(pi: str(": ") {des})176 p!(out, str(": ") {des})
181 }177 }
182 if let Some(def) = item.expr() {178 if let Some(def) = item.expr() {
183 p!(pi: str(" = ") {def});179 p!(out, str(" = ") {def});
184 }180 }
185 p!(pi: str(",") nl);181 p!(out, str(",") nl);
186 }182 }
187 if let Some(rest) = o.destruct_rest() {183 if let Some(rest) = o.destruct_rest() {
188 p!(pi: {rest} nl)184 p!(out, {rest} nl)
189 }185 }
190 p!(pi: <i str("}"));186 p!(out, <i str("}"));
191 }187 }
192 }188 }
193 pi
194 }189 }
195}190}
196191
197impl Printable for FieldName {192impl Printable for FieldName {
198 fn print(&self) -> PrintItems {193 fn print(&self, out: &mut PrintItems) {
199 match self {194 match self {
200 FieldName::FieldNameFixed(f) => {195 FieldName::FieldNameFixed(f) => {
201 if let Some(id) = f.id() {196 if let Some(id) = f.id() {
202 p!(new: {id})197 p!(out, { id })
203 } else if let Some(str) = f.text() {198 } else if let Some(str) = f.text() {
204 p!(new: {str})199 p!(out, { str })
205 } else {200 } else {
206 p!(new: str("/*missing FieldName*/"))201 p!(out, str("/*missing FieldName*/"))
207 }202 }
208 }203 }
209 FieldName::FieldNameDynamic(d) => {204 FieldName::FieldNameDynamic(d) => {
210 p!(new: str("[") {d.expr()} str("]"))205 p!(out, str("[") {d.expr()} str("]"))
211 }206 }
212 }207 }
213 }208 }
214}209}
215210
216impl Printable for Visibility {211impl Printable for Visibility {
217 fn print(&self) -> PrintItems {212 fn print(&self, out: &mut PrintItems) {
218 p!(new: string(self.to_string()))213 p!(out, string(self.to_string()))
219 }214 }
220}215}
221216
222impl Printable for ObjLocal {217impl Printable for ObjLocal {
223 fn print(&self) -> PrintItems {218 fn print(&self, out: &mut PrintItems) {
224 p!(new: str("local ") {self.bind()})219 p!(out, str("local ") {self.bind()})
225 }220 }
226}221}
227222
228impl Printable for Assertion {223impl Printable for Assertion {
229 fn print(&self) -> PrintItems {224 fn print(&self, out: &mut PrintItems) {
230 let mut pi = p!(new: str("assert ") {self.condition()});225 p!(out, str("assert ") {self.condition()});
231 if self.colon_token().is_some() || self.message().is_some() {226 if self.colon_token().is_some() || self.message().is_some() {
232 p!(pi: str(": ") {self.message()})227 p!(out, str(": ") {self.message()})
233 }228 }
234 pi
235 }229 }
236}230}
237231
238impl Printable for ParamsDesc {232impl Printable for ParamsDesc {
239 fn print(&self) -> PrintItems {233 fn print(&self, out: &mut PrintItems) {
240 let mut pi = p!(new: str("(") >i nl);234 p!(out, str("(") >i nl);
241 for param in self.params() {235 for param in self.params() {
242 p!(pi: {param.destruct()});236 p!(out, { param.destruct() });
243 if param.assign_token().is_some() || param.expr().is_some() {237 if param.assign_token().is_some() || param.expr().is_some() {
244 p!(pi: str(" = ") {param.expr()})238 p!(out, str(" = ") {param.expr()})
245 }239 }
246 p!(pi: str(",") nl)240 p!(out, str(",") nl)
247 }241 }
248 p!(pi: <i str(")"));242 p!(out, <i str(")"));
249 pi
250 }243 }
251}244}
252impl Printable for ArgsDesc {245impl Printable for ArgsDesc {
253 fn print(&self) -> PrintItems {246 fn print(&self, out: &mut PrintItems) {
254 let mut pi = p!(new: str("(") >i nl);247 p!(out, str("(") >i nl);
255 for arg in self.args() {248 for arg in self.args() {
256 if arg.name().is_some() || arg.assign_token().is_some() {249 if arg.name().is_some() || arg.assign_token().is_some() {
257 p!(pi: {arg.name()} str(" = "));250 p!(out, {arg.name()} str(" = "));
258 }251 }
259 p!(pi: {arg.expr()} str(",") nl)252 p!(out, {arg.expr()} str(",") nl)
260 }253 }
261 p!(pi: <i str(")"));254 p!(out, <i str(")"));
262 pi
263 }255 }
264}256}
265impl Printable for SliceDesc {257impl Printable for SliceDesc {
266 fn print(&self) -> PrintItems {258 fn print(&self, out: &mut PrintItems) {
267 let mut pi = p!(new: str("["));259 p!(out, str("["));
268 if self.from().is_some() {260 if self.from().is_some() {
269 p!(pi: {self.from()});261 p!(out, { self.from() });
270 }262 }
271 p!(pi: str(":"));263 p!(out, str(":"));
272 if self.end().is_some() {264 if self.end().is_some() {
273 p!(pi: {self.end().map(|e|e.expr())})265 p!(out, { self.end().map(|e| e.expr()) })
274 }266 }
275 // Keep only one : in case if we don't need step267 // Keep only one : in case if we don't need step
276 if self.step().is_some() {268 if self.step().is_some() {
277 p!(pi: str(":") {self.step().map(|e|e.expr())});269 p!(out, str(":") {self.step().map(|e|e.expr())});
278 }270 }
279 p!(pi: str("]"));271 p!(out, str("]"));
280 pi
281 }272 }
282}273}
283274
284impl Printable for Member {275impl Printable for Member {
285 fn print(&self) -> PrintItems {276 fn print(&self, out: &mut PrintItems) {
286 match self {277 match self {
287 Member::MemberBindStmt(b) => {278 Member::MemberBindStmt(b) => {
288 p!(new: {b.obj_local()})279 p!(out, { b.obj_local() })
289 }280 }
290 Member::MemberAssertStmt(ass) => {281 Member::MemberAssertStmt(ass) => {
291 p!(new: {ass.assertion()})282 p!(out, { ass.assertion() })
292 }283 }
293 Member::MemberFieldNormal(n) => {284 Member::MemberFieldNormal(n) => {
294 p!(new: {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})285 p!(out, {n.field_name()} if(n.plus_token().is_some())({n.plus_token()}) {n.visibility()} str(" ") {n.expr()})
295 }286 }
296 Member::MemberFieldMethod(m) => {287 Member::MemberFieldMethod(m) => {
297 p!(new: {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})288 p!(out, {m.field_name()} {m.params_desc()} {m.visibility()} str(" ") {m.expr()})
298 }289 }
299 }290 }
300 }291 }
301}292}
302293
303impl Printable for ObjBody {294impl Printable for ObjBody {
304 fn print(&self) -> PrintItems {295 fn print(&self, out: &mut PrintItems) {
305 match self {296 match self {
306 ObjBody::ObjBodyComp(l) => {297 ObjBody::ObjBodyComp(l) => {
307 let (children, mut end_comments) = children_between::<Member>(298 let (children, mut end_comments) = children_between::<Member>(
318 None,309 None,
319 );310 );
320 let trailing_for_comp = end_comments.extract_trailing();311 let trailing_for_comp = end_comments.extract_trailing();
321 let mut pi = p!(new: str("{") >i nl);312 p!(out, str("{") >i nl);
322 for mem in children.into_iter() {313 for mem in children.into_iter() {
323 if mem.should_start_with_newline {314 if mem.should_start_with_newline {
324 p!(pi: nl);315 p!(out, nl);
325 }316 }
326 p!(pi: items(format_comments(&mem.before_trivia, CommentLocation::AboveItem)));317 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);
327 p!(pi: {mem.value} str(","));318 p!(out, {mem.value} str(","));
328 p!(pi: items(format_comments(&mem.inline_trivia, CommentLocation::ItemInline)));319 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);
329 p!(pi: nl)320 p!(out, nl)
330 }321 }
331322
332 if end_comments.should_start_with_newline {323 if end_comments.should_start_with_newline {
333 p!(pi: nl);324 p!(out, nl);
334 }325 }
335 p!(pi: items(format_comments(&end_comments.trivia, CommentLocation::EndOfItems)));326 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);
336327
337 let (compspecs, end_comments) = children_between::<CompSpec>(328 let (compspecs, end_comments) = children_between::<CompSpec>(
338 l.syntax().clone(),329 l.syntax().clone(),
347 );338 );
348 for mem in compspecs.into_iter() {339 for mem in compspecs.into_iter() {
349 if mem.should_start_with_newline {340 if mem.should_start_with_newline {
350 p!(pi: nl);341 p!(out, nl);
351 }342 }
352 p!(pi: items(format_comments(&mem.before_trivia, CommentLocation::AboveItem)));343 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);
353 p!(pi: {mem.value});344 p!(out, { mem.value });
354 p!(pi: items(format_comments(&mem.inline_trivia, CommentLocation::ItemInline)));345 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);
355 }346 }
356 if end_comments.should_start_with_newline {347 if end_comments.should_start_with_newline {
357 p!(pi: nl);348 p!(out, nl);
358 }349 }
359 p!(pi: items(format_comments(&end_comments.trivia, CommentLocation::EndOfItems)));350 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);
360351
361 p!(pi: nl <i str("}"));352 p!(out, nl <i str("}"));
362 pi
363 }353 }
364 ObjBody::ObjBodyMemberList(l) => {354 ObjBody::ObjBodyMemberList(l) => {
365 let (children, end_comments) = children_between::<Member>(355 let (children, end_comments) = children_between::<Member>(
369 None,359 None,
370 );360 );
371 if children.is_empty() && end_comments.is_empty() {361 if children.is_empty() && end_comments.is_empty() {
372 return p!(new: str("{ }"));362 p!(out, str("{ }"));
363 return;
373 }364 }
374 let mut pi = p!(new: str("{") >i nl);365 p!(out, str("{") >i nl);
375 for (i, mem) in children.into_iter().enumerate() {366 for (i, mem) in children.into_iter().enumerate() {
376 if mem.should_start_with_newline && i != 0 {367 if mem.should_start_with_newline && i != 0 {
377 p!(pi: nl);368 p!(out, nl);
378 }369 }
379 p!(pi: items(format_comments(&mem.before_trivia, CommentLocation::AboveItem)));370 format_comments(&mem.before_trivia, CommentLocation::AboveItem, out);
380 p!(pi: {mem.value} str(","));371 p!(out, {mem.value} str(","));
381 p!(pi: items(format_comments(&mem.inline_trivia, CommentLocation::ItemInline)));372 format_comments(&mem.inline_trivia, CommentLocation::ItemInline, out);
382 p!(pi: nl)373 p!(out, nl)
383 }374 }
384375
385 if end_comments.should_start_with_newline {376 if end_comments.should_start_with_newline {
386 p!(pi: nl);377 p!(out, nl);
387 }378 }
388 p!(pi: items(format_comments(&end_comments.trivia, CommentLocation::EndOfItems)));379 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);
389 p!(pi: <i str("}"));380 p!(out, <i str("}"));
390 pi
391 }381 }
392 }382 }
393 }383 }
394}384}
395impl Printable for UnaryOperator {385impl Printable for UnaryOperator {
396 fn print(&self) -> PrintItems {386 fn print(&self, out: &mut PrintItems) {
397 p!(new: string(self.text().to_string()))387 p!(out, string(self.text().to_string()))
398 }388 }
399}389}
400impl Printable for BinaryOperator {390impl Printable for BinaryOperator {
401 fn print(&self) -> PrintItems {391 fn print(&self, out: &mut PrintItems) {
402 p!(new: string(self.text().to_string()))392 p!(out, string(self.text().to_string()))
403 }393 }
404}394}
405impl Printable for Bind {395impl Printable for Bind {
406 fn print(&self) -> PrintItems {396 fn print(&self, out: &mut PrintItems) {
407 match self {397 match self {
408 Bind::BindDestruct(d) => {398 Bind::BindDestruct(d) => {
409 p!(new: {d.into()} str(" = ") {d.value()})399 p!(out, {d.into()} str(" = ") {d.value()})
410 }400 }
411 Bind::BindFunction(f) => {401 Bind::BindFunction(f) => {
412 p!(new: {f.name()} {f.params()} str(" = ") {f.value()})402 p!(out, {f.name()} {f.params()} str(" = ") {f.value()})
413 }403 }
414 }404 }
415 }405 }
416}406}
417impl Printable for Literal {407impl Printable for Literal {
418 fn print(&self) -> PrintItems {408 fn print(&self, out: &mut PrintItems) {
419 p!(new: string(self.syntax().to_string()))409 p!(out, string(self.syntax().to_string()))
420 }410 }
421}411}
422impl Printable for ImportKind {412impl Printable for ImportKind {
423 fn print(&self) -> PrintItems {413 fn print(&self, out: &mut PrintItems) {
424 p!(new: string(self.syntax().to_string()))414 p!(out, string(self.syntax().to_string()))
425 }415 }
426}416}
427impl Printable for ForSpec {417impl Printable for ForSpec {
428 fn print(&self) -> PrintItems {418 fn print(&self, out: &mut PrintItems) {
429 p!(new: str("for ") {self.bind()} str(" in ") {self.expr()})419 p!(out, str("for ") {self.bind()} str(" in ") {self.expr()})
430 }420 }
431}421}
432impl Printable for IfSpec {422impl Printable for IfSpec {
433 fn print(&self) -> PrintItems {423 fn print(&self, out: &mut PrintItems) {
434 p!(new: str("if ") {self.expr()})424 p!(out, str("if ") {self.expr()})
435 }425 }
436}426}
437impl Printable for CompSpec {427impl Printable for CompSpec {
438 fn print(&self) -> PrintItems {428 fn print(&self, out: &mut PrintItems) {
439 match self {429 match self {
440 CompSpec::ForSpec(f) => f.print(),430 CompSpec::ForSpec(f) => f.print(out),
441 CompSpec::IfSpec(i) => i.print(),431 CompSpec::IfSpec(i) => i.print(out),
442 }432 }
443 }433 }
444}434}
445impl Printable for Expr {435impl Printable for Expr {
446 fn print(&self) -> PrintItems {436 fn print(&self, out: &mut PrintItems) {
447 let mut o = p!(new:);
448 let (stmts, ending) = children_between::<Stmt>(437 let (stmts, _ending) = children_between::<Stmt>(
449 self.syntax().clone(),438 self.syntax().clone(),
450 None,439 None,
451 self.expr_base()440 self.expr_base()
457 None,446 None,
458 );447 );
459 for stmt in stmts {448 for stmt in stmts {
460 p!(o: {stmt.value});449 p!(out, { stmt.value });
461 }450 }
462 p!(o: {self.expr_base()});451 p!(out, { self.expr_base() });
463 let (suffixes, ending) = children_between::<Suffix>(452 let (suffixes, _ending) = children_between::<Suffix>(
464 self.syntax().clone(),453 self.syntax().clone(),
465 self.expr_base()454 self.expr_base()
466 .as_ref()455 .as_ref()
472 None,461 None,
473 );462 );
474 for suffix in suffixes {463 for suffix in suffixes {
475 p!(o: {suffix.value});464 p!(out, { suffix.value });
476 }465 }
477 o
478 }466 }
479}467}
480impl Printable for Suffix {468impl Printable for Suffix {
481 fn print(&self) -> PrintItems {469 fn print(&self, out: &mut PrintItems) {
482 let mut o = p!(new:);
483 match self {470 match self {
484 Suffix::SuffixIndex(i) => {471 Suffix::SuffixIndex(i) => {
485 if i.question_mark_token().is_some() {472 if i.question_mark_token().is_some() {
486 p!(o: str("?"));473 p!(out, str("?"));
487 }474 }
488 p!(o: str(".") {i.index()});475 p!(out, str(".") {i.index()});
489 }476 }
490 Suffix::SuffixIndexExpr(e) => {477 Suffix::SuffixIndexExpr(e) => {
491 if e.question_mark_token().is_some() {478 if e.question_mark_token().is_some() {
492 p!(o: str(".?"));479 p!(out, str(".?"));
493 }480 }
494 p!(o: str("[") {e.index()} str("]"))481 p!(out, str("[") {e.index()} str("]"))
495 }482 }
496 Suffix::SuffixSlice(d) => {483 Suffix::SuffixSlice(d) => {
497 p!(o: {d.slice_desc()})484 p!(out, { d.slice_desc() })
498 }485 }
499 Suffix::SuffixApply(a) => {486 Suffix::SuffixApply(a) => {
500 p!(o: {a.args_desc()})487 p!(out, { a.args_desc() })
501 }488 }
502 }489 }
503 o
504 }490 }
505}491}
506impl Printable for Stmt {492impl Printable for Stmt {
507 fn print(&self) -> PrintItems {493 fn print(&self, out: &mut PrintItems) {
508 match self {494 match self {
509 Stmt::StmtLocal(l) => {495 Stmt::StmtLocal(l) => {
510 let mut pi = p!(new:);
511 let (binds, end_comments) = children_between::<Bind>(496 let (binds, end_comments) = children_between::<Bind>(
512 l.syntax().clone(),497 l.syntax().clone(),
513 l.local_kw_token().map(Into::into).as_ref(),498 l.local_kw_token().map(Into::into).as_ref(),
516 );501 );
517 if binds.len() == 1 {502 if binds.len() == 1 {
518 let bind = &binds[0];503 let bind = &binds[0];
519 p!(pi: items(format_comments(&bind.before_trivia, CommentLocation::AboveItem)));504 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);
520 p!(pi: str("local ") {bind.value});505 p!(out, str("local ") {bind.value});
521 // TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?506 // TODO: keep end_comments, child.inline_trivia somehow, force multiple locals formatting in case of presence?
522 } else {507 } else {
523 p!(pi: str("local") >i nl);508 p!(out,str("local") >i nl);
524 for bind in binds {509 for bind in binds {
525 if bind.should_start_with_newline {510 if bind.should_start_with_newline {
526 p!(pi: nl);511 p!(out, nl);
527 }512 }
528 p!(pi: items(format_comments(&bind.before_trivia, CommentLocation::AboveItem)));513 format_comments(&bind.before_trivia, CommentLocation::AboveItem, out);
529 p!(pi: {bind.value} str(","));514 p!(out, {bind.value} str(","));
530 p!(pi: items(format_comments(&bind.inline_trivia, CommentLocation::ItemInline)) nl);515 format_comments(&bind.inline_trivia, CommentLocation::ItemInline, out);
531 }516 }
532 if end_comments.should_start_with_newline {517 if end_comments.should_start_with_newline {
533 p!(pi: nl)518 p!(out, nl)
534 }519 }
535 p!(pi: items(format_comments(&end_comments.trivia, CommentLocation::EndOfItems)));520 format_comments(&end_comments.trivia, CommentLocation::EndOfItems, out);
536 p!(pi: <i);521 p!(out,<i);
537 }522 }
538 p!(pi: str(";") nl);523 p!(out,str(";") nl);
539 pi
540 }524 }
541 Stmt::StmtAssert(a) => {525 Stmt::StmtAssert(a) => {
542 p!(new: {a.assertion()} str(";") nl)526 p!(out, {a.assertion()} str(";") nl)
543 }527 }
544 }528 }
545 }529 }
546}530}
547impl Printable for ExprBase {531impl Printable for ExprBase {
548 fn print(&self) -> PrintItems {532 fn print(&self, out: &mut PrintItems) {
549 match self {533 match self {
550 Self::ExprBinary(b) => {534 Self::ExprBinary(b) => {
551 p!(new: {b.lhs_work()} str(" ") {b.binary_operator()} str(" ") {b.rhs_work()})535 p!(out, {b.lhs_work()} str(" ") {b.binary_operator()} str(" ") {b.rhs_work()})
552 }536 }
553 Self::ExprUnary(u) => p!(new: {u.unary_operator()} {u.rhs()}),537 Self::ExprUnary(u) => p!(out, {u.unary_operator()} {u.rhs()}),
554 // Self::ExprSlice(s) => {538 // Self::ExprSlice(s) => {
555 // p!(new: {s.expr()} {s.slice_desc()})539 // p!(new: {s.expr()} {s.slice_desc()})
556 // }540 // }
561 // Self::ExprApply(a) => {545 // Self::ExprApply(a) => {
562 // let mut pi = p!(new: {a.expr()} {a.args_desc()});546 // let mut pi = p!(new: {a.expr()} {a.args_desc()});
563 // if a.tailstrict_kw_token().is_some() {547 // if a.tailstrict_kw_token().is_some() {
564 // p!(pi: str(" tailstrict"));548 // p!(out,str(" tailstrict"));
565 // }549 // }
566 // pi550 // pi
567 // }551 // }
568 Self::ExprObjExtend(ex) => {552 Self::ExprObjExtend(ex) => {
569 p!(new: {ex.lhs_work()} str(" ") {ex.rhs_work()})553 p!(out, {ex.lhs_work()} str(" ") {ex.rhs_work()})
570 }554 }
571 Self::ExprParened(p) => {555 Self::ExprParened(p) => {
572 p!(new: str("(") {p.expr()} str(")"))556 p!(out, str("(") {p.expr()} str(")"))
573 }557 }
574 Self::ExprString(s) => p!(new: {s.text()}),558 Self::ExprString(s) => p!(out, { s.text() }),
575 Self::ExprNumber(n) => p!(new: {n.number()}),559 Self::ExprNumber(n) => p!(out, { n.number() }),
576 Self::ExprArray(a) => {560 Self::ExprArray(a) => {
577 let mut pi = p!(new: str("[") >i nl);561 p!(out, str("[") >i nl);
578 for el in a.exprs() {562 for el in a.exprs() {
579 p!(pi: {el} str(",") nl);563 p!(out, {el} str(",") nl);
580 }564 }
581 p!(pi: <i str("]"));565 p!(out, <i str("]"));
582 pi
583 }566 }
584 Self::ExprObject(obj) => {567 Self::ExprObject(obj) => {
585 p!(new: {obj.obj_body()})568 p!(out, { obj.obj_body() })
586 }569 }
587 Self::ExprArrayComp(arr) => {570 Self::ExprArrayComp(arr) => {
588 let mut pi = p!(new: str("[") {arr.expr()});571 p!(out, str("[") {arr.expr()});
589 for spec in arr.comp_specs() {572 for spec in arr.comp_specs() {
590 p!(pi: str(" ") {spec});573 p!(out, str(" ") {spec});
591 }574 }
592 p!(pi: str("]"));575 p!(out, str("]"));
593 pi
594 }576 }
595 Self::ExprImport(v) => {577 Self::ExprImport(v) => {
596 p!(new: {v.import_kind()} str(" ") {v.text()})578 p!(out, {v.import_kind()} str(" ") {v.text()})
597 }579 }
598 Self::ExprVar(n) => p!(new: {n.name()}),580 Self::ExprVar(n) => p!(out, { n.name() }),
599 // Self::ExprLocal(l) => {581 // Self::ExprLocal(l) => {
600 // }582 // }
601 Self::ExprIfThenElse(ite) => {583 Self::ExprIfThenElse(ite) => {
602 let mut pi =584 p!(out, str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});
603 p!(new: str("if ") {ite.cond()} str(" then ") {ite.then().map(|t| t.expr())});
604 if ite.else_kw_token().is_some() || ite.else_().is_some() {585 if ite.else_kw_token().is_some() || ite.else_().is_some() {
605 p!(pi: str(" else ") {ite.else_().map(|t| t.expr())})586 p!(out, str(" else ") {ite.else_().map(|t| t.expr())})
606 }587 }
607 pi
608 }588 }
609 Self::ExprFunction(f) => p!(new: str("function") {f.params_desc()} nl {f.expr()}),589 Self::ExprFunction(f) => p!(out, str("function") {f.params_desc()} nl {f.expr()}),
610 // Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),590 // Self::ExprAssert(a) => p!(new: {a.assertion()} str("; ") {a.expr()}),
611 Self::ExprError(e) => p!(new: str("error ") {e.expr()}),591 Self::ExprError(e) => p!(out, str("error ") {e.expr()}),
612 Self::ExprLiteral(l) => {592 Self::ExprLiteral(l) => {
613 p!(new: {l.literal()})593 p!(out, { l.literal() })
614 }594 }
615 }595 }
616 }596 }
617}597}
618598
619impl Printable for SourceFile {599impl Printable for SourceFile {
620 fn print(&self) -> PrintItems {600 fn print(&self, out: &mut PrintItems) {
621 let mut pi = p!(new:);
622 let before = trivia_before(601 let before = trivia_before(
623 self.syntax().clone(),602 self.syntax().clone(),
624 self.expr()603 self.expr()
633 .map(Into::into)612 .map(Into::into)
634 .as_ref(),613 .as_ref(),
635 );614 );
636 p!(pi: items(format_comments(&before, CommentLocation::AboveItem)));615 format_comments(&before, CommentLocation::AboveItem, out);
637 p!(pi: {self.expr()} nl);616 p!(out, {self.expr()} nl);
638 p!(pi: items(format_comments(&after, CommentLocation::EndOfItems)));617 format_comments(&after, CommentLocation::EndOfItems, out)
639 pi
640 }618 }
641}619}
642620
671 return None;649 return None;
672 }650 }
673 Some(dprint_core::formatting::format(651 Some(dprint_core::formatting::format(
674 || parsed.print(),652 || {
653 let mut out = PrintItems::new();
654 parsed.print(&mut out);
655 out
656 },
675 PrintOptions {657 PrintOptions {
676 indent_width: if opts.indent == 0 {658 indent_width: if opts.indent == 0 {
677 // Reasonable max length for both 2 and 4 space sized tabs.659 // Reasonable max length for both 2 and 4 space sized tabs.
726 #[error("persist: {0}")]708 #[error("persist: {0}")]
727 Persist(#[from] tempfile::PersistError),709 Persist(#[from] tempfile::PersistError),
728 #[error("parsing failed, refusing to reformat corrupted input")]710 #[error("parsing failed, refusing to reformat corrupted input")]
729 ParseError,711 Parse,
730}712}
731713
732fn main_result() -> Result<(), Error> {714fn main_result() -> Result<(), Error> {
763 },745 },
764 },746 },
765 ) else {747 ) else {
766 return Err(Error::ParseError);748 return Err(Error::Parse);
767 };749 };
768 tmp = reformatted.trim().to_owned();750 tmp = reformatted.trim().to_owned();
769 if formatted == tmp {751 if formatted == tmp {