darklua_core/rules/
replace_referenced_tokens.rs1use crate::nodes::*;
2use crate::process::{DefaultVisitor, NodeProcessor, NodeVisitor};
3use crate::rules::{
4 Context, FlawlessRule, RuleConfiguration, RuleConfigurationError, 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<'a> NodeProcessor for Processor<'a> {
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_expression(&mut self, expression: &mut Expression) {
90 match expression {
91 Expression::False(token)
92 | Expression::Nil(token)
93 | Expression::True(token)
94 | Expression::VariableArguments(token) => {
95 if let Some(token) = token {
96 token.replace_referenced_tokens(self.code);
97 }
98 }
99 Expression::Binary(_)
100 | Expression::Call(_)
101 | Expression::Field(_)
102 | Expression::Function(_)
103 | Expression::Identifier(_)
104 | Expression::If(_)
105 | Expression::Index(_)
106 | Expression::Number(_)
107 | Expression::Parenthese(_)
108 | Expression::String(_)
109 | Expression::InterpolatedString(_)
110 | Expression::Table(_)
111 | Expression::Unary(_)
112 | Expression::TypeCast(_) => {}
113 }
114 }
115
116 fn process_binary_expression(&mut self, binary: &mut BinaryExpression) {
117 binary.replace_referenced_tokens(self.code);
118 }
119
120 fn process_field_expression(&mut self, field: &mut FieldExpression) {
121 field.replace_referenced_tokens(self.code);
122 }
123
124 fn process_function_expression(&mut self, function: &mut FunctionExpression) {
125 function.replace_referenced_tokens(self.code);
126 }
127
128 fn process_if_expression(&mut self, if_expression: &mut IfExpression) {
129 if_expression.replace_referenced_tokens(self.code);
130 }
131
132 fn process_variable_expression(&mut self, identifier: &mut Identifier) {
133 identifier.replace_referenced_tokens(self.code);
134 }
135
136 fn process_index_expression(&mut self, index: &mut IndexExpression) {
137 index.replace_referenced_tokens(self.code);
138 }
139
140 fn process_number_expression(&mut self, number: &mut NumberExpression) {
141 number.replace_referenced_tokens(self.code);
142 }
143
144 fn process_parenthese_expression(&mut self, expression: &mut ParentheseExpression) {
145 expression.replace_referenced_tokens(self.code);
146 }
147
148 fn process_string_expression(&mut self, string: &mut StringExpression) {
149 string.replace_referenced_tokens(self.code);
150 }
151
152 fn process_interpolated_string_expression(
153 &mut self,
154 string: &mut InterpolatedStringExpression,
155 ) {
156 string.replace_referenced_tokens(self.code);
157 }
158
159 fn process_table_expression(&mut self, table: &mut TableExpression) {
160 table.replace_referenced_tokens(self.code);
161 }
162
163 fn process_unary_expression(&mut self, unary: &mut UnaryExpression) {
164 unary.replace_referenced_tokens(self.code);
165 }
166
167 fn process_type_cast_expression(&mut self, type_cast: &mut TypeCastExpression) {
168 type_cast.replace_referenced_tokens(self.code);
169 }
170
171 fn process_prefix_expression(&mut self, _: &mut Prefix) {}
172
173 fn process_type(&mut self, r#type: &mut Type) {
174 match r#type {
175 Type::True(token) | Type::False(token) | Type::Nil(token) => {
176 if let Some(token) = token {
177 token.replace_referenced_tokens(self.code)
178 }
179 }
180 _ => {}
181 }
182 }
183
184 fn process_type_name(&mut self, type_name: &mut TypeName) {
185 type_name.replace_referenced_tokens(self.code);
186 }
187
188 fn process_type_field(&mut self, type_field: &mut TypeField) {
189 type_field.replace_referenced_tokens(self.code);
190 }
191
192 fn process_string_type(&mut self, string_type: &mut StringType) {
193 string_type.replace_referenced_tokens(self.code);
194 }
195
196 fn process_array_type(&mut self, array: &mut ArrayType) {
197 array.replace_referenced_tokens(self.code);
198 }
199
200 fn process_table_type(&mut self, table: &mut TableType) {
201 table.replace_referenced_tokens(self.code);
202 }
203
204 fn process_expression_type(&mut self, expression_type: &mut ExpressionType) {
205 expression_type.replace_referenced_tokens(self.code);
206 }
207
208 fn process_parenthese_type(&mut self, parenthese_type: &mut ParentheseType) {
209 parenthese_type.replace_referenced_tokens(self.code);
210 }
211
212 fn process_function_type(&mut self, function_type: &mut FunctionType) {
213 function_type.replace_referenced_tokens(self.code);
214 }
215
216 fn process_optional_type(&mut self, optional: &mut OptionalType) {
217 optional.replace_referenced_tokens(self.code);
218 }
219
220 fn process_intersection_type(&mut self, intersection: &mut IntersectionType) {
221 intersection.replace_referenced_tokens(self.code);
222 }
223
224 fn process_union_type(&mut self, union: &mut UnionType) {
225 union.replace_referenced_tokens(self.code);
226 }
227
228 fn process_type_pack(&mut self, type_pack: &mut TypePack) {
229 type_pack.replace_referenced_tokens(self.code);
230 }
231
232 fn process_generic_type_pack(&mut self, generic_type_pack: &mut GenericTypePack) {
233 generic_type_pack.replace_referenced_tokens(self.code);
234 }
235
236 fn process_variadic_type_pack(&mut self, variadic_type_pack: &mut VariadicTypePack) {
237 variadic_type_pack.replace_referenced_tokens(self.code);
238 }
239}
240
241pub const REPLACE_REFERENCED_TOKENS: &str = "replace_referenced_tokens";
242
243#[derive(Debug, Default, PartialEq, Eq)]
244pub(crate) struct ReplaceReferencedTokens {}
245
246impl FlawlessRule for ReplaceReferencedTokens {
247 fn flawless_process(&self, block: &mut Block, context: &Context) {
248 let mut processor = Processor::new(context.original_code());
249 DefaultVisitor::visit_block(block, &mut processor);
250 }
251}
252
253impl RuleConfiguration for ReplaceReferencedTokens {
254 fn configure(&mut self, properties: RuleProperties) -> Result<(), RuleConfigurationError> {
255 verify_no_rule_properties(&properties)?;
256 Ok(())
257 }
258
259 fn get_name(&self) -> &'static str {
260 REPLACE_REFERENCED_TOKENS
261 }
262
263 fn serialize_to_properties(&self) -> RuleProperties {
264 RuleProperties::new()
265 }
266}
267
268#[cfg(test)]
269mod test {
270 use super::*;
271 use crate::{
272 generator::{LuaGenerator, TokenBasedLuaGenerator},
273 rules::{ContextBuilder, Rule},
274 Parser, Resources,
275 };
276
277 use insta::assert_json_snapshot;
278
279 fn new_rule() -> ReplaceReferencedTokens {
280 ReplaceReferencedTokens::default()
281 }
282
283 #[test]
284 fn serialize_default_rule() {
285 let rule: Box<dyn Rule> = Box::new(new_rule());
286
287 assert_json_snapshot!("default_replace_referenced_tokens", rule);
288 }
289
290 fn test_code(code: &str) {
291 let parser = Parser::default().preserve_tokens();
292
293 let mut block = parser.parse(code).expect("unable to parse code");
294
295 ReplaceReferencedTokens::default().flawless_process(
296 &mut block,
297 &ContextBuilder::new(".", &Resources::from_memory(), code).build(),
298 );
299
300 let mut generator = TokenBasedLuaGenerator::new("");
303
304 generator.write_block(&block);
305 }
306
307 #[test]
308 fn test_fuzzed_case_a() {
309 let code = include_str!("../../tests/fuzzed_test_cases/a.lua");
310 test_code(code);
311 }
312
313 #[test]
314 fn test_fuzzed_case_b() {
315 let code = include_str!("../../tests/fuzzed_test_cases/b.lua");
316 test_code(code);
317 }
318
319 #[test]
320 fn test_fuzzed_case_c() {
321 let code = include_str!("../../tests/fuzzed_test_cases/c.lua");
322 test_code(code);
323 }
324}