mago_reflection/class_like/
mod.rs

1use ahash::HashMap;
2use ahash::HashSet;
3use serde::Deserialize;
4use serde::Serialize;
5
6use mago_interner::StringIdentifier;
7use mago_reporting::IssueCollection;
8use mago_source::HasSource;
9use mago_source::SourceIdentifier;
10use mago_span::HasSpan;
11use mago_span::Span;
12
13use crate::Reflection;
14use crate::attribute::AttributeReflection;
15use crate::class_like::constant::ClassLikeConstantReflection;
16use crate::class_like::enum_case::EnumCaseReflection;
17use crate::class_like::inheritance::InheritanceReflection;
18use crate::class_like::member::MemeberCollection;
19use crate::class_like::property::PropertyReflection;
20use crate::function_like::FunctionLikeReflection;
21use crate::identifier::ClassLikeName;
22use crate::identifier::Name;
23use crate::r#type::TypeReflection;
24
25pub mod constant;
26pub mod enum_case;
27pub mod inheritance;
28pub mod member;
29pub mod property;
30
31/// Represents reflection data for a PHP class, interface, enum, or trait.
32#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize)]
33pub struct ClassLikeReflection {
34    /// Attributes (e.g., annotations) associated with the class-like entity.
35    pub attribute_reflections: Vec<AttributeReflection>,
36
37    /// The name of the class-like entity, such as its fully qualified name.
38    pub name: ClassLikeName,
39
40    /// Inheritance information for the class-like entity, including parent classes and implemented interfaces.
41    pub inheritance: InheritanceReflection,
42
43    /// Constants defined in the class-like entity.
44    pub constants: HashMap<StringIdentifier, ClassLikeConstantReflection>,
45
46    /// Enum cases defined in the class-like entity, if it is an enum.
47    pub cases: HashMap<StringIdentifier, EnumCaseReflection>,
48
49    /// Properties defined in the class-like entity.
50    pub properties: MemeberCollection<PropertyReflection>,
51
52    /// Methods defined in the class-like entity.
53    pub methods: MemeberCollection<FunctionLikeReflection>,
54
55    /// Traits used by the class-like entity.
56    pub used_traits: HashSet<Name>,
57
58    /// Traits used by the class-like entity.
59    pub used_trait_names: HashMap<StringIdentifier, Name>,
60
61    /// The backing type of the entity, used if it is an enum.
62    pub backing_type: Option<TypeReflection>,
63
64    /// Whether the class-like entity is declared as `final`.
65    pub is_final: bool,
66
67    /// Whether the class-like entity is declared as `readonly`.
68    pub is_readonly: bool,
69
70    /// Whether the class-like entity is declared as `abstract`.
71    pub is_abstract: bool,
72
73    /// Whether the entity is an anonymous class.
74    pub is_anonymous: bool,
75
76    /// The span in the source code where the class-like entity is declared.
77    pub span: Span,
78
79    /// Indicates whether the reflection is fully populated with all metadata.
80    pub is_populated: bool,
81
82    /// Issues encountered while processing the class-like entity.
83    pub issues: IssueCollection,
84}
85
86impl ClassLikeReflection {
87    pub fn new(name: ClassLikeName, span: Span) -> Self {
88        Self {
89            attribute_reflections: Vec::new(),
90            name,
91            inheritance: InheritanceReflection::default(),
92            constants: HashMap::default(),
93            cases: HashMap::default(),
94            properties: MemeberCollection::default(),
95            methods: MemeberCollection::default(),
96            used_traits: HashSet::default(),
97            used_trait_names: HashMap::default(),
98            backing_type: None,
99            is_final: false,
100            is_readonly: false,
101            is_abstract: false,
102            is_anonymous: false,
103            span,
104            is_populated: false,
105            issues: IssueCollection::new(),
106        }
107    }
108
109    /// Checks if this class-like entity is a trait.
110    #[inline]
111    pub const fn is_trait(&self) -> bool {
112        matches!(self.name, ClassLikeName::Trait(_))
113    }
114
115    /// Checks if this class-like entity is an interface.
116    #[inline]
117    pub const fn is_interface(&self) -> bool {
118        matches!(self.name, ClassLikeName::Interface(_))
119    }
120
121    /// Checks if this class-like entity is a class.
122    #[inline]
123    pub const fn is_class(&self) -> bool {
124        matches!(self.name, ClassLikeName::Class(_))
125    }
126
127    /// Checks if this class-like entity is an enum.
128    #[inline]
129    pub const fn is_enum(&self) -> bool {
130        matches!(self.name, ClassLikeName::Enum(_))
131    }
132
133    /// Checks if this class-like entity is a trait.
134    #[inline]
135    pub const fn is_anonymous_class(&self) -> bool {
136        matches!(self.name, ClassLikeName::AnonymousClass(_))
137    }
138}
139
140impl HasSpan for ClassLikeReflection {
141    /// Returns the span of the class-like entity in the source code.
142    ///
143    /// The span covers the entire declaration of the entity, including its attributes,
144    /// inheritance, and body.
145    fn span(&self) -> Span {
146        self.span
147    }
148}
149
150impl HasSource for ClassLikeReflection {
151    /// Returns the source identifier of the file containing this class-like entity.
152    ///
153    /// The source identifier provides metadata about the origin of the entity,
154    /// such as whether it is user-defined, vendor-provided, or built-in.
155    fn source(&self) -> SourceIdentifier {
156        self.span.source()
157    }
158}
159
160impl Reflection for ClassLikeReflection {
161    /// Returns the source category of the class-like entity.
162    ///
163    /// The category indicates whether the entity is part of the project (`UserDefined`),
164    /// vendor-provided (`Vendor`), or built-in (`BuiltIn`).
165    fn get_category(&self) -> crate::SourceCategory {
166        self.source().category()
167    }
168
169    /// Indicates whether the class-like entity's reflection data is fully populated.
170    ///
171    /// If `is_populated` is `false`, additional processing may be required to resolve
172    /// all metadata for this entity.
173    fn is_populated(&self) -> bool {
174        self.is_populated
175    }
176
177    fn take_issues(&mut self) -> IssueCollection {
178        std::mem::take(&mut self.issues)
179    }
180}