1use crate::{span::Spanned, syntax::*};
2use core::fmt;
3use std::fmt::{Display, Formatter};
4
5use itertools::Itertools;
6
7struct FormatFn<F: (Fn(&mut Formatter) -> fmt::Result)>(F);
9
10impl<F: Fn(&mut Formatter) -> fmt::Result> Display for FormatFn<F> {
11 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
12 (self.0)(f)
13 }
14}
15
16impl<T: Display> Display for Spanned<T> {
17 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
18 self.node().fmt(f)
19 }
20}
21
22struct Indent<T: Display>(pub T);
23
24impl<T: Display> Display for Indent<T> {
25 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
26 let indent = " ";
27 let inner_display = self.0.to_string();
28 let fmt = inner_display
29 .lines()
30 .format_with("\n", |l, f| f(&format_args!("{indent}{l}")));
31 write!(f, "{fmt}")?;
32 Ok(())
33 }
34}
35
36impl Display for TranslationUnit {
37 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
38 if !self.imports.is_empty() {
39 for import in &self.imports {
40 writeln!(f, "{import}\n")?;
41 }
42 }
43 if !self.global_directives.is_empty() {
44 let directives = self.global_directives.iter().format("\n");
45 write!(f, "{directives}\n\n")?;
46 }
47 let declarations = self
48 .global_declarations
49 .iter()
50 .filter(|decl| !matches!(decl.node(), GlobalDeclaration::Void))
51 .format("\n\n");
52 writeln!(f, "{declarations}")
53 }
54}
55
56impl Display for Ident {
57 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
58 write!(f, "{}", self.name())
59 }
60}
61
62impl Display for Visibility {
63 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
64 match self {
65 Visibility::Private => f.write_str("private"),
66 Visibility::Package => f.write_str("package"),
67 Visibility::Public => f.write_str("public"),
68 }
69 }
70}
71
72impl Display for ImportStatement {
73 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
74 write!(
75 f,
76 "{}{}",
77 fmt_attrs(&self.attributes, false),
78 fmt_visibility(self.visibility)
79 )?;
80 let content = &self.content;
81 if let Some(path) = &self.path {
82 write!(f, "import {path}::{content};")
83 } else {
84 write!(f, "import {content};")
85 }
86 }
87}
88
89impl Display for ModulePath {
90 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
91 match &self.origin {
92 PathOrigin::Absolute => write!(f, "package")?,
93 PathOrigin::Relative(0) => write!(f, "self")?,
94 PathOrigin::Relative(n) => write!(f, "{}", (0..*n).map(|_| "super").format("::"))?,
95 PathOrigin::Package(p) => write!(f, "{p}")?,
96 };
97 if !self.components.is_empty() {
98 write!(f, "::{}", self.components.iter().format("::"))?;
99 }
100 Ok(())
101 }
102}
103
104impl Display for Import {
105 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
106 if !self.path.is_empty() {
107 let path = self.path.iter().format("::");
108 write!(f, "{path}::")?;
109 }
110 let content = &self.content;
111 write!(f, "{content}")
112 }
113}
114
115impl Display for ImportContent {
116 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
117 match self {
118 ImportContent::Item(item) => {
119 write!(f, "{}", item.ident)?;
120 if let Some(rename) = &item.rename {
121 write!(f, " as {rename}")?;
122 }
123 Ok(())
124 }
125 ImportContent::Collection(coll) => {
126 let coll = coll.iter().format(", ");
127 write!(f, "{{ {coll} }}")
128 }
129 }
130 }
131}
132
133impl Display for GlobalDirective {
134 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
135 match self {
136 GlobalDirective::Diagnostic(print) => write!(f, "{print}"),
137 GlobalDirective::Enable(print) => write!(f, "{print}"),
138 GlobalDirective::Requires(print) => write!(f, "{print}"),
139 }
140 }
141}
142
143impl Display for DiagnosticDirective {
144 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
145 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
146 let severity = &self.severity;
147 let rule = &self.rule_name;
148 write!(f, "diagnostic ({severity}, {rule});")
149 }
150}
151
152impl Display for EnableDirective {
153 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
154 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
155 let exts = self.extensions.iter().format(", ");
156 write!(f, "enable {exts};")
157 }
158}
159
160impl Display for RequiresDirective {
161 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
162 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
163 let exts = self.extensions.iter().format(", ");
164 write!(f, "requires {exts};")
165 }
166}
167
168impl Display for GlobalDeclaration {
169 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
170 match self {
171 GlobalDeclaration::Void => write!(f, ";"),
172 GlobalDeclaration::Declaration(print) => write!(f, "{print}"),
173 GlobalDeclaration::TypeAlias(print) => write!(f, "{print}"),
174 GlobalDeclaration::Struct(print) => write!(f, "{print}"),
175 GlobalDeclaration::Function(print) => write!(f, "{print}"),
176 GlobalDeclaration::ConstAssert(print) => write!(f, "{print}"),
177 GlobalDeclaration::Compound(print) => write!(f, "{print}"),
178 }
179 }
180}
181
182impl Display for Declaration {
183 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
184 write!(
185 f,
186 "{}{}",
187 fmt_attrs(&self.attributes, false),
188 fmt_visibility(self.visibility)
189 )?;
190 let kind = &self.kind;
191 let name = &self.ident;
192 let ty = self
193 .ty
194 .iter()
195 .format_with("", |ty, f| f(&format_args!(": {ty}")));
196 let init = self
197 .initializer
198 .iter()
199 .format_with("", |ty, f| f(&format_args!(" = {ty}")));
200 write!(f, "{kind} {name}{ty}{init};")
201 }
202}
203
204impl Display for DeclarationKind {
205 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
206 match self {
207 Self::Const => write!(f, "const"),
208 Self::Override => write!(f, "override"),
209 Self::Let => write!(f, "let"),
210 Self::Var(None) => write!(f, "var"),
211 Self::Var(Some((a_s, None))) => write!(f, "var<{a_s}>"),
212 Self::Var(Some((a_s, Some(a_m)))) => write!(f, "var<{a_s}, {a_m}>"),
213 }
214 }
215}
216
217impl Display for TypeAlias {
218 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
219 write!(
220 f,
221 "{}{}",
222 fmt_attrs(&self.attributes, false),
223 fmt_visibility(self.visibility)
224 )?;
225 let name = &self.ident;
226 let ty = &self.ty;
227 write!(f, "alias {name} = {ty};")
228 }
229}
230
231impl Display for Struct {
232 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
233 write!(
234 f,
235 "{}{}",
236 fmt_attrs(&self.attributes, false),
237 fmt_visibility(self.visibility)
238 )?;
239 let name = &self.ident;
240 let members = Indent(self.members.iter().format(",\n"));
241 write!(f, "struct {name} {{\n{members}\n}}")
242 }
243}
244
245impl Display for StructMember {
246 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
247 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
248 let name = &self.ident;
249 let ty = &self.ty;
250 write!(f, "{name}: {ty}")
251 }
252}
253
254impl Display for Function {
255 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
256 write!(
257 f,
258 "{}{}",
259 fmt_attrs(&self.attributes, false),
260 fmt_visibility(self.visibility)
261 )?;
262 let name = &self.ident;
263 let params = self.parameters.iter().format(", ");
264 let ret_ty = self.return_type.iter().format_with("", |ty, f| {
265 f(&FormatFn(|f: &mut Formatter| {
266 write!(f, "-> ")?;
267 write!(f, "{}", fmt_attrs(&self.return_attributes, true))?;
268 write!(f, "{ty} ")?;
269 Ok(())
270 }))
271 });
272 let body = &self.body;
273 write!(f, "fn {name}({params}) {ret_ty}{body}")
274 }
275}
276
277impl Display for FormalParameter {
278 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
279 write!(f, "{}", fmt_attrs(&self.attributes, true))?;
280 let name = &self.ident;
281 let ty = &self.ty;
282 write!(f, "{name}: {ty}")
283 }
284}
285
286impl Display for ConstAssert {
287 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
288 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
289 let expr = &self.expression;
290 write!(f, "const_assert {expr};",)
291 }
292}
293
294impl Display for CompoundGlobalDeclaration {
295 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
296 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
297 let stmts = Indent(self.body.iter().format("\n"));
298 write!(f, "{{\n{stmts}\n}}")
299 }
300}
301
302impl Display for Attribute {
303 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
304 match self {
305 Attribute::Align(e1) => write!(f, "@align({e1})"),
306 Attribute::Binding(e1) => write!(f, "@binding({e1})"),
307 Attribute::BlendSrc(e1) => write!(f, "@blend_src({e1})"),
308 Attribute::Builtin(e1) => write!(f, "@builtin({e1})"),
309 Attribute::Const => write!(f, "@const"),
310 Attribute::Diagnostic(DiagnosticAttribute { severity, rule }) => {
311 write!(f, "@diagnostic({severity}, {rule})")
312 }
313 Attribute::Group(e1) => write!(f, "@group({e1})"),
314 Attribute::Id(e1) => write!(f, "@id({e1})"),
315 Attribute::Interpolate(InterpolateAttribute { ty, sampling }) => {
316 if let Some(sampling) = sampling {
317 write!(f, "@interpolate({ty}, {sampling})")
318 } else {
319 write!(f, "@interpolate({ty})")
320 }
321 }
322 Attribute::Invariant => write!(f, "@invariant"),
323 Attribute::Location(e1) => write!(f, "@location({e1})"),
324 Attribute::MustUse => write!(f, "@must_use"),
325 Attribute::Size(e1) => write!(f, "@size({e1})"),
326 Attribute::WorkgroupSize(WorkgroupSizeAttribute { x, y, z }) => {
327 let xyz = std::iter::once(x).chain(y).chain(z).format(", ");
328 write!(f, "@workgroup_size({xyz})")
329 }
330 Attribute::Vertex => write!(f, "@vertex"),
331 Attribute::Fragment => write!(f, "@fragment"),
332 Attribute::Compute => write!(f, "@compute"),
333
334 Attribute::If(e1) => write!(f, "@if({e1})"),
336 Attribute::Elif(e1) => write!(f, "@elif({e1})"),
337 Attribute::Else => write!(f, "@else"),
338 #[cfg(feature = "generics")]
339 Attribute::Type(e1) => write!(f, "@type({e1})"),
340
341 #[cfg(feature = "naga-ext")]
343 Attribute::Task => write!(f, "@task"),
344 #[cfg(feature = "naga-ext")]
345 Attribute::Payload(p) => write!(f, "@payload({p})"),
346 #[cfg(feature = "naga-ext")]
347 Attribute::Mesh(m) => write!(f, "@mesh({m})"),
348 #[cfg(feature = "naga-ext")]
349 Attribute::RayGeneration => write!(f, "@ray_generation"),
350 #[cfg(feature = "naga-ext")]
351 Attribute::AnyHit => write!(f, "@any_hit"),
352 #[cfg(feature = "naga-ext")]
353 Attribute::ClosestHit => write!(f, "@closest_hit"),
354 #[cfg(feature = "naga-ext")]
355 Attribute::Miss => write!(f, "@miss"),
356 #[cfg(feature = "naga-ext")]
357 Attribute::IncomingPayload(p) => write!(f, "@incoming_payload({p})"),
358 #[cfg(feature = "naga-ext")]
359 Attribute::EarlyDepthTest(None) => write!(f, "@early_depth_test"),
360 #[cfg(feature = "naga-ext")]
361 Attribute::EarlyDepthTest(Some(e1)) => write!(f, "@early_depth_test({e1})"),
362 Attribute::Custom(custom) => {
363 let name = &custom.name;
364 let args = custom.arguments.iter().format_with("", |args, f| {
365 f(&format_args!("({})", args.iter().format(", ")))
366 });
367 write!(f, "@{name}{args}")
368 }
369 }
370 }
371}
372
373#[cfg(feature = "generics")]
374impl Display for TypeConstraint {
375 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
376 let name = &self.ident;
377 let variants = self.variants.iter().format(" | ");
378 write!(f, "{name}, {variants}")
379 }
380}
381
382fn fmt_attrs(attrs: &[AttributeNode], inline: bool) -> impl fmt::Display + '_ {
383 FormatFn(move |f| {
384 let print = attrs.iter().format(" ");
385 let suffix = if attrs.is_empty() {
386 ""
387 } else if inline {
388 " "
389 } else {
390 "\n"
391 };
392 write!(f, "{print}{suffix}")
393 })
394}
395
396fn fmt_visibility(vis: Visibility) -> impl fmt::Display {
397 FormatFn(move |f| match vis {
398 Visibility::Public => f.write_str("public "),
399 Visibility::Package => Ok(()),
400 Visibility::Private => f.write_str("private "),
401 })
402}
403
404impl Display for Expression {
405 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
406 match self {
407 Expression::Literal(print) => write!(f, "{print}"),
408 Expression::Parenthesized(print) => {
409 write!(f, "{print}")
410 }
411 Expression::NamedComponent(print) => write!(f, "{print}"),
412 Expression::Indexing(print) => write!(f, "{print}"),
413 Expression::Unary(print) => write!(f, "{print}"),
414 Expression::Binary(print) => write!(f, "{print}"),
415 Expression::FunctionCall(print) => write!(f, "{print}"),
416 Expression::TypeOrIdentifier(print) => write!(f, "{print}"),
417 }
418 }
419}
420
421impl Display for LiteralExpression {
422 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
423 match self {
424 LiteralExpression::Bool(true) => write!(f, "true"),
425 LiteralExpression::Bool(false) => write!(f, "false"),
426 LiteralExpression::AbstractInt(num) => write!(f, "{num}"),
427 LiteralExpression::AbstractFloat(num) => write!(f, "{num:?}"), LiteralExpression::I32(num) => write!(f, "{num}i"),
429 LiteralExpression::U32(num) => write!(f, "{num}u"),
430 LiteralExpression::F32(num) => write!(f, "{num}f"),
431 LiteralExpression::F16(num) => write!(f, "{num}h"),
432 #[cfg(feature = "naga-ext")]
433 LiteralExpression::I64(num) => write!(f, "{num}li"),
434 #[cfg(feature = "naga-ext")]
435 LiteralExpression::U64(num) => write!(f, "{num}lu"),
436 #[cfg(feature = "naga-ext")]
437 LiteralExpression::F64(num) => write!(f, "{num}lf"),
438 }
439 }
440}
441
442impl Display for ParenthesizedExpression {
443 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
444 let expr = &self.expression;
445 write!(f, "({expr})")
446 }
447}
448
449impl Display for NamedComponentExpression {
450 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
451 let base = &self.base;
452 let component = &self.component;
453 write!(f, "{base}.{component}")
454 }
455}
456
457impl Display for IndexingExpression {
458 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
459 let base = &self.base;
460 let index = &self.index;
461 write!(f, "{base}[{index}]")
462 }
463}
464
465impl Display for UnaryExpression {
466 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
467 let operator = &self.operator;
468 let operand = &self.operand;
469 write!(f, "{operator}{operand}")
470 }
471}
472
473impl Display for BinaryExpression {
474 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
475 let operator = &self.operator;
476 let left = &self.left;
477 let right = &self.right;
478 write!(f, "{left} {operator} {right}")
479 }
480}
481
482impl Display for FunctionCall {
483 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
484 let ty = &self.ty;
485 let args = self.arguments.iter().format(", ");
486 write!(f, "{ty}({args})")
487 }
488}
489
490impl Display for TypeExpression {
491 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
492 if let Some(path) = &self.path {
493 write!(f, "{path}::")?;
494 }
495
496 let name = &self.ident;
497 let tplt = fmt_template(&self.template_args);
498 write!(f, "{name}{tplt}")
499 }
500}
501
502impl Display for TemplateArg {
503 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
504 let expr = &self.expression;
505 write!(f, "{expr}")
506 }
507}
508
509fn fmt_template(tplt: &Option<Vec<TemplateArg>>) -> impl fmt::Display + '_ {
510 tplt.iter().format_with("", |tplt, f| {
511 f(&format_args!("<{}>", tplt.iter().format(", ")))
512 })
513}
514
515impl Display for Statement {
516 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
517 match self {
518 Statement::Void => write!(f, ";"),
519 Statement::Compound(print) => write!(f, "{print}"),
520 Statement::Assignment(print) => write!(f, "{print}"),
521 Statement::Increment(print) => write!(f, "{print}"),
522 Statement::Decrement(print) => write!(f, "{print}"),
523 Statement::If(print) => write!(f, "{print}"),
524 Statement::Switch(print) => write!(f, "{print}"),
525 Statement::Loop(print) => write!(f, "{print}"),
526 Statement::For(print) => write!(f, "{print}"),
527 Statement::While(print) => write!(f, "{print}"),
528 Statement::Break(print) => write!(f, "{print}"),
529 Statement::Continue(print) => write!(f, "{print}"),
530 Statement::Return(print) => write!(f, "{print}"),
531 Statement::Discard(print) => write!(f, "{print}"),
532 Statement::FunctionCall(print) => write!(f, "{print}"),
533 Statement::ConstAssert(print) => write!(f, "{print}"),
534 Statement::Declaration(print) => write!(f, "{print}"),
535 }
536 }
537}
538
539impl Display for CompoundStatement {
540 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
541 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
542 let stmts = Indent(
543 self.statements
544 .iter()
545 .filter(|stmt| !matches!(stmt.node(), Statement::Void))
546 .format("\n"),
547 );
548 write!(f, "{{\n{stmts}\n}}")
549 }
550}
551
552impl Display for AssignmentStatement {
553 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
554 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
555 let operator = &self.operator;
556 let lhs = &self.lhs;
557 let rhs = &self.rhs;
558 write!(f, "{lhs} {operator} {rhs};")
559 }
560}
561
562impl Display for IncrementStatement {
563 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
564 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
565 let expr = &self.expression;
566 write!(f, "{expr}++;")
567 }
568}
569
570impl Display for DecrementStatement {
571 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
572 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
573 let expr = &self.expression;
574 write!(f, "{expr}--;")
575 }
576}
577
578impl Display for IfStatement {
579 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
580 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
581 let if_clause = &self.if_clause;
582 write!(f, "{if_clause}")?;
583 for else_if_clause in self.else_if_clauses.iter() {
584 write!(f, "\n{else_if_clause}")?;
585 }
586 if let Some(else_clause) = &self.else_clause {
587 write!(f, "\n{else_clause}")?;
588 }
589 Ok(())
590 }
591}
592
593impl Display for IfClause {
594 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
595 let expr = &self.expression;
596 let stmt = &self.body;
597 write!(f, "if {expr} {stmt}")
598 }
599}
600
601impl Display for ElseIfClause {
602 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
603 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
604 let expr = &self.expression;
605 let stmt = &self.body;
606 write!(f, "else if {expr} {stmt}")
607 }
608}
609
610impl Display for ElseClause {
611 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
612 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
613 let stmt = &self.body;
614 write!(f, "else {stmt}")
615 }
616}
617
618impl Display for SwitchStatement {
619 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
620 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
621 let expr = &self.expression;
622 let body_attrs = fmt_attrs(&self.body_attributes, false);
623 let clauses = Indent(self.clauses.iter().format("\n"));
624 write!(f, "switch {expr} {body_attrs}{{\n{clauses}\n}}")
625 }
626}
627
628impl Display for SwitchClause {
629 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
630 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
631 let cases = self.case_selectors.iter().format(", ");
632 let body = &self.body;
633 write!(f, "case {cases} {body}")
634 }
635}
636
637impl Display for CaseSelector {
638 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
639 match self {
640 CaseSelector::Default => write!(f, "default"),
641 CaseSelector::Expression(expr) => {
642 write!(f, "{expr}")
643 }
644 }
645 }
646}
647
648impl Display for LoopStatement {
649 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
650 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
651 let body_attrs = fmt_attrs(&self.body.attributes, false);
652 let stmts = Indent(
653 self.body
654 .statements
655 .iter()
656 .filter(|stmt| !matches!(stmt.node(), Statement::Void))
657 .format("\n"),
658 );
659 let continuing = self
660 .continuing
661 .iter()
662 .format_with("", |cont, f| f(&format_args!("{}\n", Indent(cont))));
663 write!(f, "loop {body_attrs}{{\n{stmts}\n{continuing}}}")
664 }
665}
666
667impl Display for ContinuingStatement {
668 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
669 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
670 let body_attrs = fmt_attrs(&self.body.attributes, false);
671 let stmts = Indent(
672 self.body
673 .statements
674 .iter()
675 .filter(|stmt| !matches!(stmt.node(), Statement::Void))
676 .format("\n"),
677 );
678 let break_if = self
679 .break_if
680 .iter()
681 .format_with("", |stmt, f| f(&format_args!("{}\n", Indent(stmt))));
682 write!(f, "continuing {body_attrs}{{\n{stmts}\n{break_if}}}")
683 }
684}
685
686impl Display for BreakIfStatement {
687 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
688 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
689 let expr = &self.expression;
690 write!(f, "break if {expr};")
691 }
692}
693
694impl Display for ForStatement {
695 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
696 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
697 let mut init = self
698 .initializer
699 .as_ref()
700 .map(|stmt| format!("{stmt}"))
701 .unwrap_or_default();
702 if init.ends_with(';') {
703 init.pop();
704 }
705 let cond = self
706 .condition
707 .iter()
708 .format_with("", |expr, f| f(&format_args!("{expr}")));
709 let mut updt = self
710 .update
711 .as_ref()
712 .map(|stmt| format!("{stmt}"))
713 .unwrap_or_default();
714 if updt.ends_with(';') {
715 updt.pop();
716 }
717 let body = &self.body;
718 write!(f, "for ({init}; {cond}; {updt}) {body}")
719 }
720}
721
722impl Display for WhileStatement {
723 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
724 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
725 let cond = &self.condition;
726 let body = &self.body;
727 write!(f, "while {cond} {body}")
728 }
729}
730
731impl Display for BreakStatement {
732 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
733 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
734 write!(f, "break;")
735 }
736}
737
738impl Display for ContinueStatement {
739 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
740 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
741 write!(f, "continue;")
742 }
743}
744
745impl Display for ReturnStatement {
746 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
747 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
748 let expr = self
749 .expression
750 .iter()
751 .format_with("", |expr, f| f(&format_args!(" {expr}")));
752 write!(f, "return{expr};")
753 }
754}
755
756impl Display for DiscardStatement {
757 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
758 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
759 write!(f, "discard;")
760 }
761}
762
763impl Display for FunctionCallStatement {
764 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
765 write!(f, "{}", fmt_attrs(&self.attributes, false))?;
766 let call = &self.call;
767 write!(f, "{call};")
768 }
769}
770
771#[cfg(test)]
772mod test {
773 use crate::syntax::ModulePath;
774 use crate::syntax::{Ident, TypeExpression};
775
776 #[test]
777 fn type_expression_display() {
778 let expr = TypeExpression {
779 path: None,
780 ident: Ident::new("foo".into()),
781 template_args: None,
782 };
783
784 assert_eq!(expr.to_string(), "foo");
785
786 let expr = TypeExpression {
787 path: Some(ModulePath::new(
788 crate::syntax::PathOrigin::Absolute,
789 vec!["bar".into(), "qux".into()],
790 )),
791 ident: Ident::new("foo".into()),
792 template_args: None,
793 };
794
795 assert_eq!(expr.to_string(), "package::bar::qux::foo");
796 }
797}