mago_syntax/ast/ast/function_like/
parameter.rs1use serde::Serialize;
2
3use mago_span::HasSpan;
4use mago_span::Span;
5
6use crate::ast::ast::attribute::AttributeList;
7use crate::ast::ast::class_like::property::PropertyHookList;
8use crate::ast::ast::expression::Expression;
9use crate::ast::ast::modifier::Modifier;
10use crate::ast::ast::type_hint::Hint;
11use crate::ast::ast::variable::DirectVariable;
12use crate::ast::sequence::Sequence;
13use crate::ast::sequence::TokenSeparatedSequence;
14
15#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
17pub struct FunctionLikeParameterList<'arena> {
18 pub left_parenthesis: Span,
19 pub parameters: TokenSeparatedSequence<'arena, FunctionLikeParameter<'arena>>,
20 pub right_parenthesis: Span,
21}
22
23#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
27pub struct FunctionLikeParameter<'arena> {
28 pub attribute_lists: Sequence<'arena, AttributeList<'arena>>,
29 pub modifiers: Sequence<'arena, Modifier<'arena>>,
30 pub hint: Option<Hint<'arena>>,
31 pub ampersand: Option<Span>,
32 pub ellipsis: Option<Span>,
33 pub variable: DirectVariable<'arena>,
34 pub default_value: Option<FunctionLikeParameterDefaultValue<'arena>>,
35 pub hooks: Option<PropertyHookList<'arena>>,
36}
37
38#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
40pub struct FunctionLikeParameterDefaultValue<'arena> {
41 pub equals: Span,
42 pub value: Expression<'arena>,
43}
44
45impl FunctionLikeParameter<'_> {
46 #[must_use]
55 pub fn is_promoted_property(&self) -> bool {
56 !self.modifiers.is_empty() || self.hooks.is_some()
57 }
58
59 #[inline]
60 #[must_use]
61 pub const fn is_variadic(&self) -> bool {
62 self.ellipsis.is_some()
63 }
64
65 #[inline]
66 #[must_use]
67 pub const fn is_reference(&self) -> bool {
68 self.ampersand.is_some()
69 }
70}
71
72impl HasSpan for FunctionLikeParameterList<'_> {
73 fn span(&self) -> Span {
74 Span::between(self.left_parenthesis, self.right_parenthesis)
75 }
76}
77
78impl HasSpan for FunctionLikeParameter<'_> {
79 fn span(&self) -> Span {
80 let right = self.hooks.as_ref().map_or_else(
81 || self.default_value.as_ref().map_or_else(|| self.variable.span(), HasSpan::span),
82 HasSpan::span,
83 );
84
85 if let Some(attribute) = self.attribute_lists.first() {
86 return Span::between(attribute.span(), right);
87 }
88
89 if let Some(modifier) = self.modifiers.first() {
90 return Span::between(modifier.span(), right);
91 }
92
93 if let Some(type_hint) = &self.hint {
94 return Span::between(type_hint.span(), right);
95 }
96
97 if let Some(ellipsis) = self.ellipsis {
98 return Span::between(ellipsis, right);
99 }
100
101 if let Some(ampersand) = self.ampersand {
102 return Span::between(ampersand, right);
103 }
104
105 Span::between(self.variable.span(), right)
106 }
107}
108
109impl HasSpan for FunctionLikeParameterDefaultValue<'_> {
110 fn span(&self) -> Span {
111 Span::between(self.equals, self.value.span())
112 }
113}