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<'a, 'arena>(
11    expression: &'a Expression<'arena>,
12) -> Option<&'a Assignment<'arena>> {
13    match &expression {
14        Expression::Assignment(assignment_operation) => Some(assignment_operation),
15        Expression::Parenthesized(parenthesized) => get_assignment_from_expression(parenthesized.expression),
16        Expression::Binary(operation) => {
17            get_assignment_from_expression(operation.lhs).or_else(|| get_assignment_from_expression(operation.rhs))
18        }
19        Expression::UnaryPrefix(operation) => get_assignment_from_expression(operation.operand),
20        Expression::UnaryPostfix(operation) => get_assignment_from_expression(operation.operand),
21        Expression::Conditional(conditional) => get_assignment_from_expression(conditional.condition)
22            .or_else(|| conditional.then.as_ref().and_then(|then| get_assignment_from_expression(then)))
23            .or_else(|| get_assignment_from_expression(conditional.r#else)),
24        Expression::Array(array) => array.elements.iter().find_map(|element| match &element {
25            ArrayElement::KeyValue(key_value_array_element) => {
26                get_assignment_from_expression(key_value_array_element.key)
27                    .or_else(|| get_assignment_from_expression(key_value_array_element.value))
28            }
29            ArrayElement::Value(value_array_element) => get_assignment_from_expression(value_array_element.value),
30            ArrayElement::Variadic(variadic_array_element) => {
31                get_assignment_from_expression(variadic_array_element.value)
32            }
33            ArrayElement::Missing(_) => None,
34        }),
35        Expression::LegacyArray(legacy_array) => legacy_array.elements.iter().find_map(|element| match &element {
36            ArrayElement::KeyValue(key_value_array_element) => {
37                get_assignment_from_expression(key_value_array_element.key)
38                    .or_else(|| get_assignment_from_expression(key_value_array_element.value))
39            }
40            ArrayElement::Value(value_array_element) => get_assignment_from_expression(value_array_element.value),
41            ArrayElement::Variadic(variadic_array_element) => {
42                get_assignment_from_expression(variadic_array_element.value)
43            }
44            ArrayElement::Missing(_) => None,
45        }),
46        Expression::List(list) => list.elements.iter().find_map(|element| match &element {
47            ArrayElement::KeyValue(key_value_array_element) => {
48                get_assignment_from_expression(key_value_array_element.key)
49                    .or_else(|| get_assignment_from_expression(key_value_array_element.value))
50            }
51            ArrayElement::Value(value_array_element) => get_assignment_from_expression(value_array_element.value),
52            ArrayElement::Variadic(variadic_array_element) => {
53                get_assignment_from_expression(variadic_array_element.value)
54            }
55            ArrayElement::Missing(_) => None,
56        }),
57        Expression::ArrayAccess(array_access) => get_assignment_from_expression(array_access.array)
58            .or_else(|| get_assignment_from_expression(array_access.index)),
59        Expression::ArrayAppend(array_append) => get_assignment_from_expression(array_append.array),
60        Expression::Match(r#match) => get_assignment_from_expression(r#match.expression).or_else(|| {
61            r#match.arms.iter().find_map(|arm| match arm {
62                MatchArm::Expression(match_expression_arm) => match_expression_arm
63                    .conditions
64                    .iter()
65                    .find_map(|condition| get_assignment_from_expression(condition))
66                    .or_else(|| get_assignment_from_expression(match_expression_arm.expression)),
67                MatchArm::Default(match_default_arm) => get_assignment_from_expression(match_default_arm.expression),
68            })
69        }),
70        Expression::Yield(r#yield) => match r#yield {
71            Yield::Value(yield_value) => {
72                yield_value.value.as_ref().and_then(|value| get_assignment_from_expression(value))
73            }
74            Yield::Pair(yield_pair) => get_assignment_from_expression(yield_pair.key)
75                .or_else(|| get_assignment_from_expression(yield_pair.value)),
76            Yield::From(yield_from) => get_assignment_from_expression(yield_from.iterator),
77        },
78        Expression::Construct(construct) => match construct {
79            Construct::Isset(isset_construct) => {
80                isset_construct.values.iter().find_map(|v| get_assignment_from_expression(v))
81            }
82            Construct::Empty(empty_construct) => get_assignment_from_expression(empty_construct.value),
83            Construct::Eval(eval_construct) => get_assignment_from_expression(eval_construct.value),
84            Construct::Include(include_construct) => get_assignment_from_expression(include_construct.value),
85            Construct::IncludeOnce(include_once_construct) => {
86                get_assignment_from_expression(include_once_construct.value)
87            }
88            Construct::Require(require_construct) => get_assignment_from_expression(require_construct.value),
89            Construct::RequireOnce(require_once_construct) => {
90                get_assignment_from_expression(require_once_construct.value)
91            }
92            Construct::Print(print_construct) => get_assignment_from_expression(print_construct.value),
93            Construct::Exit(exit_construct) => exit_construct.arguments.as_ref().and_then(|arguments| {
94                arguments.arguments.iter().find_map(|argument| {
95                    get_assignment_from_expression(match &argument {
96                        Argument::Positional(positional_argument) => &positional_argument.value,
97                        Argument::Named(named_argument) => &named_argument.value,
98                    })
99                })
100            }),
101            Construct::Die(die_construct) => die_construct.arguments.as_ref().and_then(|arguments| {
102                arguments.arguments.iter().find_map(|argument| {
103                    get_assignment_from_expression(match &argument {
104                        Argument::Positional(positional_argument) => &positional_argument.value,
105                        Argument::Named(named_argument) => &named_argument.value,
106                    })
107                })
108            }),
109        },
110        Expression::Throw(throw) => get_assignment_from_expression(throw.exception),
111        Expression::Clone(clone) => get_assignment_from_expression(clone.object),
112        Expression::Call(call) => match &call {
113            Call::Function(function_call) => get_assignment_from_expression(function_call.function).or_else(|| {
114                function_call.argument_list.arguments.iter().find_map(|argument| match &argument {
115                    Argument::Positional(positional_argument) => {
116                        get_assignment_from_expression(&positional_argument.value)
117                    }
118                    Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
119                })
120            }),
121            Call::Method(method_call) => get_assignment_from_expression(method_call.object)
122                .or_else(|| match &method_call.method {
123                    ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
124                        get_assignment_from_expression(class_like_member_expression_selector.expression)
125                    }
126                    _ => None,
127                })
128                .or_else(|| {
129                    method_call.argument_list.arguments.iter().find_map(|argument| match &argument {
130                        Argument::Positional(positional_argument) => {
131                            get_assignment_from_expression(&positional_argument.value)
132                        }
133                        Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
134                    })
135                }),
136            Call::NullSafeMethod(null_safe_method_call) => get_assignment_from_expression(null_safe_method_call.object)
137                .or_else(|| match &null_safe_method_call.method {
138                    ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
139                        get_assignment_from_expression(class_like_member_expression_selector.expression)
140                    }
141                    _ => None,
142                })
143                .or_else(|| {
144                    null_safe_method_call.argument_list.arguments.iter().find_map(|argument| match &argument {
145                        Argument::Positional(positional_argument) => {
146                            get_assignment_from_expression(&positional_argument.value)
147                        }
148                        Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
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) => get_assignment_from_expression(class_constant_access.class)
190                .or_else(|| match &class_constant_access.constant {
191                    ClassLikeConstantSelector::Expression(class_like_member_expression_selector) => {
192                        get_assignment_from_expression(class_like_member_expression_selector.expression)
193                    }
194                    _ => None,
195                }),
196        },
197        Expression::ClosureCreation(closure_creation) => match closure_creation {
198            ClosureCreation::Function(function_closure_creation) => {
199                get_assignment_from_expression(function_closure_creation.function)
200            }
201            ClosureCreation::Method(method_closure_creation) => get_assignment_from_expression(
202                method_closure_creation.object,
203            )
204            .or_else(|| match &method_closure_creation.method {
205                ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
206                    get_assignment_from_expression(class_like_member_expression_selector.expression)
207                }
208                _ => None,
209            }),
210            ClosureCreation::StaticMethod(static_method_closure_creation) => {
211                get_assignment_from_expression(static_method_closure_creation.class).or_else(|| {
212                    match &static_method_closure_creation.method {
213                        ClassLikeMemberSelector::Expression(class_like_member_expression_selector) => {
214                            get_assignment_from_expression(class_like_member_expression_selector.expression)
215                        }
216                        _ => None,
217                    }
218                })
219            }
220        },
221        Expression::Instantiation(instantiation) => get_assignment_from_expression(instantiation.class).or_else(|| {
222            instantiation.argument_list.as_ref().and_then(|arguments| {
223                arguments.arguments.iter().find_map(|argument| match &argument {
224                    Argument::Positional(positional_argument) => {
225                        get_assignment_from_expression(&positional_argument.value)
226                    }
227                    Argument::Named(named_argument) => get_assignment_from_expression(&named_argument.value),
228                })
229            })
230        }),
231        _ => None,
232    }
233}