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 pub fn is_promoted_property(&self) -> bool {
55 !self.modifiers.is_empty() || self.hooks.is_some()
56 }
57
58 #[inline]
59 pub const fn is_variadic(&self) -> bool {
60 self.ellipsis.is_some()
61 }
62
63 #[inline]
64 pub const fn is_reference(&self) -> bool {
65 self.ampersand.is_some()
66 }
67}
68
69impl HasSpan for FunctionLikeParameterList<'_> {
70 fn span(&self) -> Span {
71 Span::between(self.left_parenthesis, self.right_parenthesis)
72 }
73}
74
75impl HasSpan for FunctionLikeParameter<'_> {
76 fn span(&self) -> Span {
77 let right = self.hooks.as_ref().map(|hooks| hooks.span()).unwrap_or_else(|| {
78 self.default_value.as_ref().map_or_else(|| self.variable.span(), |default_value| default_value.span())
79 });
80
81 if let Some(attribute) = self.attribute_lists.first() {
82 return Span::between(attribute.span(), right);
83 }
84
85 if let Some(modifier) = self.modifiers.first() {
86 return Span::between(modifier.span(), right);
87 }
88
89 if let Some(type_hint) = &self.hint {
90 return Span::between(type_hint.span(), right);
91 }
92
93 if let Some(ellipsis) = self.ellipsis {
94 return Span::between(ellipsis, right);
95 }
96
97 if let Some(ampersand) = self.ampersand {
98 return Span::between(ampersand, right);
99 }
100
101 Span::between(self.variable.span(), right)
102 }
103}
104
105impl HasSpan for FunctionLikeParameterDefaultValue<'_> {
106 fn span(&self) -> Span {
107 Span::between(self.equals, self.value.span())
108 }
109}