cargo_cargofmt/formatting/
string.rs

1use std::borrow::Cow;
2
3use toml_writer::TomlWrite as _;
4
5use crate::toml::TokenKind;
6
7#[tracing::instrument]
8pub fn normalize_strings(tokens: &mut crate::toml::TomlTokens<'_>) {
9    for i in tokens.indices() {
10        let token = &mut tokens.tokens[i];
11        match token.kind {
12            TokenKind::StdTableOpen | TokenKind::ArrayTableOpen => {}
13            TokenKind::ArrayOpen | TokenKind::InlineTableOpen => {}
14            TokenKind::StdTableClose | TokenKind::ArrayTableClose => {}
15            TokenKind::ArrayClose | TokenKind::InlineTableClose => {}
16            TokenKind::SimpleKey => {
17                if token.encoding.is_some() {
18                    let mut new_raw = String::new();
19                    new_raw
20                        .key(
21                            toml_writer::TomlKeyBuilder::new(token.decoded.as_ref().unwrap())
22                                .as_default(),
23                        )
24                        .unwrap();
25                    token.raw = Cow::Owned(new_raw);
26                }
27            }
28            TokenKind::KeySep => {}
29            TokenKind::KeyValSep => {}
30            TokenKind::Scalar => {
31                if let Some(decoded) = token.decoded.as_ref() {
32                    let mut new_raw = String::new();
33                    new_raw
34                        .value(toml_writer::TomlStringBuilder::new(decoded).as_default())
35                        .unwrap();
36                    token.raw = Cow::Owned(new_raw);
37                }
38            }
39            TokenKind::ValueSep => {}
40            TokenKind::Whitespace => {}
41            TokenKind::Comment => {}
42            TokenKind::Newline => {}
43            TokenKind::Error => {}
44        }
45    }
46}
47
48#[cfg(test)]
49mod test {
50    use snapbox::assert_data_eq;
51    use snapbox::str;
52    use snapbox::IntoData;
53
54    #[track_caller]
55    fn valid(input: &str, expected: impl IntoData) {
56        let mut tokens = crate::toml::TomlTokens::parse(input);
57        super::normalize_strings(&mut tokens);
58        let actual = tokens.to_string();
59
60        assert_data_eq!(&actual, expected);
61
62        let (_, errors) = toml::de::DeTable::parse_recoverable(&actual);
63        if !errors.is_empty() {
64            use std::fmt::Write as _;
65            let mut result = String::new();
66            writeln!(&mut result, "---").unwrap();
67            for error in errors {
68                writeln!(&mut result, "{error}").unwrap();
69                writeln!(&mut result, "---").unwrap();
70            }
71            panic!("failed to parse\n---\n{actual}\n{result}");
72        }
73    }
74
75    #[test]
76    fn empty() {
77        valid("", str![]);
78    }
79
80    #[test]
81    fn bare_key() {
82        valid(
83            r#"
84a = "value"
85"#,
86            str![[r#"
87
88a = "value"
89
90"#]],
91        );
92    }
93
94    #[test]
95    fn normalize_key_basic() {
96        valid(
97            r#"
98"" = "value"
99"b" = "value"
100"c'" = "value"
101"d\"" = "value"
102"#,
103            str![[r#"
104
105"" = "value"
106b = "value"
107"c'" = "value"
108'd"' = "value"
109
110"#]],
111        );
112    }
113
114    #[test]
115    fn normalize_key_literal() {
116        valid(
117            r#"
118'' = "value"
119'b' = "value"
120'd"' = "value"
121"#,
122            str![[r#"
123
124"" = "value"
125b = "value"
126'd"' = "value"
127
128"#]],
129        );
130    }
131
132    #[test]
133    fn normalize_value_string_type() {
134        valid(
135            r#"
136a = "value"
137b = 'value'
138c = """value"""
139d = """
140value"""
141e = '''value'''
142f = '''
143value'''
144"#,
145            str![[r#"
146
147a = "value"
148b = "value"
149c = "value"
150d = "value"
151e = "value"
152f = "value"
153
154"#]],
155        );
156    }
157
158    #[test]
159    fn normalize_value_escape() {
160        valid(
161            r#"
162a = "a\"b"
163b = 'a"b'
164c = """a\"b"""
165d = """
166a\"b"""
167e = '''a"b'''
168f = '''
169a"b'''
170"#,
171            str![[r#"
172
173a = 'a"b'
174b = 'a"b'
175c = 'a"b'
176d = 'a"b'
177e = 'a"b'
178f = 'a"b'
179
180"#]],
181        );
182    }
183
184    #[test]
185    fn normalize_value_multi_leading_nl() {
186        valid(
187            r#"
188a = """ab"""
189b = """a\nb"""
190c = """a
191b
192"""
193d = """
194a
195b
196"""
197e = '''ab'''
198f = '''a
199b
200'''
201g = '''
202a
203b
204'''
205"#,
206            str![[r#"
207
208a = "ab"
209b = """
210a
211b"""
212c = """
213a
214b
215"""
216d = """
217a
218b
219"""
220e = "ab"
221f = """
222a
223b
224"""
225g = """
226a
227b
228"""
229
230"#]],
231        );
232    }
233}