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, 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::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
94impl FlawlessRule for RemoveIfExpression {
95 fn flawless_process(&self, block: &mut Block, _: &Context) {
96 let mut processor = Processor::default();
97 DefaultVisitor::visit_block(block, &mut processor);
98 }
99}
100
101impl RuleConfiguration for RemoveIfExpression {
102 fn configure(&mut self, properties: RuleProperties) -> Result<(), RuleConfigurationError> {
103 verify_no_rule_properties(&properties)?;
104
105 Ok(())
106 }
107
108 fn get_name(&self) -> &'static str {
109 REMOVE_IF_EXPRESSION_RULE_NAME
110 }
111
112 fn serialize_to_properties(&self) -> RuleProperties {
113 RuleProperties::new()
114 }
115}
116
117#[cfg(test)]
118mod test {
119 use super::*;
120 use crate::rules::Rule;
121
122 use insta::assert_json_snapshot;
123
124 fn new_rule() -> RemoveIfExpression {
125 RemoveIfExpression::default()
126 }
127
128 #[test]
129 fn serialize_default_rule() {
130 let rule: Box<dyn Rule> = Box::new(new_rule());
131
132 assert_json_snapshot!("default_remove_if_expression", rule);
133 }
134
135 #[test]
136 fn configure_with_extra_field_error() {
137 let result = json5::from_str::<Box<dyn Rule>>(
138 r#"{
139 rule: 'remove_if_expression',
140 prop: "something",
141 }"#,
142 );
143 pretty_assertions::assert_eq!(result.unwrap_err().to_string(), "unexpected field 'prop'");
144 }
145}