mago_ast/ast/class_like/
trait_use.rs

1use serde::Deserialize;
2use serde::Serialize;
3use strum::Display;
4
5use mago_span::HasSpan;
6use mago_span::Span;
7
8use crate::ast::identifier::Identifier;
9use crate::ast::identifier::LocalIdentifier;
10use crate::ast::keyword::Keyword;
11use crate::ast::modifier::Modifier;
12use crate::ast::terminator::Terminator;
13use crate::sequence::Sequence;
14use crate::sequence::TokenSeparatedSequence;
15
16#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
17#[repr(C)]
18pub struct TraitUse {
19    pub r#use: Keyword,
20    pub trait_names: TokenSeparatedSequence<Identifier>,
21    pub specification: TraitUseSpecification,
22}
23
24#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
25#[serde(tag = "type", content = "value")]
26#[repr(C, u8)]
27pub enum TraitUseSpecification {
28    Abstract(TraitUseAbstractSpecification),
29    Concrete(TraitUseConcreteSpecification),
30}
31
32#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
33#[repr(C)]
34pub struct TraitUseAbstractSpecification(pub Terminator);
35
36#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
37#[repr(C)]
38pub struct TraitUseConcreteSpecification {
39    pub left_brace: Span,
40    pub adaptations: Sequence<TraitUseAdaptation>,
41    pub right_brace: Span,
42}
43
44#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
45#[serde(tag = "type", content = "value")]
46#[repr(C, u8)]
47pub enum TraitUseAdaptation {
48    Precedence(TraitUsePrecedenceAdaptation),
49    Alias(TraitUseAliasAdaptation),
50}
51
52#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
53#[repr(C)]
54pub struct TraitUsePrecedenceAdaptation {
55    pub method_reference: TraitUseAbsoluteMethodReference,
56    pub insteadof: Keyword,
57    pub trait_names: TokenSeparatedSequence<Identifier>,
58    pub terminator: Terminator,
59}
60
61#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
62#[repr(C)]
63pub struct TraitUseAliasAdaptation {
64    pub method_reference: TraitUseMethodReference,
65    pub r#as: Keyword,
66    pub visibility: Option<Modifier>,
67    pub alias: Option<LocalIdentifier>,
68    pub terminator: Terminator,
69}
70
71#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord, Display)]
72#[serde(tag = "type", content = "value")]
73#[repr(C, u8)]
74pub enum TraitUseMethodReference {
75    Identifier(LocalIdentifier),
76    Absolute(TraitUseAbsoluteMethodReference),
77}
78
79#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize, PartialOrd, Ord)]
80#[repr(C)]
81pub struct TraitUseAbsoluteMethodReference {
82    pub trait_name: Identifier,
83    pub double_colon: Span,
84    pub method_name: LocalIdentifier,
85}
86
87impl HasSpan for TraitUse {
88    fn span(&self) -> Span {
89        Span::between(self.r#use.span(), self.specification.span())
90    }
91}
92
93impl HasSpan for TraitUseSpecification {
94    fn span(&self) -> Span {
95        match self {
96            TraitUseSpecification::Abstract(specification) => specification.span(),
97            TraitUseSpecification::Concrete(specification) => specification.span(),
98        }
99    }
100}
101
102impl HasSpan for TraitUseAbstractSpecification {
103    fn span(&self) -> Span {
104        self.0.span()
105    }
106}
107
108impl HasSpan for TraitUseConcreteSpecification {
109    fn span(&self) -> Span {
110        Span::between(self.left_brace, self.right_brace)
111    }
112}
113
114impl HasSpan for TraitUseAdaptation {
115    fn span(&self) -> Span {
116        match self {
117            TraitUseAdaptation::Precedence(adaptation) => adaptation.span(),
118            TraitUseAdaptation::Alias(adaptation) => adaptation.span(),
119        }
120    }
121}
122
123impl HasSpan for TraitUsePrecedenceAdaptation {
124    fn span(&self) -> Span {
125        Span::between(self.method_reference.span(), self.terminator.span())
126    }
127}
128
129impl HasSpan for TraitUseAliasAdaptation {
130    fn span(&self) -> Span {
131        self.method_reference.span().join(self.terminator.span())
132    }
133}
134
135impl HasSpan for TraitUseMethodReference {
136    fn span(&self) -> Span {
137        match self {
138            TraitUseMethodReference::Identifier(identifier) => identifier.span(),
139            TraitUseMethodReference::Absolute(absolute) => absolute.span(),
140        }
141    }
142}
143
144impl HasSpan for TraitUseAbsoluteMethodReference {
145    fn span(&self) -> Span {
146        Span::between(self.trait_name.span(), self.method_name.span())
147    }
148}