1use std::rc::Rc;
4
5use nonempty::NonEmpty;
6use wdl_ast::SyntaxKind;
7use wdl_ast::SyntaxToken;
8
9pub mod decl;
10pub mod expr;
11pub mod import;
12pub mod meta;
13pub mod sort;
14pub mod r#struct;
15pub mod task;
16pub mod workflow;
17
18use crate::PreToken;
19use crate::TokenStream;
20use crate::Writable as _;
21use crate::element::FormatElement;
22
23pub fn format_ast(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
31 fn last_token_of_element(elem: &FormatElement) -> SyntaxToken {
32 elem.element()
33 .as_node()
34 .expect("all children of an AST should be nodes")
35 .inner()
36 .last_token()
37 .expect("nodes should have tokens")
38 }
39
40 let mut children = element.children().expect("AST children");
41
42 let version_statement = children.next().expect("version statement");
43 assert!(version_statement.element().kind() == SyntaxKind::VersionStatementNode);
44 (&version_statement).write(stream);
45
46 stream.blank_line();
47
48 let mut imports = Vec::new();
49 let mut remainder = Vec::new();
50
51 for child in children {
52 match child.element().kind() {
53 SyntaxKind::ImportStatementNode => imports.push(child),
54 _ => remainder.push(child),
55 }
56 }
57
58 imports.sort_by(|a, b| {
59 let a = a
60 .element()
61 .as_node()
62 .expect("import statement node")
63 .as_import_statement()
64 .expect("import statement");
65 let b = b
66 .element()
67 .as_node()
68 .expect("import statement node")
69 .as_import_statement()
70 .expect("import statement");
71 let a_uri = a
72 .uri()
73 .text()
74 .expect("import uri should not be interpolated");
75 let b_uri = b
76 .uri()
77 .text()
78 .expect("import uri should not be interpolated");
79 a_uri.text().cmp(b_uri.text())
80 });
81
82 stream.ignore_trailing_blank_lines();
83
84 let mut trailing_comments = None;
85
86 for import in imports {
87 (&import).write(stream);
88
89 if trailing_comments.is_none() {
90 trailing_comments = find_trailing_comments(&last_token_of_element(import));
91 }
92 }
93
94 stream.blank_line();
95
96 for child in &remainder {
97 (child).write(stream);
98
99 if trailing_comments.is_none() {
100 trailing_comments = find_trailing_comments(&last_token_of_element(child));
101 }
102
103 stream.blank_line();
104 }
105
106 if let Some(comments) = trailing_comments {
107 stream.trim_end(&PreToken::BlankLine);
108 for comment in comments {
109 stream.push(PreToken::Trivia(crate::Trivia::Comment(
110 crate::Comment::Preceding(Rc::new(comment.text().into())),
111 )));
112 stream.push(PreToken::LineEnd);
113 }
114 }
115}
116
117fn find_trailing_comments(token: &SyntaxToken) -> Option<NonEmpty<SyntaxToken>> {
125 let mut next_token = token.next_token();
126 let mut on_next_line = false;
127
128 fn is_comment(token: &SyntaxToken) -> bool {
129 matches!(token.kind(), SyntaxKind::Comment)
130 }
131
132 let mut encountered_comments = Vec::new();
133
134 while let Some(next) = next_token {
135 if !next.kind().is_trivia() {
136 return None;
137 }
138
139 let skip = !on_next_line && is_comment(&next);
141 on_next_line = on_next_line || next.text().contains('\n');
142 next_token = next.next_token();
143 if skip {
144 continue;
145 }
146 if is_comment(&next) {
147 encountered_comments.push(next);
148 }
149 }
150
151 NonEmpty::from_vec(encountered_comments)
152}
153
154pub fn format_version_statement(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
156 for child in element.children().expect("version statement children") {
157 (&child).write(stream);
158 stream.end_word();
159 }
160 stream.end_line();
161}
162
163pub fn format_input_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
170 let mut children = element.children().expect("input section children");
171
172 let input_keyword = children.next().expect("input section input keyword");
173 assert!(input_keyword.element().kind() == SyntaxKind::InputKeyword);
174 (&input_keyword).write(stream);
175 stream.end_word();
176
177 let open_brace = children.next().expect("input section open brace");
178 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
179 (&open_brace).write(stream);
180 stream.increment_indent();
181
182 let mut inputs = Vec::new();
183 let mut close_brace = None;
184
185 for child in children {
186 match child.element().kind() {
187 SyntaxKind::BoundDeclNode | SyntaxKind::UnboundDeclNode => inputs.push(child),
188 SyntaxKind::CloseBrace => close_brace = Some(child),
189 _ => panic!("unexpected input section child"),
190 }
191 }
192
193 inputs.sort_by(|a, b| {
194 let a_decl =
195 wdl_ast::v1::Decl::cast(a.element().as_node().unwrap().inner().clone()).unwrap();
196 let b_decl =
197 wdl_ast::v1::Decl::cast(b.element().as_node().unwrap().inner().clone()).unwrap();
198 sort::compare_decl(&a_decl, &b_decl)
199 });
200 for input in inputs {
201 (&input).write(stream);
202 }
203
204 stream.decrement_indent();
205 (&close_brace.expect("input section close brace")).write(stream);
206 stream.end_line();
207}
208
209pub fn format_output_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
216 let mut children = element.children().expect("output section children");
217
218 let output_keyword = children.next().expect("output keyword");
219 assert!(output_keyword.element().kind() == SyntaxKind::OutputKeyword);
220 (&output_keyword).write(stream);
221 stream.end_word();
222
223 let open_brace = children.next().expect("output section open brace");
224 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
225 (&open_brace).write(stream);
226 stream.increment_indent();
227
228 for child in children {
229 if child.element().kind() == SyntaxKind::CloseBrace {
230 stream.decrement_indent();
231 } else {
232 assert!(child.element().kind() == SyntaxKind::BoundDeclNode);
233 }
234 (&child).write(stream);
235 stream.end_line();
236 }
237}
238
239pub fn format_literal_input_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
246 let mut children = element.children().expect("literal input item children");
247
248 let key = children.next().expect("literal input item key");
249 assert!(key.element().kind() == SyntaxKind::Ident);
250 (&key).write(stream);
251
252 let colon = children.next().expect("literal input item colon");
253 assert!(colon.element().kind() == SyntaxKind::Colon);
254 (&colon).write(stream);
255 stream.end_word();
256
257 let hints_node = children.next().expect("literal input item hints node");
258 assert!(hints_node.element().kind() == SyntaxKind::LiteralHintsNode);
259 (&hints_node).write(stream);
260}
261
262pub fn format_literal_input(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
269 let mut children = element.children().expect("literal input children");
270
271 let input_keyword = children.next().expect("literal input keyword");
272 assert!(input_keyword.element().kind() == SyntaxKind::InputKeyword);
273 (&input_keyword).write(stream);
274 stream.end_word();
275
276 let open_brace = children.next().expect("literal input open brace");
277 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
278 (&open_brace).write(stream);
279 stream.increment_indent();
280
281 for child in children {
282 if child.element().kind() == SyntaxKind::CloseBrace {
283 stream.decrement_indent();
284 } else {
285 assert!(child.element().kind() == SyntaxKind::LiteralInputItemNode);
286 }
287 (&child).write(stream);
288 }
289 stream.end_line();
290}
291
292pub fn format_literal_hints_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
299 let mut children = element.children().expect("literal hints item children");
300
301 let key = children.next().expect("literal hints item key");
302 assert!(key.element().kind() == SyntaxKind::Ident);
303 (&key).write(stream);
304
305 let colon = children.next().expect("literal hints item colon");
306 assert!(colon.element().kind() == SyntaxKind::Colon);
307 (&colon).write(stream);
308 stream.end_word();
309
310 let value = children.next().expect("literal hints item value");
311 (&value).write(stream);
312}
313
314pub fn format_literal_hints(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
321 let mut children = element.children().expect("literal hints children");
322
323 let hints_keyword = children.next().expect("literal hints keyword");
324 assert!(hints_keyword.element().kind() == SyntaxKind::HintsKeyword);
325 (&hints_keyword).write(stream);
326 stream.end_word();
327
328 let open_brace = children.next().expect("literal hints open brace");
329 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
330 (&open_brace).write(stream);
331 stream.increment_indent();
332
333 let mut items = Vec::new();
334 let mut commas = Vec::new();
335 let mut close_brace = None;
336
337 for child in children {
338 match child.element().kind() {
339 SyntaxKind::LiteralHintsItemNode => items.push(child),
340 SyntaxKind::Comma => commas.push(child),
341 SyntaxKind::CloseBrace => close_brace = Some(child),
342 _ => panic!("unexpected literal hints child"),
343 }
344 }
345
346 let mut commas = commas.iter();
347 for item in items {
348 (&item).write(stream);
349 if let Some(comma) = commas.next() {
350 (comma).write(stream);
351 } else {
352 stream.push_literal(",".to_string(), SyntaxKind::Comma);
353 }
354 stream.end_line();
355 }
356
357 stream.decrement_indent();
358 (&close_brace.expect("literal hints close brace")).write(stream);
359}
360
361pub fn format_literal_output_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
368 let mut children = element.children().expect("literal output item children");
369
370 for child in children.by_ref() {
371 if matches!(child.element().kind(), SyntaxKind::Ident | SyntaxKind::Dot) {
372 (&child).write(stream);
373 } else {
374 assert!(child.element().kind() == SyntaxKind::Colon);
375 (&child).write(stream);
376 stream.end_word();
377 break;
378 }
379 }
380
381 let value = children.next().expect("literal output item value");
382 (&value).write(stream);
383}
384
385pub fn format_literal_output(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
392 let mut children = element.children().expect("literal output children");
393
394 let output_keyword = children.next().expect("literal output keyword");
395 assert!(output_keyword.element().kind() == SyntaxKind::OutputKeyword);
396 (&output_keyword).write(stream);
397 stream.end_word();
398
399 let open_brace = children.next().expect("literal output open brace");
400 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
401 (&open_brace).write(stream);
402 stream.increment_indent();
403
404 let mut items = Vec::new();
405 let mut commas = Vec::new();
406 let mut close_brace = None;
407
408 for child in children {
409 match child.element().kind() {
410 SyntaxKind::LiteralOutputItemNode => items.push(child),
411 SyntaxKind::Comma => commas.push(child),
412 SyntaxKind::CloseBrace => close_brace = Some(child),
413 _ => panic!("unexpected literal output child"),
414 }
415 }
416
417 let mut commas = commas.iter();
418 for item in items {
419 (&item).write(stream);
420 if let Some(comma) = commas.next() {
421 (comma).write(stream);
422 } else {
423 stream.push_literal(",".to_string(), SyntaxKind::Comma);
424 }
425 stream.end_line();
426 }
427
428 stream.decrement_indent();
429 (&close_brace.expect("literal output close brace")).write(stream);
430}