mago_syntax/utils/
assignment.rs

1use crate::ast::*;
2
3/// Get the assignment operation from an expression.
4///
5/// This function will recursively search through the expression and its children to find
6///  the first assignment operation.
7///
8/// If no assignment operation is found, it will return `None`.
9#[inline]
10pub fn get_assignment_from_expression(expression: &Expression) -> Option<&Assignment> {
11    match &expression {
12        Expression::Assignment(assignment_operation) => Some(assignment_operation),
13        Expression::Parenthesized(parenthesized) => get_assignment_from_expression(&parenthesized.expression),
14        Expression::Binary(operation) => {
15            get_assignment_from_expression(&operation.lhs).or_else(|| get_assignment_from_expression(&operation.rhs))
16        }
17        Expression::UnaryPrefix(operation) => get_assignment_from_expression(&operation.operand),
18        Expression::UnaryPostfix(operation) => get_assignment_from_expression(&operation.operand),
19        Expression::Conditional(conditional) => get_assignment_from_expression(&conditional.condition)
20            .or_else(|| conditional.then.as_ref().and_then(|then| get_assignment_from_expression(then)))
21            .or_else(|| get_assignment_from_expression(&conditional.r#else)),
22        Expression::Array(array) => array.elements.iter().find_map(|element| match &element {
23            ArrayElement::KeyValue(key_value_array_element) => {
24                get_assignment_from_expression(&key_value_array_element.key)
25                    .or_else(|| get_assignment_from_expression(&key_value_array_element.value))
26            }
27            ArrayElement::Value(value_array_element) => get_assignment_from_expression(&value_array_element.value),
28            ArrayElement::Variadic(variadic_array_element) => {
29                get_assignment_from_expression(&variadic_array_element.value)
30            }
31            ArrayElement::Missing(_) => None,
32        }),
33        Expression::LegacyArray(legacy_array) => legacy_array.elements.iter().find_map(|element| match &element {
34            ArrayElement::KeyValue(key_value_array_element) => {
35                get_assignment_from_expression(&key_value_array_element.key)
36                    .or_else(|| get_assignment_from_expression(&key_value_array_element.value))
37            }
38            ArrayElement::Value(value_array_element) => get_assignment_from_expression(&value_array_element.value),
39            ArrayElement::Variadic(variadic_array_element) => {
40                get_assignment_from_expression(&variadic_array_element.value)
41            }
42            ArrayElement::Missing(_) => None,
43        }),
44        Expression::List(list) => list.elements.iter().find_map(|element| match &element {
45            ArrayElement::KeyValue(key_value_array_element) => {
46                get_assignment_from_expression(&key_value_array_element.key)
47                    .or_else(|| get_assignment_from_expression(&key_value_array_element.value))
48            }
49            ArrayElement::Value(value_array_element) => get_assignment_from_expression(&value_array_element.value),
50            ArrayElement::Variadic(variadic_array_element) => {
51                get_assignment_from_expression(&variadic_array_element.value)
52            }
53            ArrayElement::Missing(_) => None,
54        }),
55        Expression::ArrayAccess(array_access) => get_assignment_from_expression(&array_access.array)
56            .or_else(|| get_assignment_from_expression(&array_access.index)),
57        Expression::ArrayAppend(array_append) => get_assignment_from_expression(&array_append.array),
58        Expression::Match(r#match) => get_assignment_from_expression(&r#match.expression).or_else(|| {
59            r#match.arms.iter().find_map(|arm| match arm {
60                MatchArm::Expression(match_expression_arm) => match_expression_arm
61                    .conditions
62                    .iter()
63                    .find_map(|condition| get_assignment_from_expression(condition))
64                    .or_else(|| get_assignment_from_expression(&match_expression_arm.expression)),
65                MatchArm::Default(match_default_arm) => get_assignment_from_expression(&match_default_arm.expression),
66            })
67        }),
68        Expression::Yield(r#yield) => match r#yield {
69            Yield::Value(yield_value) => {
70                yield_value.value.as_ref().and_then(|value| get_assignment_from_expression(value))
71            }
72            Yield::Pair(yield_pair) => get_assignment_from_expression(&yield_pair.key)
73                .or_else(|| get_assignment_from_expression(&yield_pair.value)),
74            Yield::From(yield_from) => get_assignment_from_expression(&yield_from.iterator),
75        },
76        Expression::Construct(construct) => match construct {
77            Construct::Isset(isset_construct) => {
78                isset_construct.values.iter().find_map(|v| get_assignment_from_expression(v))
79            }
80            Construct::Empty(empty_construct) => get_assignment_from_expression(&empty_construct.value),
81            Construct::Eval(eval_construct) => get_assignment_from_expression(&eval_construct.value),
82            Construct::Include(include_construct) => get_assignment_from_expression(&include_construct.value),
83            Construct::IncludeOnce(include_once_construct) => {
84                get_assignment_from_expression(&include_once_construct.value)
85            }
86            Construct::Require(require_construct) => get_assignment_from_expression(&require_construct.value),
87            Construct::RequireOnce(require_once_construct) => {
88                get_assignment_from_expression(&require_once_construct.value)
89            }
90            Construct::Print(print_construct) => get_assignment_from_expression(&print_construct.value),
91            Construct::Exit(exit_construct) => exit_construct.arguments.as_ref().and_then(|arguments| {
92                arguments.arguments.iter().find_map(|argument| {
93                    get_assignment_from_expression(match &argument {
94                        Argument::Positional(positional_argument) => &positional_argument.value,
95                        Argument::Named(named_argument) => &named_argument.value,
96                    })
97                })
98            }),
99            Construct::Die(die_construct) => die_construct.arguments.as_ref().and_then(|arguments| {
100                arguments.arguments.iter().find_map(|argument| {
101                    get_assignment_from_expression(match &argument {
102                        Argument::Positional(positional_argument) => &positional_argument.value,
103                        Argument::Named(named_argument) => &named_argument.value,
104                    })
105                })
106            }),
107        },
108        Expression::Throw(throw) => get_assignment_from_expression(&throw.exception),
109        Expression::Clone(clone) => get_assignment_from_expression(&clone.object),
110        Expression::Call(call) => match &call {
111            Call::Function(function_call) => get_assignment_from_expression(&function_call.function).or_else(|| {
112                function_call.argument_list.arguments.iter().find_map(|argument| match &argument {
113                    Argument::Positional(positional_argument) => {
114                        get_assignment_from_expression(&positional_argument.value)
115                    }
116                    Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
117                })
118            }),
119            Call::Method(method_call) => get_assignment_from_expression(&method_call.object)
120                .or_else(|| match &method_call.method {
121                    ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
122                        get_assignment_from_expression(&class_like_member_expression_selector.expression)
123                    }
124                    _ => None,
125                })
126                .or_else(|| {
127                    method_call.argument_list.arguments.iter().find_map(|argument| match &argument {
128                        Argument::Positional(positional_argument) => {
129                            get_assignment_from_expression(&positional_argument.value)
130                        }
131                        Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
132                    })
133                }),
134            Call::NullSafeMethod(null_safe_method_call) => {
135                get_assignment_from_expression(&null_safe_method_call.object)
136                    .or_else(|| match &null_safe_method_call.method {
137                        ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
138                            get_assignment_from_expression(&class_like_member_expression_selector.expression)
139                        }
140                        _ => None,
141                    })
142                    .or_else(|| {
143                        null_safe_method_call.argument_list.arguments.iter().find_map(|argument| match &argument {
144                            Argument::Positional(positional_argument) => {
145                                get_assignment_from_expression(&positional_argument.value)
146                            }
147                            Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
148                        })
149                    })
150            }
151            Call::StaticMethod(static_method_call) => get_assignment_from_expression(&static_method_call.class)
152                .or_else(|| match &static_method_call.method {
153                    ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
154                        get_assignment_from_expression(&class_like_member_expression_selector.expression)
155                    }
156                    _ => None,
157                })
158                .or_else(|| {
159                    static_method_call.argument_list.arguments.iter().find_map(|argument| match &argument {
160                        Argument::Positional(positional_argument) => {
161                            get_assignment_from_expression(&positional_argument.value)
162                        }
163                        Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
164                    })
165                }),
166        },
167        Expression::Access(access) => match access {
168            Access::Property(property_access) => {
169                get_assignment_from_expression(&property_access.object).or_else(|| match &property_access.property {
170                    ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
171                        get_assignment_from_expression(&class_like_member_expression_selector.expression)
172                    }
173                    _ => None,
174                })
175            }
176            Access::NullSafeProperty(null_safe_property_access) => {
177                get_assignment_from_expression(&null_safe_property_access.object).or_else(|| {
178                    match &null_safe_property_access.property {
179                        ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
180                            get_assignment_from_expression(&class_like_member_expression_selector.expression)
181                        }
182                        _ => None,
183                    }
184                })
185            }
186            Access::StaticProperty(static_property_access) => {
187                get_assignment_from_expression(&static_property_access.class)
188            }
189            Access::ClassConstant(class_constant_access) => {
190                get_assignment_from_expression(&class_constant_access.class).or_else(|| {
191                    match &class_constant_access.constant {
192                        ClassLikeConstantSelector::Expression(class_like_member_expression_selector) => {
193                            get_assignment_from_expression(&class_like_member_expression_selector.expression)
194                        }
195                        _ => None,
196                    }
197                })
198            }
199        },
200        Expression::ClosureCreation(closure_creation) => match closure_creation {
201            ClosureCreation::Function(function_closure_creation) => {
202                get_assignment_from_expression(&function_closure_creation.function)
203            }
204            ClosureCreation::Method(method_closure_creation) => {
205                get_assignment_from_expression(&method_closure_creation.object).or_else(|| {
206                    match &method_closure_creation.method {
207                        ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
208                            get_assignment_from_expression(&class_like_member_expression_selector.expression)
209                        }
210                        _ => None,
211                    }
212                })
213            }
214            ClosureCreation::StaticMethod(static_method_closure_creation) => {
215                get_assignment_from_expression(&static_method_closure_creation.class).or_else(|| {
216                    match &static_method_closure_creation.method {
217                        ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
218                            get_assignment_from_expression(&class_like_member_expression_selector.expression)
219                        }
220                        _ => None,
221                    }
222                })
223            }
224        },
225        Expression::Instantiation(instantiation) => {
226            get_assignment_from_expression(&instantiation.class).or_else(|| {
227                instantiation.argument_list.as_ref().and_then(|arguments| {
228                    arguments.arguments.iter().find_map(|argument| match &argument {
229                        Argument::Positional(positional_argument) => {
230                            get_assignment_from_expression(&positional_argument.value)
231                        }
232                        Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
233                    })
234                })
235            })
236        }
237        _ => None,
238    }
239}