mago_codex/metadata/
parameter.rs

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