darklua_core/rules/
remove_if_expression.rs1use crate::nodes::{
2 BinaryExpression, BinaryOperator, Block, Expression, IndexExpression, TableEntry,
3 TableExpression,
4};
5use crate::process::{DefaultVisitor, Evaluator, NodeProcessor, NodeVisitor};
6use crate::rules::{
7 Context, FlawlessRule, RuleConfiguration, RuleConfigurationError, RuleMetadata, RuleProperties,
8};
9
10use super::verify_no_rule_properties;
11
12#[derive(Default)]
13struct Processor {
14 evaluator: Evaluator,
15}
16
17impl Processor {
18 fn wrap_in_table(&self, expression: Expression) -> Expression {
19 TableExpression::new(vec![TableEntry::from_value({
20 if self.evaluator.can_return_multiple_values(&expression) {
21 expression.in_parentheses()
22 } else {
23 expression
24 }
25 })])
26 .into()
27 }
28
29 fn convert_if_branch(
30 &self,
31 condition: Expression,
32 result: Expression,
33 else_result: Expression,
34 ) -> Expression {
35 if self
36 .evaluator
37 .evaluate(&result)
38 .is_truthy()
39 .unwrap_or_default()
40 {
41 BinaryExpression::new(
42 BinaryOperator::Or,
43 BinaryExpression::new(BinaryOperator::And, condition, result),
44 else_result,
45 )
46 .into()
47 } else {
48 IndexExpression::new(
49 Expression::from(BinaryExpression::new(
50 BinaryOperator::Or,
51 BinaryExpression::new(
52 BinaryOperator::And,
53 condition,
54 self.wrap_in_table(result),
55 ),
56 self.wrap_in_table(else_result),
57 )),
58 Expression::from(1),
59 )
60 .into()
61 }
62 }
63}
64
65impl NodeProcessor for Processor {
66 fn process_expression(&mut self, expression: &mut Expression) {
67 if let Expression::If(if_expression) = expression {
68 let else_result = if_expression.iter_branches().fold(
69 if_expression.get_else_result().clone(),
70 |else_result, branch| {
71 self.convert_if_branch(
72 branch.get_condition().clone(),
73 branch.get_result().clone(),
74 else_result,
75 )
76 },
77 );
78
79 *expression = self.convert_if_branch(
80 if_expression.get_condition().clone(),
81 if_expression.get_result().clone(),
82 else_result,
83 );
84 }
85 }
86}
87
88pub const REMOVE_IF_EXPRESSION_RULE_NAME: &str = "remove_if_expression";
89
90#[derive(Debug, Default, PartialEq, Eq)]
92pub struct RemoveIfExpression {
93 metadata: RuleMetadata,
94}
95
96impl FlawlessRule for RemoveIfExpression {
97 fn flawless_process(&self, block: &mut Block, _: &Context) {
98 let mut processor = Processor::default();
99 DefaultVisitor::visit_block(block, &mut processor);
100 }
101}
102
103impl RuleConfiguration for RemoveIfExpression {
104 fn configure(&mut self, properties: RuleProperties) -> Result<(), RuleConfigurationError> {
105 verify_no_rule_properties(&properties)?;
106
107 Ok(())
108 }
109
110 fn get_name(&self) -> &'static str {
111 REMOVE_IF_EXPRESSION_RULE_NAME
112 }
113
114 fn serialize_to_properties(&self) -> RuleProperties {
115 RuleProperties::new()
116 }
117
118 fn set_metadata(&mut self, metadata: RuleMetadata) {
119 self.metadata = metadata;
120 }
121
122 fn metadata(&self) -> &RuleMetadata {
123 &self.metadata
124 }
125}
126
127#[cfg(test)]
128mod test {
129 use super::*;
130 use crate::rules::Rule;
131
132 use insta::assert_json_snapshot;
133
134 fn new_rule() -> RemoveIfExpression {
135 RemoveIfExpression::default()
136 }
137
138 #[test]
139 fn serialize_default_rule() {
140 let rule: Box<dyn Rule> = Box::new(new_rule());
141
142 assert_json_snapshot!(rule, @r###""remove_if_expression""###);
143 }
144
145 #[test]
146 fn configure_with_extra_field_error() {
147 let result = json5::from_str::<Box<dyn Rule>>(
148 r#"{
149 rule: 'remove_if_expression',
150 prop: "something",
151 }"#,
152 );
153 insta::assert_snapshot!(result.unwrap_err().to_string(), @"unexpected field 'prop' at line 1 column 1");
154 }
155}