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