mago_reflection/function_like/
mod.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4use mago_reporting::IssueCollection;
5use mago_source::HasSource;
6use mago_source::SourceIdentifier;
7use mago_span::HasSpan;
8use mago_span::Span;
9
10use crate::Reflection;
11use crate::attribute::AttributeReflection;
12use crate::class_like::member::ClassLikeMemberVisibilityReflection;
13use crate::function_like::parameter::FunctionLikeParameterReflection;
14use crate::function_like::r#return::FunctionLikeReturnTypeReflection;
15use crate::identifier::FunctionLikeName;
16use crate::r#type::kind::Template;
17
18pub mod parameter;
19pub mod r#return;
20
21/// Represents reflection data for a function-like entity, such as a function or method.
22///
23/// This includes details about its parameters, return type, attributes, and various properties
24/// like visibility, overrides, and whether it supports specific PHP features.
25#[derive(Debug, Clone, Eq, PartialEq, Hash, Serialize, Deserialize)]
26pub struct FunctionLikeReflection {
27    /// Attributes associated with this function-like entity.
28    pub attribute_reflections: Vec<AttributeReflection>,
29
30    /// Visibility information for this function-like if it is a class member.
31    pub visibility_reflection: Option<ClassLikeMemberVisibilityReflection>,
32
33    /// The unique identifier for this function or method.
34    pub name: FunctionLikeName,
35
36    /// The list of templates accepted by this function or method.
37    pub templates: Vec<Template>,
38
39    /// The list of parameters accepted by this function or method, including their types and attributes.
40    pub parameters: Vec<FunctionLikeParameterReflection>,
41
42    /// The return type of this function or method, if specified.
43    pub return_type_reflection: Option<FunctionLikeReturnTypeReflection>,
44
45    /// Indicates whether the function or method returns by reference.
46    pub returns_by_reference: bool,
47
48    /// Flags if the function or method contains a `yield` expression, indicating it is a generator.
49    pub has_yield: bool,
50
51    /// Flags if the function or method has the potential to throw an exception.
52    pub has_throws: bool,
53
54    /// Indicates if this function-like entity is anonymous (i.e., a closure or an anonymous function).
55    ///
56    /// For functions and methods, this is always `false`.
57    pub is_anonymous: bool,
58
59    /// Indicates if this function or method is static.
60    ///
61    /// This is always `false` for functions; for closures, arrow functions, and methods, it depends on their declaration.
62    pub is_static: bool,
63
64    /// Indicates if this function or method is declared as final.
65    ///
66    /// This is always `true` for functions, arrow functions, and closures. For methods, it depends on the declaration.
67    pub is_final: bool,
68
69    /// Indicates if this function or method is abstract.
70    ///
71    /// Always `false` for functions, arrow functions, and closures. For methods, it depends on the declaration.
72    pub is_abstract: bool,
73
74    /// Indicates if this function or method is pure.
75    pub is_pure: bool,
76
77    /// Flags if this method overrides a method from a parent class.
78    ///
79    /// Always `false` for functions, arrow functions, and closures. For methods,
80    /// it depends on whether they override a parent method.
81    pub is_overriding: bool,
82
83    /// The span in the source code where this function or method is defined.
84    pub span: Span,
85
86    /// Indicate if this function-like entity is populated.
87    pub is_populated: bool,
88
89    /// Collection of issues associated with this function-like entity.
90    pub issues: IssueCollection,
91}
92
93impl FunctionLikeReflection {
94    /// Checks if this entity is a function.
95    pub fn is_function(&self) -> bool {
96        matches!(self.name, FunctionLikeName::Function(_))
97    }
98
99    /// Checks if this entity is a method.
100    pub fn is_method(&self) -> bool {
101        matches!(self.name, FunctionLikeName::Method(_, _))
102    }
103
104    /// Checks if this entity is a property hook.
105    pub fn is_property_hook(&self) -> bool {
106        matches!(self.name, FunctionLikeName::PropertyHook(_, _, _))
107    }
108
109    /// Checks if this entity is a closure.
110    pub fn is_closure(&self) -> bool {
111        matches!(self.name, FunctionLikeName::Closure(_))
112    }
113
114    /// Checks if this entity is an arrow function.
115    pub fn is_arrow_function(&self) -> bool {
116        matches!(self.name, FunctionLikeName::ArrowFunction(_))
117    }
118}
119
120impl HasSpan for FunctionLikeReflection {
121    /// Returns the span of the function-like entity in the source code.
122    fn span(&self) -> Span {
123        self.span
124    }
125}
126
127impl HasSource for FunctionLikeReflection {
128    /// Returns the source identifier of the file containing this function-like entity.
129    fn source(&self) -> SourceIdentifier {
130        self.span.source()
131    }
132}
133
134impl Reflection for FunctionLikeReflection {
135    /// Returns the source category of the function-like entity.
136    fn get_category(&self) -> crate::SourceCategory {
137        self.source().category()
138    }
139
140    /// Indicates whether the function-like entity's reflection data is fully populated.
141    ///
142    /// If `is_populated` is `false`, additional processing may be required to resolve
143    /// all metadata for this entity.
144    fn is_populated(&self) -> bool {
145        self.is_populated
146    }
147
148    fn take_issues(&mut self) -> IssueCollection {
149        std::mem::take(&mut self.issues)
150    }
151}