mago_syntax/ast/ast/class_like/
method.rs1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::ast::attribute::AttributeList;
8use crate::ast::ast::block::Block;
9use crate::ast::ast::function_like::parameter::FunctionLikeParameterList;
10use crate::ast::ast::function_like::r#return::FunctionLikeReturnTypeHint;
11use crate::ast::ast::identifier::LocalIdentifier;
12use crate::ast::ast::keyword::Keyword;
13use crate::ast::ast::modifier::Modifier;
14use crate::ast::sequence::Sequence;
15
16#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
28pub struct Method<'arena> {
29 pub attribute_lists: Sequence<'arena, AttributeList<'arena>>,
30 pub modifiers: Sequence<'arena, Modifier<'arena>>,
31 pub function: Keyword<'arena>,
32 pub ampersand: Option<Span>,
33 pub name: LocalIdentifier<'arena>,
34 pub parameter_list: FunctionLikeParameterList<'arena>,
35 pub return_type_hint: Option<FunctionLikeReturnTypeHint<'arena>>,
36 pub body: MethodBody<'arena>,
37}
38
39#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
41#[serde(tag = "type", content = "value")]
42#[repr(u8)]
43pub enum MethodBody<'arena> {
44 Abstract(MethodAbstractBody),
45 Concrete(Block<'arena>),
46}
47
48#[derive(Debug, Clone, Copy, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
61pub struct MethodAbstractBody {
62 pub semicolon: Span,
63}
64
65impl Method<'_> {
66 pub fn has_promoted_properties(&self) -> bool {
68 self.parameter_list
69 .parameters
70 .iter()
71 .any(super::super::function_like::parameter::FunctionLikeParameter::is_promoted_property)
72 }
73
74 #[inline]
76 #[must_use]
77 pub const fn is_abstract(&self) -> bool {
78 matches!(self.body, MethodBody::Abstract(_))
79 }
80
81 #[inline]
83 pub fn is_static(&self) -> bool {
84 self.modifiers.iter().any(super::super::modifier::Modifier::is_static)
85 }
86}
87
88impl HasSpan for Method<'_> {
89 fn span(&self) -> Span {
90 if let Some(attribute_list) = self.attribute_lists.first() {
91 return Span::between(attribute_list.span(), self.body.span());
92 }
93
94 if let Some(modifier) = self.modifiers.first() {
95 return Span::between(modifier.span(), self.body.span());
96 }
97
98 Span::between(self.function.span, self.body.span())
99 }
100}
101
102impl HasSpan for MethodBody<'_> {
103 fn span(&self) -> Span {
104 match self {
105 MethodBody::Abstract(body) => body.span(),
106 MethodBody::Concrete(body) => body.span(),
107 }
108 }
109}
110
111impl HasSpan for MethodAbstractBody {
112 fn span(&self) -> Span {
113 self.semicolon
114 }
115}