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}