Skip to main content

rustidy_ast/expr/without_block/
array.rs

1//! Array
2
3// Imports
4use {
5	crate::{expr::Expression, token, util::Bracketed},
6	rustidy_ast_util::{Delimited, delimited, punct::{self, PunctuatedTrailing}},
7	rustidy_format::{Format, FormatOutput, Formattable, WhitespaceConfig, WhitespaceFormat},
8	rustidy_parse::Parse,
9	rustidy_print::Print,
10	rustidy_util::Whitespace,
11};
12
13/// `ArrayExpression`
14#[derive(PartialEq, Eq, Clone, Debug)]
15#[derive(serde::Serialize, serde::Deserialize)]
16#[derive(Parse, Formattable, Print)]
17#[parse(name = "an array expression")]
18pub struct ArrayExpression(Bracketed<Option<ArrayElements>>);
19
20impl ArrayExpression {
21	/// Formats all `values` within a single-line.
22	fn format_single_line(
23		prefix: &mut token::BracketOpen,
24		values: &mut PunctuatedTrailing<Expression, token::Comma>,
25		suffix: &mut token::BracketClose,
26		ctx: &mut rustidy_format::Context,
27		prefix_ws: WhitespaceConfig,
28	) -> FormatOutput {
29		let mut delimited = Delimited { prefix, value: values, suffix, };
30		let args = delimited::FmtRemoveWith(
31			punct::fmt(Whitespace::SINGLE, Whitespace::REMOVE)
32		);
33		delimited.format(ctx, prefix_ws, args)
34	}
35
36	/// Formats all `values` as multi-line
37	fn format_multi_line(
38		prefix: &mut token::BracketOpen,
39		values: &mut PunctuatedTrailing<Expression, token::Comma>,
40		suffix: &mut token::BracketClose,
41		ctx: &mut rustidy_format::Context,
42		prefix_ws: WhitespaceConfig,
43	) -> FormatOutput {
44		let mut delimited = Delimited { prefix, value: values, suffix, };
45		let args = delimited::fmt_indent_if_non_blank_with_value(
46			punct::FmtIndentColumns { columns: ctx.config().array_expr_cols, }
47		);
48		delimited.format(ctx, prefix_ws, args)
49	}
50}
51
52impl Format<WhitespaceConfig, ()> for ArrayExpression {
53	fn format(
54		&mut self,
55		ctx: &mut rustidy_format::Context,
56		prefix_ws: WhitespaceConfig,
57		_args: ()
58	) -> FormatOutput {
59		match &mut self.0.value {
60			Some(ArrayElements::Punctuated(values)) => {
61				let trailing_comma = values.trailing.take();
62				let single_line_output = Self::format_single_line(
63					&mut self.0.prefix,
64					values,
65					&mut self.0.suffix,
66					ctx,
67					prefix_ws
68				);
69
70				// Then check if we can fit into a single line.
71				// Note: If the user specified a number of columns, only
72				//       put everything into a single line if they fit.
73				// TODO: Should we even special case that?
74				let cols = ctx.config().array_expr_cols;
75				let is_single_line = single_line_output.multiline.is_none() && match cols {
76					Some(cols) => cols >= values.values_len(),
77					None => single_line_output.len_non_multiline_ws() <= ctx.config().max_array_expr_len,
78				};
79
80				// If we don't fit in a single line, format it multi-line
81				match is_single_line {
82					true => single_line_output,
83					false => {
84						values.trailing = Some(trailing_comma.unwrap_or_default());
85						Self::format_multi_line(
86							&mut self.0.prefix,
87							values,
88							&mut self.0.suffix,
89							ctx,
90							prefix_ws,
91						)
92					},
93				}
94			},
95
96			Some(ArrayElements::Repeat(repeat)) => {
97				let mut output = FormatOutput::default();
98
99				ctx
100					.format(&mut self.0.prefix, prefix_ws)
101					.append_to(&mut output);
102				ctx
103					.format(repeat, Whitespace::REMOVE)
104					.append_to(&mut output);
105				ctx
106					.format(&mut self.0.suffix, Whitespace::REMOVE)
107					.append_to(&mut output);
108
109				output
110			},
111
112			None => FormatOutput::default(),
113		}
114	}
115}
116
117/// `ArrayElements`
118#[derive(PartialEq, Eq, Clone, Debug)]
119#[derive(serde::Serialize, serde::Deserialize)]
120#[derive(Parse, Formattable, Print)]
121pub enum ArrayElements {
122	Repeat(ArrayElementsRepeat),
123	Punctuated(PunctuatedTrailing<Expression, token::Comma>),
124}
125
126#[derive(PartialEq, Eq, Clone, Debug)]
127#[derive(serde::Serialize, serde::Deserialize)]
128#[derive(Parse, Formattable, Format, Print)]
129pub struct ArrayElementsRepeat {
130	pub expr:  Expression,
131	#[format(prefix_ws = Whitespace::REMOVE)]
132	pub semi:  token::Semi,
133	#[format(prefix_ws = Whitespace::SINGLE)]
134	pub count: Expression,
135}