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