wdl_format/v1/
workflow.rs1pub mod call;
4
5use wdl_ast::SyntaxKind;
6use wdl_ast::Token;
7
8use crate::Config;
9use crate::PreToken;
10use crate::TokenStream;
11use crate::Trivia;
12use crate::Writable as _;
13use crate::element::FormatElement;
14
15pub fn format_conditional_statement(
21 element: &FormatElement,
22 stream: &mut TokenStream<PreToken>,
23 config: &Config,
24) {
25 for child in element.children().expect("conditional statement children") {
26 (&child).write(stream, config);
27 }
28 stream.end_line();
29}
30
31pub fn format_conditional_statement_clause(
33 element: &FormatElement,
34 stream: &mut TokenStream<PreToken>,
35 config: &Config,
36) {
37 let mut children = element
38 .children()
39 .expect("conditional statement clause children")
40 .peekable();
41
42 let mut has_condition = false;
43
44 while let Some(el) = children.peek() {
45 let Some(token) = el.element().as_token() else {
48 break;
49 };
50
51 match token {
53 Token::IfKeyword(_) => {
54 has_condition = true;
55 }
56 Token::ElseKeyword(_) => {}
57 _ => break,
58 }
59
60 el.write(stream, config);
61 stream.end_word();
62
63 children.next();
65 }
66
67 if has_condition {
70 let open_paren = children.next().expect("open paren");
71 assert!(open_paren.element().kind() == SyntaxKind::OpenParen);
72 (&open_paren).write(stream, config);
73
74 for child in children.by_ref() {
75 (&child).write(stream, config);
76 if child.element().kind() == SyntaxKind::CloseParen {
77 stream.end_word();
78 break;
79 }
80 }
81 }
82
83 let open_brace = children.next().expect("open brace");
84 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
85 (&open_brace).write(stream, config);
86 stream.increment_indent();
87
88 for child in children {
89 if child.element().kind() == SyntaxKind::CloseBrace {
90 stream.decrement_indent();
91 }
92 (&child).write(stream, config);
93 }
94 stream.end_word();
95}
96
97pub fn format_scatter_statement(
103 element: &FormatElement,
104 stream: &mut TokenStream<PreToken>,
105 config: &Config,
106) {
107 let mut children = element.children().expect("scatter statement children");
108
109 let scatter_keyword = children.next().expect("scatter keyword");
110 assert!(scatter_keyword.element().kind() == SyntaxKind::ScatterKeyword);
111 (&scatter_keyword).write(stream, config);
112 stream.end_word();
113
114 let open_paren = children.next().expect("open paren");
115 assert!(open_paren.element().kind() == SyntaxKind::OpenParen);
116 (&open_paren).write(stream, config);
117
118 let variable = children.next().expect("scatter variable");
119 assert!(variable.element().kind() == SyntaxKind::Ident);
120 (&variable).write(stream, config);
121 stream.end_word();
122
123 let in_keyword = children.next().expect("in keyword");
124 assert!(in_keyword.element().kind() == SyntaxKind::InKeyword);
125 (&in_keyword).write(stream, config);
126 stream.end_word();
127
128 for child in children.by_ref() {
129 (&child).write(stream, config);
130 if child.element().kind() == SyntaxKind::CloseParen {
131 stream.end_word();
132 break;
133 }
134 }
135
136 let open_brace = children.next().expect("open brace");
137 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
138 (&open_brace).write(stream, config);
139 stream.end_line();
140 stream.increment_indent();
141
142 for child in children {
143 if child.element().kind() == SyntaxKind::CloseBrace {
144 stream.decrement_indent();
145 }
146 (&child).write(stream, config);
147 }
148 stream.end_line();
149}
150
151pub fn format_workflow_definition(
157 element: &FormatElement,
158 stream: &mut TokenStream<PreToken>,
159 config: &Config,
160) {
161 let mut children = element.children().expect("workflow definition children");
162
163 stream.ignore_trailing_blank_lines();
164
165 let workflow_keyword = children.next().expect("workflow keyword");
166 assert!(workflow_keyword.element().kind() == SyntaxKind::WorkflowKeyword);
167 (&workflow_keyword).write(stream, config);
168 stream.end_word();
169
170 let name = children.next().expect("workflow name");
171 assert!(name.element().kind() == SyntaxKind::Ident);
172 (&name).write(stream, config);
173 stream.end_word();
174
175 let open_brace = children.next().expect("open brace");
176 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
177 (&open_brace).write(stream, config);
178 stream.increment_indent();
179
180 let mut meta = None;
181 let mut parameter_meta = None;
182 let mut input = None;
183 let mut body = Vec::new();
184 let mut output = None;
185 let mut hints = None;
186 let mut close_brace = None;
187
188 for child in children {
189 match child.element().kind() {
190 SyntaxKind::MetadataSectionNode => {
191 meta = Some(child.clone());
192 }
193 SyntaxKind::ParameterMetadataSectionNode => {
194 parameter_meta = Some(child.clone());
195 }
196 SyntaxKind::InputSectionNode => {
197 input = Some(child.clone());
198 }
199 SyntaxKind::BoundDeclNode => {
200 body.push(child.clone());
201 }
202 SyntaxKind::CallStatementNode => {
203 body.push(child.clone());
204 }
205 SyntaxKind::ConditionalStatementNode => {
206 body.push(child.clone());
207 }
208 SyntaxKind::ScatterStatementNode => {
209 body.push(child.clone());
210 }
211 SyntaxKind::OutputSectionNode => {
212 output = Some(child.clone());
213 }
214 SyntaxKind::WorkflowHintsSectionNode => {
215 hints = Some(child.clone());
216 }
217 SyntaxKind::CloseBrace => {
218 close_brace = Some(child.clone());
219 }
220 _ => {
221 unreachable!(
222 "unexpected child in workflow definition: {:?}",
223 child.element().kind()
224 );
225 }
226 }
227 }
228
229 if let Some(meta) = meta {
230 (&meta).write(stream, config);
231 stream.blank_line();
232 }
233
234 if let Some(parameter_meta) = parameter_meta {
235 (¶meter_meta).write(stream, config);
236 stream.blank_line();
237 }
238
239 if let Some(input) = input {
240 (&input).write(stream, config);
241 stream.blank_line();
242 }
243
244 stream.allow_blank_lines();
245 let body_empty = body.is_empty();
246 for child in body {
247 (&child).write(stream, config);
248 }
249 stream.ignore_trailing_blank_lines();
250 if !body_empty {
251 stream.blank_line();
252 }
253
254 if let Some(output) = output {
255 (&output).write(stream, config);
256 stream.blank_line();
257 }
258
259 if let Some(hints) = hints {
260 (&hints).write(stream, config);
261 stream.blank_line();
262 }
263
264 stream.trim_while(|t| matches!(t, PreToken::BlankLine | PreToken::Trivia(Trivia::BlankLine)));
265
266 stream.decrement_indent();
267 (&close_brace.expect("workflow close brace")).write(stream, config);
268 stream.end_line();
269}
270
271pub fn format_workflow_hints_array(
277 element: &FormatElement,
278 stream: &mut TokenStream<PreToken>,
279 config: &Config,
280) {
281 let mut children = element.children().expect("workflow hints array children");
282
283 let open_bracket = children.next().expect("open bracket");
284 assert!(open_bracket.element().kind() == SyntaxKind::OpenBracket);
285 (&open_bracket).write(stream, config);
286 stream.increment_indent();
287
288 let mut items = Vec::new();
289 let mut commas = Vec::new();
290 let mut close_bracket = None;
291
292 for child in children {
293 match child.element().kind() {
294 SyntaxKind::Comma => {
295 commas.push(child.clone());
296 }
297 SyntaxKind::CloseBracket => {
298 close_bracket = Some(child.clone());
299 }
300 _ => {
301 items.push(child.clone());
302 }
303 }
304 }
305
306 let mut commas = commas.into_iter();
307 for item in items {
308 (&item).write(stream, config);
309 match commas.next() {
310 Some(comma) => {
311 (&comma).write(stream, config);
312 }
313 _ if config.trailing_commas => {
314 stream.push_literal(",".to_string(), SyntaxKind::Comma);
315 }
316 _ => {}
317 }
318 stream.end_line();
319 }
320
321 stream.decrement_indent();
322 (&close_bracket.expect("workflow hints array close bracket")).write(stream, config);
323}
324
325pub fn format_workflow_hints_item(
331 element: &FormatElement,
332 stream: &mut TokenStream<PreToken>,
333 config: &Config,
334) {
335 let mut children = element.children().expect("workflow hints item children");
336
337 let key = children.next().expect("workflow hints item key");
338 assert!(key.element().kind() == SyntaxKind::Ident);
339 (&key).write(stream, config);
340
341 let colon = children.next().expect("workflow hints item colon");
342 assert!(colon.element().kind() == SyntaxKind::Colon);
343 (&colon).write(stream, config);
344 stream.end_word();
345
346 let value = children.next().expect("workflow hints item value");
347 (&value).write(stream, config);
348
349 stream.end_line();
350}
351
352pub fn format_workflow_hints_object_item(
358 element: &FormatElement,
359 stream: &mut TokenStream<PreToken>,
360 config: &Config,
361) {
362 let mut children = element
363 .children()
364 .expect("workflow hints object item children");
365
366 let key = children.next().expect("workflow hints object item key");
367 assert!(key.element().kind() == SyntaxKind::Ident);
368 (&key).write(stream, config);
369
370 let colon = children.next().expect("workflow hints object item colon");
371 assert!(colon.element().kind() == SyntaxKind::Colon);
372 (&colon).write(stream, config);
373 stream.end_word();
374
375 let value = children.next().expect("workflow hints object item value");
376 (&value).write(stream, config);
377
378 stream.end_line();
379}
380
381pub fn format_workflow_hints_object(
387 element: &FormatElement,
388 stream: &mut TokenStream<PreToken>,
389 config: &Config,
390) {
391 let mut children = element.children().expect("workflow hints object children");
392
393 let open_brace = children.next().expect("open brace");
394 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
395 (&open_brace).write(stream, config);
396 stream.increment_indent();
397
398 for child in children {
399 if child.element().kind() == SyntaxKind::CloseBrace {
400 stream.decrement_indent();
401 }
402 (&child).write(stream, config);
403 stream.end_line();
404 }
405}
406
407pub fn format_workflow_hints_section(
413 element: &FormatElement,
414 stream: &mut TokenStream<PreToken>,
415 config: &Config,
416) {
417 let mut children = element.children().expect("workflow hints section children");
418
419 let hints_keyword = children.next().expect("hints keyword");
420 assert!(hints_keyword.element().kind() == SyntaxKind::HintsKeyword);
421 (&hints_keyword).write(stream, config);
422 stream.end_word();
423
424 let open_brace = children.next().expect("open brace");
425 assert!(open_brace.element().kind() == SyntaxKind::OpenBrace);
426 (&open_brace).write(stream, config);
427 stream.increment_indent();
428
429 for child in children {
430 if child.element().kind() == SyntaxKind::CloseBrace {
431 stream.decrement_indent();
432 }
433 (&child).write(stream, config);
434 stream.end_line();
435 }
436}