1use wdl_ast::SyntaxKind;
4use wdl_ast::v1::StrippedCommandPart;
5
6use crate::PreToken;
7use crate::TokenStream;
8use crate::Trivia;
9use crate::Writable as _;
10use crate::element::FormatElement;
11
12pub fn format_task_definition(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
18 let mut children = element.children().expect("task definition children");
19
20 stream.ignore_trailing_blank_lines();
21
22 let task_keyword = children.next().expect("task keyword");
23 assert!(task_keyword.element().kind() == SyntaxKind::TaskKeyword);
24 (&task_keyword).write(stream);
25 stream.end_word();
26
27 let name = children.next().expect("task name");
28 assert!(name.element().kind() == SyntaxKind::Ident);
29 (&name).write(stream);
30 stream.end_word();
31
32 let open_brace = children.next().expect("open brace");
33 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
34 (&open_brace).write(stream);
35 stream.end_line();
36 stream.increment_indent();
37
38 let mut meta = None;
39 let mut parameter_meta = None;
40 let mut input = None;
41 let mut body = Vec::new();
42 let mut command = None;
43 let mut output = None;
44 let mut requirements = None;
45 let mut runtime = None;
46 let mut hints = None;
47 let mut close_brace = None;
48
49 for child in children {
50 match child.element().kind() {
51 SyntaxKind::InputSectionNode => {
52 input = Some(child.clone());
53 }
54 SyntaxKind::MetadataSectionNode => {
55 meta = Some(child.clone());
56 }
57 SyntaxKind::ParameterMetadataSectionNode => {
58 parameter_meta = Some(child.clone());
59 }
60 SyntaxKind::BoundDeclNode => {
61 body.push(child.clone());
62 }
63 SyntaxKind::CommandSectionNode => {
64 command = Some(child.clone());
65 }
66 SyntaxKind::OutputSectionNode => {
67 output = Some(child.clone());
68 }
69 SyntaxKind::RequirementsSectionNode => {
70 requirements = Some(child.clone());
71 }
72 SyntaxKind::RuntimeSectionNode => {
73 runtime = Some(child.clone());
74 }
75 SyntaxKind::TaskHintsSectionNode => {
76 hints = Some(child.clone());
77 }
78 SyntaxKind::CloseBrace => {
79 close_brace = Some(child.clone());
80 }
81 _ => {
82 unreachable!(
83 "unexpected child in task definition: {:?}",
84 child.element().kind()
85 );
86 }
87 }
88 }
89
90 if let Some(meta) = meta {
91 (&meta).write(stream);
92 stream.blank_line();
93 }
94
95 if let Some(parameter_meta) = parameter_meta {
96 (¶meter_meta).write(stream);
97 stream.blank_line();
98 }
99
100 if let Some(input) = input {
101 (&input).write(stream);
102 stream.blank_line();
103 }
104
105 stream.allow_blank_lines();
106 let body_empty = body.is_empty();
107 for child in body {
108 (&child).write(stream);
109 }
110 stream.ignore_trailing_blank_lines();
111 if !body_empty {
112 stream.blank_line();
113 }
114
115 if let Some(command) = command {
116 (&command).write(stream);
117 stream.blank_line();
118 }
119
120 if let Some(output) = output {
121 (&output).write(stream);
122 stream.blank_line();
123 }
124
125 match requirements {
126 Some(requirements) => {
127 (&requirements).write(stream);
128 stream.blank_line();
129 }
130 _ => {
131 if let Some(runtime) = runtime {
132 (&runtime).write(stream);
133 stream.blank_line();
134 }
135 }
136 }
137
138 if let Some(hints) = hints {
139 (&hints).write(stream);
140 stream.blank_line();
141 }
142
143 stream.trim_while(|t| matches!(t, PreToken::BlankLine | PreToken::Trivia(Trivia::BlankLine)));
144
145 stream.decrement_indent();
146 (&close_brace.expect("task close brace")).write(stream);
147 stream.end_line();
148}
149
150pub fn format_command_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
156 let mut children = element.children().expect("command section children");
157
158 let command_keyword = children.next().expect("command keyword");
159 assert!(command_keyword.element().kind() == SyntaxKind::CommandKeyword);
160 (&command_keyword).write(stream);
161 stream.end_word();
162
163 let open_delimiter = children.next().expect("open delimiter");
164 match open_delimiter.element().kind() {
165 SyntaxKind::OpenBrace => {
166 stream.push_literal_in_place_of_token(
167 open_delimiter
168 .element()
169 .as_token()
170 .expect("open brace should be token"),
171 "<<<".to_string(),
172 );
173 }
174 SyntaxKind::OpenHeredoc => {
175 (&open_delimiter).write(stream);
176 }
177 _ => {
178 unreachable!(
179 "unexpected open delimiter in command section: {:?}",
180 open_delimiter.element().kind()
181 );
182 }
183 }
184
185 let parts = element
186 .element()
187 .as_node()
188 .expect("command section node")
189 .as_command_section()
190 .expect("command section")
191 .strip_whitespace();
192 match parts {
193 None => {
194 for child in children {
198 match child.element().kind() {
199 SyntaxKind::CloseBrace => {
200 stream.push_literal_in_place_of_token(
201 child
202 .element()
203 .as_token()
204 .expect("close brace should be token"),
205 ">>>".to_string(),
206 );
207 }
208 SyntaxKind::CloseHeredoc => {
209 (&child).write(stream);
210 }
211 SyntaxKind::LiteralCommandText | SyntaxKind::PlaceholderNode => {
212 (&child).write(stream);
213 }
214 _ => {
215 unreachable!(
216 "unexpected child in command section: {:?}",
217 child.element().kind()
218 );
219 }
220 }
221 }
222 }
223 Some(parts) => {
224 stream.increment_indent();
227
228 for (part, child) in parts.iter().zip(children.by_ref()) {
229 match part {
230 StrippedCommandPart::Text(text) => {
231 for (i, line) in text.lines().enumerate() {
233 if i > 0 {
234 stream.end_line();
235 }
236 stream.push_literal(line.to_owned(), SyntaxKind::LiteralCommandText);
237 }
238
239 if text.ends_with('\n') {
240 stream.end_line();
241 }
242 }
243 StrippedCommandPart::Placeholder(_) => {
244 stream.push(PreToken::TempIndentStart);
245 (&child).write(stream);
246 stream.push(PreToken::TempIndentEnd);
247 }
248 }
249 }
250
251 stream.decrement_indent();
252
253 for child in children {
254 match child.element().kind() {
255 SyntaxKind::CloseBrace => {
256 stream.push_literal_in_place_of_token(
257 child
258 .element()
259 .as_token()
260 .expect("close brace should be token"),
261 ">>>".to_string(),
262 );
263 }
264 SyntaxKind::CloseHeredoc => {
265 (&child).write(stream);
266 }
267 _ => {
268 unreachable!(
269 "unexpected child in command section: {:?}",
270 child.element().kind()
271 );
272 }
273 }
274 }
275 }
276 }
277 stream.end_line();
278}
279
280pub fn format_requirements_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
286 let mut children = element.children().expect("requirements item children");
287
288 let name = children.next().expect("requirements item name");
289 assert!(name.element().kind() == SyntaxKind::Ident);
290 (&name).write(stream);
291
292 let colon = children.next().expect("requirements item colon");
293 assert!(colon.element().kind() == SyntaxKind::Colon);
294 (&colon).write(stream);
295 stream.end_word();
296
297 let value = children.next().expect("requirements item value");
298 (&value).write(stream);
299}
300
301pub fn format_requirements_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
307 let mut children = element.children().expect("requirements section children");
308
309 let requirements_keyword = children.next().expect("requirements keyword");
310 assert!(requirements_keyword.element().kind() == SyntaxKind::RequirementsKeyword);
311 (&requirements_keyword).write(stream);
312 stream.end_word();
313
314 let open_brace = children.next().expect("open brace");
315 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
316 (&open_brace).write(stream);
317 stream.increment_indent();
318
319 let mut items = Vec::new();
320 let mut close_brace = None;
321
322 for child in children {
323 match child.element().kind() {
324 SyntaxKind::RequirementsItemNode => {
325 items.push(child.clone());
326 }
327 SyntaxKind::CloseBrace => {
328 close_brace = Some(child.clone());
329 }
330 _ => {
331 unreachable!(
332 "unexpected child in requirements section: {:?}",
333 child.element().kind()
334 );
335 }
336 }
337 }
338
339 for item in items {
340 (&item).write(stream);
341 stream.end_line();
342 }
343
344 stream.decrement_indent();
345 (&close_brace.expect("requirements close brace")).write(stream);
346 stream.end_line();
347}
348
349pub fn format_task_hints_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
355 let mut children = element.children().expect("task hints item children");
356
357 let name = children.next().expect("task hints item name");
358 assert!(name.element().kind() == SyntaxKind::Ident);
359 (&name).write(stream);
360
361 let colon = children.next().expect("task hints item colon");
362 assert!(colon.element().kind() == SyntaxKind::Colon);
363 (&colon).write(stream);
364 stream.end_word();
365
366 let value = children.next().expect("task hints item value");
367 (&value).write(stream);
368
369 assert!(children.next().is_none());
370}
371
372pub fn format_runtime_item(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
378 let mut children = element.children().expect("runtime item children");
379
380 let name = children.next().expect("runtime item name");
381 assert!(name.element().kind() == SyntaxKind::Ident);
382 (&name).write(stream);
383
384 let colon = children.next().expect("runtime item colon");
385 assert!(colon.element().kind() == SyntaxKind::Colon);
386 (&colon).write(stream);
387 stream.end_word();
388
389 let value = children.next().expect("runtime item value");
390 (&value).write(stream);
391}
392
393pub fn format_runtime_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
399 let mut children = element.children().expect("runtime section children");
400
401 let runtime_keyword = children.next().expect("runtime keyword");
402 assert!(runtime_keyword.element().kind() == SyntaxKind::RuntimeKeyword);
403 (&runtime_keyword).write(stream);
404 stream.end_word();
405
406 let open_brace = children.next().expect("open brace");
407 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
408 (&open_brace).write(stream);
409 stream.increment_indent();
410
411 let mut items = Vec::new();
412 let mut close_brace = None;
413
414 for child in children {
415 match child.element().kind() {
416 SyntaxKind::RuntimeItemNode => {
417 items.push(child.clone());
418 }
419 SyntaxKind::CloseBrace => {
420 close_brace = Some(child.clone());
421 }
422 _ => {
423 unreachable!(
424 "unexpected child in runtime section: {:?}",
425 child.element().kind()
426 );
427 }
428 }
429 }
430
431 for item in items {
432 (&item).write(stream);
433 stream.end_line();
434 }
435
436 stream.decrement_indent();
437 (&close_brace.expect("runtime close brace")).write(stream);
438 stream.end_line();
439}
440
441pub fn format_task_hints_section(element: &FormatElement, stream: &mut TokenStream<PreToken>) {
447 let mut children = element.children().expect("task hints section children");
448
449 let hints_keyword = children.next().expect("hints keyword");
450 assert!(hints_keyword.element().kind() == SyntaxKind::HintsKeyword);
451 (&hints_keyword).write(stream);
452 stream.end_word();
453
454 let open_brace = children.next().expect("open brace");
455 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
456 (&open_brace).write(stream);
457 stream.increment_indent();
458
459 let mut items = Vec::new();
460 let mut close_brace = None;
461
462 for child in children {
463 match child.element().kind() {
464 SyntaxKind::TaskHintsItemNode => {
465 items.push(child.clone());
466 }
467 SyntaxKind::CloseBrace => {
468 close_brace = Some(child.clone());
469 }
470 _ => {
471 unreachable!(
472 "unexpected child in task hints section: {:?}",
473 child.element().kind()
474 );
475 }
476 }
477 }
478
479 for item in items {
480 (&item).write(stream);
481 stream.end_line();
482 }
483
484 stream.decrement_indent();
485 (&close_brace.expect("task hints close brace")).write(stream);
486 stream.end_line();
487}