cargo_cargofmt/formatting/
trailing_spaces.rs1use crate::toml::TomlToken;
2use std::borrow::Cow;
3
4#[tracing::instrument]
5pub fn trim_trailing_spaces(tokens: &mut crate::toml::TomlTokens<'_>) {
6 if let Some(last) = tokens.tokens.last_mut() {
7 if last.kind == crate::toml::TokenKind::Whitespace {
8 *last = TomlToken::EMPTY;
9 }
10 }
11 for i in tokens.indices() {
12 if tokens.tokens[i].kind != crate::toml::TokenKind::Newline {
13 continue;
14 }
15 let Some(prev_i) = i.checked_sub(1) else {
16 continue;
17 };
18 if tokens.tokens[prev_i].kind != crate::toml::TokenKind::Whitespace {
19 continue;
20 }
21 tokens.tokens[prev_i] = TomlToken::EMPTY;
22 }
23 tokens.trim_empty_whitespace();
24
25 for i in tokens.indices() {
26 if tokens.tokens[i].kind != crate::toml::TokenKind::Comment {
27 continue;
28 }
29 tokens.tokens[i].raw = match std::mem::take(&mut tokens.tokens[i].raw) {
30 Cow::Borrowed(s) => Cow::Borrowed(s.trim_end()),
31 Cow::Owned(mut s) => {
32 let trimmed = s.trim_end();
33 s.replace_range(0..trimmed.len(), "");
34 Cow::Owned(s)
35 }
36 }
37 }
38}
39
40#[cfg(test)]
41mod test {
42 use snapbox::assert_data_eq;
43 use snapbox::str;
44 use snapbox::IntoData;
45
46 #[track_caller]
47 fn valid(input: &str, expected: impl IntoData) {
48 let mut tokens = crate::toml::TomlTokens::parse(input);
49 super::trim_trailing_spaces(&mut tokens);
50 let actual = tokens.to_string();
51
52 assert_data_eq!(&actual, expected);
53
54 let (_, errors) = toml::de::DeTable::parse_recoverable(&actual);
55 if !errors.is_empty() {
56 use std::fmt::Write as _;
57 let mut result = String::new();
58 writeln!(&mut result, "---").unwrap();
59 for error in errors {
60 writeln!(&mut result, "{error}").unwrap();
61 writeln!(&mut result, "---").unwrap();
62 }
63 panic!("failed to parse\n---\n{actual}\n{result}");
64 }
65 }
66
67 #[test]
68 fn empty() {
69 valid("", str![]);
70 }
71
72 #[test]
73 fn whitespace() {
74 valid(" ", str![""]);
75 }
76
77 #[test]
78 fn leading_newline() {
79 valid(
80 "\n \n ",
81 str![[r#"
82
83
84
85"#]],
86 );
87 }
88
89 #[test]
90 fn trailing_newline() {
91 valid(
92 " \n \n",
93 str![[r#"
94
95
96
97"#]],
98 );
99 }
100
101 #[test]
102 fn trailing() {
103 valid(
104 r#"
105
106after_value = "value"
107after_comment = "value" # Hello
108[after_table]
109after_array_bits = [
110 1 ,
111 2 ,
112]
113"#,
114 str![[r#"
115
116
117after_value = "value"
118after_comment = "value" # Hello
119[after_table]
120after_array_bits = [
121 1 ,
122 2 ,
123]
124
125"#]],
126 );
127 }
128}