Skip to content

Commit c781cb9

Browse files
lu-zeroshssoichiro
authored andcommitted
feat: Uniform the behaviour of block and top-level span options
And fix the span computation.
1 parent d49ed44 commit c781cb9

File tree

3 files changed

+82
-20
lines changed

3 files changed

+82
-20
lines changed

src/formatter.rs

+24-12
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,8 @@ struct Formatter<'a> {
148148
options: &'a FormatOptions<'a>,
149149
indentation: Indentation<'a>,
150150
inline_block: InlineBlock,
151-
line_start: usize,
151+
span_len: usize,
152+
block_level: usize,
152153
}
153154

154155
impl<'a> Formatter<'a> {
@@ -165,7 +166,8 @@ impl<'a> Formatter<'a> {
165166
options.max_inline_block,
166167
options.max_inline_arguments.is_none(),
167168
),
168-
line_start: 0,
169+
span_len: 0,
170+
block_level: 0,
169171
}
170172
}
171173

@@ -209,11 +211,11 @@ impl<'a> Formatter<'a> {
209211
self.add_new_line(query);
210212
self.indentation.increase_top_level();
211213
query.push_str(&self.equalize_whitespace(&self.format_reserved_word(token.value)));
212-
let len = self.top_level_tokens_span();
214+
self.span_len = self.top_level_tokens_span();
213215
if self
214216
.options
215217
.max_inline_top_level
216-
.map_or(true, |limit| limit < len)
218+
.map_or(true, |limit| limit < self.span_len)
217219
{
218220
self.add_new_line(query);
219221
} else {
@@ -232,7 +234,7 @@ impl<'a> Formatter<'a> {
232234
if self
233235
.options
234236
.max_inline_arguments
235-
.map_or(true, |limit| limit < self.line_len_next(query))
237+
.map_or(true, |limit| limit < self.span_len)
236238
{
237239
self.add_new_line(query);
238240
} else {
@@ -256,6 +258,7 @@ impl<'a> Formatter<'a> {
256258

257259
// Opening parentheses increase the block indent level and start a new line
258260
fn format_opening_parentheses(&mut self, token: &Token<'_>, query: &mut String) {
261+
self.block_level += 1;
259262
const PRESERVE_WHITESPACE_FOR: &[TokenKind] = &[
260263
TokenKind::Whitespace,
261264
TokenKind::OpenParen,
@@ -304,6 +307,7 @@ impl<'a> Formatter<'a> {
304307

305308
// Closing parentheses decrease the block indent level
306309
fn format_closing_parentheses(&mut self, token: &Token<'_>, query: &mut String) {
310+
self.block_level = self.block_level.saturating_sub(1);
307311
let mut token = token.clone();
308312
let value = match (
309313
self.options.uppercase,
@@ -367,7 +371,7 @@ impl<'a> Formatter<'a> {
367371
}
368372

369373
if matches!((self.previous_top_level_reserved_word, self.options.max_inline_arguments),
370-
(Some(word), Some(limit)) if word.value.to_lowercase() == "select" && limit > self.line_len_next(query))
374+
(Some(word), Some(limit)) if ["select", "from"].contains(&word.value.to_lowercase().as_str()) && limit > self.span_len)
371375
{
372376
return;
373377
}
@@ -394,7 +398,7 @@ impl<'a> Formatter<'a> {
394398
}
395399
}
396400

397-
fn add_new_line(&mut self, query: &mut String) {
401+
fn add_new_line(&self, query: &mut String) {
398402
self.trim_spaces_end(query);
399403
if self.options.inline {
400404
query.push(' ');
@@ -403,7 +407,6 @@ impl<'a> Formatter<'a> {
403407
if !query.ends_with('\n') {
404408
query.push('\n');
405409
}
406-
self.line_start = query.len();
407410
query.push_str(&self.indentation.get_indent());
408411
}
409412

@@ -490,16 +493,25 @@ impl<'a> Formatter<'a> {
490493
}
491494
}
492495

493-
fn line_len_next(&self, query: &str) -> usize {
494-
query.len() - self.line_start + self.next_token(1).map_or(0, |t| t.value.len())
495-
}
496-
497496
fn top_level_tokens_span(&self) -> usize {
498497
assert_eq!(self.tokens[self.index].kind, TokenKind::ReservedTopLevel);
498+
let mut block_level = self.block_level;
499499

500500
self.tokens[self.index..]
501501
.iter()
502502
.skip(1)
503+
.take_while(|token| match token.kind {
504+
TokenKind::OpenParen => {
505+
block_level += 1;
506+
true
507+
}
508+
TokenKind::CloseParen => {
509+
block_level = block_level.saturating_sub(1);
510+
block_level > self.block_level
511+
}
512+
TokenKind::ReservedTopLevel => false,
513+
_ => true,
514+
})
503515
.map(|token| token.value.len())
504516
.sum()
505517
}

src/inline_block.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,6 @@ impl InlineBlock {
8181
} else {
8282
false
8383
}
84-
|| token.value.to_lowercase() == "case"
84+
|| ["case", "end"].contains(&token.value.to_lowercase().as_str())
8585
}
8686
}

src/lib.rs

+57-7
Original file line numberDiff line numberDiff line change
@@ -197,7 +197,7 @@ mod tests {
197197
}
198198

199199
#[test]
200-
fn split_select_arguments_over_lines() {
200+
fn split_select_arguments_inline_top_level() {
201201
let input = indoc! {
202202
"
203203
SELECT
@@ -212,16 +212,14 @@ mod tests {
212212
FROM foo;"
213213
};
214214
let options = FormatOptions {
215-
max_inline_arguments: Some(20),
215+
max_inline_arguments: Some(50),
216+
max_inline_top_level: Some(50),
216217
..Default::default()
217218
};
218219
let expected = indoc! {
219220
"
220-
SELECT
221-
a, b, c, d, e,
222-
f, g, h
223-
FROM
224-
foo;"
221+
SELECT a, b, c, d, e, f, g, h
222+
FROM foo;"
225223
};
226224
assert_eq!(format(input, &QueryParams::None, &options), expected);
227225
}
@@ -1514,6 +1512,31 @@ mod tests {
15141512
assert_eq!(format(input, &QueryParams::None, &options), expected);
15151513
}
15161514

1515+
#[test]
1516+
fn it_formats_case_when_inside_select_inlined_top_level() {
1517+
let input =
1518+
"SELECT foo, bar, CASE baz WHEN 'one' THEN 1 WHEN 'two' THEN 2 ELSE 3 END FROM table";
1519+
let options = FormatOptions {
1520+
max_inline_top_level: Some(50),
1521+
..Default::default()
1522+
};
1523+
let expected = indoc!(
1524+
"
1525+
SELECT
1526+
foo,
1527+
bar,
1528+
CASE
1529+
baz
1530+
WHEN 'one' THEN 1
1531+
WHEN 'two' THEN 2
1532+
ELSE 3
1533+
END
1534+
FROM table"
1535+
);
1536+
1537+
assert_eq!(format(input, &QueryParams::None, &options), expected);
1538+
}
1539+
15171540
#[test]
15181541
fn it_formats_case_when_with_an_expression() {
15191542
let input = "CASE toString(getNumber()) WHEN 'one' THEN 1 WHEN 'two' THEN 2 WHEN 'three' THEN 3 ELSE 4 END;";
@@ -1958,6 +1981,33 @@ mod tests {
19581981
assert_eq!(format(input, &QueryParams::None, &options), expected);
19591982
}
19601983

1984+
#[test]
1985+
fn format_nested_select() {
1986+
let input = "WITH a AS ( SELECT a, b, c FROM t WHERE a > 100 ), aa AS ( SELECT field FROM table ) SELECT b, field FROM a, aa;";
1987+
let options = FormatOptions {
1988+
max_inline_arguments: Some(10),
1989+
max_inline_top_level: Some(9),
1990+
..Default::default()
1991+
};
1992+
let expected = indoc! {
1993+
"
1994+
WITH a AS (
1995+
SELECT a, b, c
1996+
FROM t
1997+
WHERE a > 100
1998+
),
1999+
aa AS (
2000+
SELECT field
2001+
FROM table
2002+
)
2003+
SELECT
2004+
b,
2005+
field
2006+
FROM a, aa;"
2007+
};
2008+
assert_eq!(format(input, &QueryParams::None, &options), expected);
2009+
}
2010+
19612011
#[test]
19622012
fn it_converts_keywords_nothing_when_no_option_passed_in() {
19632013
let input = "select distinct * frOM foo left join bar WHERe cola > 1 and colb = 3";

0 commit comments

Comments
 (0)