Skip to main content

mago_syntax/ast/ast/class_like/
member.rs

1use serde::Serialize;
2use strum::Display;
3
4use mago_span::HasSpan;
5use mago_span::Span;
6
7use crate::ast::Sequence;
8use crate::ast::ast::class_like::constant::ClassLikeConstant;
9use crate::ast::ast::class_like::enum_case::EnumCase;
10use crate::ast::ast::class_like::method::Method;
11use crate::ast::ast::class_like::property::Property;
12use crate::ast::ast::class_like::trait_use::TraitUse;
13use crate::ast::ast::expression::Expression;
14use crate::ast::ast::identifier::LocalIdentifier;
15use crate::ast::ast::variable::Variable;
16
17#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
18#[serde(tag = "type", content = "value")]
19pub enum ClassLikeMember<'arena> {
20    TraitUse(TraitUse<'arena>),
21    Constant(ClassLikeConstant<'arena>),
22    Property(Property<'arena>),
23    EnumCase(EnumCase<'arena>),
24    Method(Method<'arena>),
25}
26
27#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
28#[serde(tag = "type", content = "value")]
29pub enum ClassLikeMemberSelector<'arena> {
30    Identifier(LocalIdentifier<'arena>),
31    Variable(Variable<'arena>),
32    Expression(ClassLikeMemberExpressionSelector<'arena>),
33    Missing(Span),
34}
35
36#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord, Display)]
37#[serde(tag = "type", content = "value")]
38pub enum ClassLikeConstantSelector<'arena> {
39    Identifier(LocalIdentifier<'arena>),
40    Expression(ClassLikeMemberExpressionSelector<'arena>),
41    Missing(Span),
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, PartialOrd, Ord)]
45pub struct ClassLikeMemberExpressionSelector<'arena> {
46    pub left_brace: Span,
47    pub expression: &'arena Expression<'arena>,
48    pub right_brace: Span,
49}
50
51impl ClassLikeMember<'_> {
52    #[inline]
53    #[must_use]
54    pub const fn is_trait_use(&self) -> bool {
55        matches!(self, ClassLikeMember::TraitUse(_))
56    }
57
58    #[inline]
59    #[must_use]
60    pub const fn is_constant(&self) -> bool {
61        matches!(self, ClassLikeMember::Constant(_))
62    }
63
64    #[inline]
65    #[must_use]
66    pub const fn is_property(&self) -> bool {
67        matches!(self, ClassLikeMember::Property(_))
68    }
69
70    #[inline]
71    #[must_use]
72    pub const fn is_enum_case(&self) -> bool {
73        matches!(self, ClassLikeMember::EnumCase(_))
74    }
75
76    #[inline]
77    #[must_use]
78    pub const fn is_method(&self) -> bool {
79        matches!(self, ClassLikeMember::Method(_))
80    }
81}
82
83impl ClassLikeMemberSelector<'_> {
84    #[inline]
85    #[must_use]
86    pub const fn is_identifier(&self) -> bool {
87        matches!(self, ClassLikeMemberSelector::Identifier(_))
88    }
89
90    #[inline]
91    #[must_use]
92    pub const fn is_variable(&self) -> bool {
93        matches!(self, ClassLikeMemberSelector::Variable(_))
94    }
95
96    #[inline]
97    #[must_use]
98    pub const fn is_expression(&self) -> bool {
99        matches!(self, ClassLikeMemberSelector::Expression(_))
100    }
101
102    #[inline]
103    #[must_use]
104    pub const fn is_missing(&self) -> bool {
105        matches!(self, ClassLikeMemberSelector::Missing(_))
106    }
107}
108
109impl ClassLikeConstantSelector<'_> {
110    #[inline]
111    #[must_use]
112    pub const fn is_identifier(&self) -> bool {
113        matches!(self, ClassLikeConstantSelector::Identifier(_))
114    }
115
116    #[inline]
117    #[must_use]
118    pub const fn is_expression(&self) -> bool {
119        matches!(self, ClassLikeConstantSelector::Expression(_))
120    }
121
122    #[inline]
123    #[must_use]
124    pub const fn is_missing(&self) -> bool {
125        matches!(self, ClassLikeConstantSelector::Missing(_))
126    }
127}
128
129/// Accessors over a class-like member [`Sequence`]. Lives as a trait
130/// because [`Sequence`] is defined in [`mago_syntax_core`]; `use`-import
131/// it to get the methods in scope.
132pub trait ClassLikeMemberSequenceExt<'arena> {
133    fn contains_trait_uses(&self) -> bool;
134    fn contains_constants(&self) -> bool;
135    fn contains_properties(&self) -> bool;
136    fn contains_enum_cases(&self) -> bool;
137    fn contains_methods(&self) -> bool;
138}
139
140impl<'arena> ClassLikeMemberSequenceExt<'arena> for Sequence<'arena, ClassLikeMember<'arena>> {
141    #[inline]
142    fn contains_trait_uses(&self) -> bool {
143        self.iter().any(|member| matches!(member, ClassLikeMember::TraitUse(_)))
144    }
145
146    #[inline]
147    fn contains_constants(&self) -> bool {
148        self.iter().any(|member| matches!(member, ClassLikeMember::Constant(_)))
149    }
150
151    #[inline]
152    fn contains_properties(&self) -> bool {
153        self.iter().any(|member| matches!(member, ClassLikeMember::Property(_)))
154    }
155
156    #[inline]
157    fn contains_enum_cases(&self) -> bool {
158        self.iter().any(|member| matches!(member, ClassLikeMember::EnumCase(_)))
159    }
160
161    #[inline]
162    fn contains_methods(&self) -> bool {
163        self.iter().any(|member| matches!(member, ClassLikeMember::Method(_)))
164    }
165}
166
167impl HasSpan for ClassLikeMember<'_> {
168    fn span(&self) -> Span {
169        match self {
170            ClassLikeMember::TraitUse(trait_use) => trait_use.span(),
171            ClassLikeMember::Constant(constant) => constant.span(),
172            ClassLikeMember::Property(property) => property.span(),
173            ClassLikeMember::EnumCase(enum_case) => enum_case.span(),
174            ClassLikeMember::Method(method) => method.span(),
175        }
176    }
177}
178
179impl HasSpan for ClassLikeMemberSelector<'_> {
180    fn span(&self) -> Span {
181        match self {
182            ClassLikeMemberSelector::Identifier(i) => i.span(),
183            ClassLikeMemberSelector::Variable(v) => v.span(),
184            ClassLikeMemberSelector::Expression(e) => e.span(),
185            ClassLikeMemberSelector::Missing(span) => *span,
186        }
187    }
188}
189
190impl HasSpan for ClassLikeConstantSelector<'_> {
191    fn span(&self) -> Span {
192        match self {
193            ClassLikeConstantSelector::Identifier(i) => i.span(),
194            ClassLikeConstantSelector::Expression(e) => e.span(),
195            ClassLikeConstantSelector::Missing(span) => *span,
196        }
197    }
198}
199
200impl HasSpan for ClassLikeMemberExpressionSelector<'_> {
201    fn span(&self) -> Span {
202        self.left_brace.join(self.right_brace)
203    }
204}