Skip to main content

darklua_core/rules/
remove_spaces.rs

1use crate::nodes::*;
2use crate::process::{DefaultVisitor, NodeProcessor, NodeVisitor};
3use crate::rules::{
4    Context, FlawlessRule, RuleConfiguration, RuleConfigurationError, RuleMetadata, RuleProperties,
5};
6
7use super::verify_no_rule_properties;
8
9#[derive(Debug, Default)]
10pub(crate) struct RemoveWhitespacesProcessor {}
11
12impl NodeProcessor for RemoveWhitespacesProcessor {
13    fn process_block(&mut self, block: &mut Block) {
14        block.clear_whitespaces();
15    }
16
17    fn process_function_call(&mut self, call: &mut FunctionCall) {
18        call.clear_whitespaces();
19        call.mutate_arguments().clear_whitespaces();
20    }
21
22    fn process_assign_statement(&mut self, assign: &mut AssignStatement) {
23        assign.clear_whitespaces();
24    }
25
26    fn process_compound_assign_statement(&mut self, assign: &mut CompoundAssignStatement) {
27        assign.clear_whitespaces();
28    }
29
30    fn process_do_statement(&mut self, statement: &mut DoStatement) {
31        statement.clear_whitespaces();
32    }
33
34    fn process_function_statement(&mut self, function: &mut FunctionStatement) {
35        function.clear_whitespaces();
36    }
37
38    fn process_generic_for_statement(&mut self, generic_for: &mut GenericForStatement) {
39        generic_for.clear_whitespaces();
40    }
41
42    fn process_if_statement(&mut self, if_statement: &mut IfStatement) {
43        if_statement.clear_whitespaces();
44    }
45
46    fn process_last_statement(&mut self, statement: &mut LastStatement) {
47        match statement {
48            LastStatement::Break(token) | LastStatement::Continue(token) => {
49                if let Some(token) = token {
50                    token.clear_whitespaces();
51                }
52            }
53            LastStatement::Return(statement) => statement.clear_whitespaces(),
54        }
55    }
56
57    fn process_local_assign_statement(&mut self, assign: &mut LocalAssignStatement) {
58        assign.clear_whitespaces();
59    }
60
61    fn process_local_function_statement(&mut self, function: &mut LocalFunctionStatement) {
62        function.clear_whitespaces();
63    }
64
65    fn process_numeric_for_statement(&mut self, numeric_for: &mut NumericForStatement) {
66        numeric_for.clear_whitespaces();
67    }
68
69    fn process_repeat_statement(&mut self, repeat: &mut RepeatStatement) {
70        repeat.clear_whitespaces();
71    }
72
73    fn process_while_statement(&mut self, statement: &mut WhileStatement) {
74        statement.clear_whitespaces();
75    }
76
77    fn process_type_declaration(&mut self, type_declaration: &mut TypeDeclarationStatement) {
78        type_declaration.clear_whitespaces();
79    }
80
81    fn process_type_function(&mut self, type_function: &mut TypeFunctionStatement) {
82        type_function.clear_whitespaces();
83    }
84
85    fn process_attributes(&mut self, attributes: &mut Attributes) {
86        attributes.clear_whitespaces();
87    }
88
89    fn process_literal_expression(&mut self, expression: &mut LiteralExpression) {
90        match expression {
91            LiteralExpression::True(token)
92            | LiteralExpression::False(token)
93            | LiteralExpression::Nil(token) => {
94                if let Some(token) = token {
95                    token.clear_whitespaces()
96                }
97            }
98            LiteralExpression::Number(_)
99            | LiteralExpression::String(_)
100            | LiteralExpression::Table(_) => {}
101        }
102    }
103
104    fn process_literal_table(&mut self, table: &mut LiteralTable) {
105        table.clear_whitespaces();
106    }
107
108    fn process_expression(&mut self, expression: &mut Expression) {
109        match expression {
110            Expression::False(token)
111            | Expression::Nil(token)
112            | Expression::True(token)
113            | Expression::VariableArguments(token) => {
114                if let Some(token) = token {
115                    token.clear_whitespaces()
116                }
117            }
118            Expression::Binary(_)
119            | Expression::Call(_)
120            | Expression::Field(_)
121            | Expression::Function(_)
122            | Expression::Identifier(_)
123            | Expression::If(_)
124            | Expression::Index(_)
125            | Expression::Number(_)
126            | Expression::Parenthese(_)
127            | Expression::String(_)
128            | Expression::InterpolatedString(_)
129            | Expression::Table(_)
130            | Expression::Unary(_)
131            | Expression::TypeCast(_) => {}
132        }
133    }
134
135    fn process_binary_expression(&mut self, binary: &mut BinaryExpression) {
136        binary.clear_whitespaces();
137    }
138
139    fn process_field_expression(&mut self, field: &mut FieldExpression) {
140        field.clear_whitespaces();
141    }
142
143    fn process_function_expression(&mut self, function: &mut FunctionExpression) {
144        function.clear_whitespaces();
145    }
146
147    fn process_if_expression(&mut self, if_expression: &mut IfExpression) {
148        if_expression.clear_whitespaces();
149    }
150
151    fn process_variable_expression(&mut self, identifier: &mut Identifier) {
152        identifier.clear_whitespaces();
153    }
154
155    fn process_index_expression(&mut self, index: &mut IndexExpression) {
156        index.clear_whitespaces();
157    }
158
159    fn process_number_expression(&mut self, number: &mut NumberExpression) {
160        number.clear_whitespaces();
161    }
162
163    fn process_parenthese_expression(&mut self, expression: &mut ParentheseExpression) {
164        expression.clear_whitespaces();
165    }
166
167    fn process_string_expression(&mut self, string: &mut StringExpression) {
168        string.clear_whitespaces();
169    }
170
171    fn process_table_expression(&mut self, table: &mut TableExpression) {
172        table.clear_whitespaces();
173    }
174
175    fn process_unary_expression(&mut self, unary: &mut UnaryExpression) {
176        unary.clear_whitespaces();
177    }
178
179    fn process_interpolated_string_expression(
180        &mut self,
181        string: &mut InterpolatedStringExpression,
182    ) {
183        string.clear_whitespaces();
184    }
185
186    fn process_type_cast_expression(&mut self, type_cast: &mut TypeCastExpression) {
187        type_cast.clear_whitespaces();
188    }
189
190    fn process_prefix_expression(&mut self, _: &mut Prefix) {}
191
192    fn process_type(&mut self, r#type: &mut Type) {
193        match r#type {
194            Type::True(token) | Type::False(token) | Type::Nil(token) => {
195                if let Some(token) = token {
196                    token.clear_whitespaces();
197                }
198            }
199            _ => {}
200        }
201    }
202
203    fn process_type_name(&mut self, type_name: &mut TypeName) {
204        type_name.clear_whitespaces();
205    }
206
207    fn process_type_field(&mut self, type_field: &mut TypeField) {
208        type_field.clear_whitespaces();
209    }
210
211    fn process_string_type(&mut self, string_type: &mut StringType) {
212        string_type.clear_whitespaces();
213    }
214
215    fn process_array_type(&mut self, array: &mut ArrayType) {
216        array.clear_whitespaces();
217    }
218
219    fn process_table_type(&mut self, table: &mut TableType) {
220        table.clear_whitespaces();
221    }
222
223    fn process_expression_type(&mut self, expression_type: &mut ExpressionType) {
224        expression_type.clear_whitespaces();
225    }
226
227    fn process_parenthese_type(&mut self, parenthese_type: &mut ParentheseType) {
228        parenthese_type.clear_whitespaces();
229    }
230
231    fn process_function_type(&mut self, function_type: &mut FunctionType) {
232        function_type.clear_whitespaces();
233    }
234
235    fn process_optional_type(&mut self, optional: &mut OptionalType) {
236        optional.clear_whitespaces();
237    }
238
239    fn process_intersection_type(&mut self, intersection: &mut IntersectionType) {
240        intersection.clear_whitespaces();
241    }
242
243    fn process_union_type(&mut self, union: &mut UnionType) {
244        union.clear_whitespaces();
245    }
246
247    fn process_type_pack(&mut self, type_pack: &mut TypePack) {
248        type_pack.clear_whitespaces();
249    }
250
251    fn process_generic_type_pack(&mut self, generic_type_pack: &mut GenericTypePack) {
252        generic_type_pack.clear_whitespaces();
253    }
254
255    fn process_variadic_type_pack(&mut self, variadic_type_pack: &mut VariadicTypePack) {
256        variadic_type_pack.clear_whitespaces();
257    }
258}
259
260pub const REMOVE_SPACES_RULE_NAME: &str = "remove_spaces";
261
262/// A rule that removes whitespaces associated with AST nodes.
263#[derive(Debug, Default, PartialEq, Eq)]
264pub struct RemoveSpaces {
265    metadata: RuleMetadata,
266}
267
268impl FlawlessRule for RemoveSpaces {
269    fn flawless_process(&self, block: &mut Block, _: &Context) {
270        let mut processor = RemoveWhitespacesProcessor::default();
271        DefaultVisitor::visit_block(block, &mut processor);
272    }
273}
274
275impl RuleConfiguration for RemoveSpaces {
276    fn configure(&mut self, properties: RuleProperties) -> Result<(), RuleConfigurationError> {
277        verify_no_rule_properties(&properties)?;
278        Ok(())
279    }
280
281    fn get_name(&self) -> &'static str {
282        REMOVE_SPACES_RULE_NAME
283    }
284
285    fn serialize_to_properties(&self) -> RuleProperties {
286        RuleProperties::new()
287    }
288
289    fn set_metadata(&mut self, metadata: RuleMetadata) {
290        self.metadata = metadata;
291    }
292
293    fn metadata(&self) -> &RuleMetadata {
294        &self.metadata
295    }
296}
297
298#[cfg(test)]
299mod test {
300    use super::*;
301    use crate::{
302        generator::{LuaGenerator, TokenBasedLuaGenerator},
303        rules::{ContextBuilder, Rule},
304        Parser, Resources,
305    };
306
307    use insta::assert_json_snapshot;
308
309    fn new_rule() -> RemoveSpaces {
310        RemoveSpaces::default()
311    }
312
313    #[test]
314    fn serialize_default_rule() {
315        let rule: Box<dyn Rule> = Box::new(new_rule());
316
317        assert_json_snapshot!(rule, @r###""remove_spaces""###);
318    }
319
320    #[test]
321    fn configure_with_extra_field_error() {
322        let result = json5::from_str::<Box<dyn Rule>>(
323            r#"{
324            rule: 'remove_spaces',
325            prop: "something",
326        }"#,
327        );
328        insta::assert_snapshot!(result.unwrap_err().to_string(), @"unexpected field 'prop' at line 1 column 1");
329    }
330
331    #[test]
332    fn remove_spaces_in_code() {
333        let code = include_str!("../../tests/test_cases/spaces_and_comments.lua");
334
335        let parser = Parser::default().preserve_tokens();
336
337        let mut block = parser.parse(code).expect("unable to parse code");
338
339        RemoveSpaces::default().flawless_process(
340            &mut block,
341            &ContextBuilder::new(".", &Resources::from_memory(), code).build(),
342        );
343
344        let mut generator = TokenBasedLuaGenerator::new(code);
345
346        generator.write_block(&block);
347
348        let code_output = &generator.into_string();
349
350        insta::assert_snapshot!("remove_spaces_in_code", code_output);
351    }
352}