mago_codex/metadata/parameter.rs
1use mago_span::HasSpan;
2use mago_span::Span;
3
4use crate::metadata::attribute::AttributeMetadata;
5use crate::metadata::flags::MetadataFlags;
6use crate::metadata::ttype::TypeMetadata;
7use crate::misc::VariableIdentifier;
8
9/// Contains metadata associated with a single parameter within a function, method, or closure signature.
10///
11/// This captures details like the parameter's name, type hint, attributes, default value,
12/// pass-by-reference status, variadic nature, and other PHP features like property promotion.
13#[derive(Debug, Clone, PartialEq, Eq, Hash)]
14#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
15#[non_exhaustive]
16pub struct FunctionLikeParameterMetadata {
17 /// Attributes attached to the parameter declaration.
18 pub attributes: Vec<AttributeMetadata>,
19
20 /// The identifier (name) of the parameter, including the leading '$'.
21 pub name: VariableIdentifier,
22
23 /// The native type declaration from the function signature.
24 ///
25 /// This is the type hint specified in the code (e.g., `string $name`), not from docblocks.
26 /// Can be `None` if no type hint is specified in the signature.
27 pub type_declaration_metadata: Option<TypeMetadata>,
28
29 /// The explicit type declaration (type hint) or docblock type (`@param`).
30 ///
31 /// If there's a docblock `@param` annotation, this will contain that type (with `from_docblock=true`).
32 /// Otherwise, this will be the same as `type_declaration_metadata`.
33 /// Can be `None` if no type is specified.
34 pub type_metadata: Option<TypeMetadata>,
35
36 /// The type specified by a `@param-out` docblock tag.
37 ///
38 /// This indicates the expected type of a pass-by-reference parameter *after* the function executes.
39 pub out_type: Option<TypeMetadata>,
40
41 /// The inferred type of the parameter's default value, if `has_default` is true and the
42 /// type could be determined.
43 ///
44 /// `None` if there is no default or the default value's type couldn't be inferred.
45 pub default_type: Option<TypeMetadata>,
46
47 /// The source code location (span) covering the entire parameter declaration.
48 pub span: Span,
49
50 /// The specific source code location (span) of the parameter's name identifier.
51 pub name_span: Span,
52
53 /// Flags indicating various properties of the parameter.
54 pub flags: MetadataFlags,
55}
56
57/// Contains metadata associated with a single parameter within a function, method, or closure signature.
58///
59/// This captures details like the parameter's name, type hint, attributes, default value,
60/// pass-by-reference status, variadic nature, and other PHP features like property promotion.
61impl FunctionLikeParameterMetadata {
62 /// Creates new `FunctionLikeParameterMetadata` for a basic parameter.
63 /// Initializes most flags to false and optional fields to None.
64 ///
65 /// # Arguments
66 ///
67 /// * `name`: The identifier (name) of the parameter (e.g., `$userId`).
68 /// * `span`: The source code location covering the entire parameter declaration.
69 /// * `name_span`: The source code location of the parameter's name identifier (`$userId`).
70 #[must_use]
71 pub fn new(name: VariableIdentifier, span: Span, name_span: Span, flags: MetadataFlags) -> Self {
72 Self {
73 attributes: Vec::new(),
74 name,
75 flags,
76 span,
77 name_span,
78 type_declaration_metadata: None,
79 type_metadata: None,
80 out_type: None,
81 default_type: None,
82 }
83 }
84
85 /// Returns a reference to the parameter's name identifier (e.g., `$userId`).
86 #[inline]
87 #[must_use]
88 pub fn get_name(&self) -> &VariableIdentifier {
89 &self.name
90 }
91
92 /// Returns the span covering the entire parameter declaration.
93 #[inline]
94 #[must_use]
95 pub fn get_span(&self) -> Span {
96 self.span
97 }
98
99 /// Returns the span covering the parameter's name identifier.
100 #[inline]
101 #[must_use]
102 pub fn get_name_span(&self) -> Span {
103 self.name_span
104 }
105
106 /// Returns a reference to the parameter's type metadata (effective type with docblock).
107 #[inline]
108 #[must_use]
109 pub fn get_type_metadata(&self) -> Option<&TypeMetadata> {
110 self.type_metadata.as_ref()
111 }
112
113 /// Returns a reference to the parameter's native type declaration metadata.
114 #[inline]
115 #[must_use]
116 pub fn get_type_declaration_metadata(&self) -> Option<&TypeMetadata> {
117 self.type_declaration_metadata.as_ref()
118 }
119
120 /// Returns a reference to the inferred type of the default value, if known.
121 #[inline]
122 #[must_use]
123 pub fn get_default_type(&self) -> Option<&TypeMetadata> {
124 self.default_type.as_ref()
125 }
126
127 /// Sets the attributes, replacing any existing ones.
128 pub fn set_attributes(&mut self, attributes: impl IntoIterator<Item = AttributeMetadata>) {
129 self.attributes = attributes.into_iter().collect();
130 }
131
132 /// Returns a new instance with the attributes replaced.
133 #[must_use]
134 pub fn with_attributes(mut self, attributes: impl IntoIterator<Item = AttributeMetadata>) -> Self {
135 self.set_attributes(attributes);
136 self
137 }
138
139 /// Sets the parameter's type metadata (effective type with docblock).
140 #[inline]
141 pub fn set_type_metadata(&mut self, type_metadata: Option<TypeMetadata>) {
142 self.type_metadata = type_metadata;
143 }
144
145 /// Sets the parameter's native type declaration metadata.
146 ///
147 /// If `type_metadata` is not set, it will be initialized with the same value.
148 #[inline]
149 pub fn set_type_declaration_metadata(&mut self, type_declaration: Option<TypeMetadata>) {
150 if self.type_metadata.is_none() {
151 self.type_metadata.clone_from(&type_declaration);
152 }
153
154 self.type_declaration_metadata = type_declaration;
155 }
156}
157
158impl HasSpan for FunctionLikeParameterMetadata {
159 fn span(&self) -> Span {
160 self.span
161 }
162}