Skip to main content

mago_codex/metadata/
constant.rs

1use mago_php_version::PHPVersion;
2use mago_php_version::PHPVersionRange;
3
4use mago_reporting::Issue;
5use mago_span::HasSpan;
6use mago_span::Span;
7use mago_word::Word;
8
9use crate::metadata::attribute::AttributeMetadata;
10use crate::metadata::flags::MetadataFlags;
11use crate::metadata::ttype::TypeMetadata;
12use crate::metadata::version_constraint::VersionConstraint;
13use crate::ttype::union::TUnion;
14
15/// Contains metadata associated with a global constant defined using `const`.
16///
17/// Represents a single constant declaration item, potentially within a grouped declaration,
18/// like `MAX_RETRIES = 3` in `const MAX_RETRIES = 3;` or `B = 2` in `const A = 1, B = 2;`.
19#[derive(Clone, Debug, PartialEq, Eq)]
20#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
21#[non_exhaustive]
22pub struct ConstantMetadata {
23    pub attributes: Vec<AttributeMetadata>,
24    pub name: Word,
25    pub span: Span,
26    pub type_metadata: Option<TypeMetadata>,
27    pub inferred_type: Option<TUnion>,
28    pub flags: MetadataFlags,
29    pub issues: Vec<Issue>,
30    pub version_constraint: VersionConstraint,
31}
32
33impl ConstantMetadata {
34    /// Creates new `ConstantMetadata` for a non-deprecated, non-internal global constant item.
35    ///
36    /// # Arguments
37    ///
38    /// * `name`: The identifier (name) of the constant.
39    /// * `span`: The source code location of this specific constant's definition item (`NAME = value`).
40    #[inline]
41    #[must_use]
42    pub fn new(name: Word, span: Span, flags: MetadataFlags) -> Self {
43        Self {
44            attributes: Vec::new(),
45            name,
46            span,
47            flags,
48            type_metadata: None,
49            inferred_type: None,
50            issues: Vec::new(),
51            version_constraint: VersionConstraint::unconstrained(),
52        }
53    }
54
55    /// Returns a mutable slice of docblock issues.
56    #[inline]
57    pub fn take_issues(&mut self) -> Vec<Issue> {
58        std::mem::take(&mut self.issues)
59    }
60
61    /// Returns `true` when this constant is available in the given PHP version.
62    #[inline]
63    #[must_use]
64    pub fn is_available_in_version(&self, version: PHPVersion) -> bool {
65        self.version_constraint.allows_version(version)
66    }
67
68    /// Returns `true` when this constant is available across the entire
69    /// supplied [`PHPVersionRange`].
70    #[inline]
71    #[must_use]
72    pub fn is_available_in_version_range(&self, range: PHPVersionRange) -> bool {
73        self.version_constraint.allows_version_range(range)
74    }
75
76    /// Applies a patch to this entry in place, refining type information.
77    pub fn apply_patch(&mut self, patch: &ConstantMetadata) {
78        if patch.type_metadata.is_some() {
79            self.type_metadata.clone_from(&patch.type_metadata);
80        }
81    }
82}
83
84impl HasSpan for ConstantMetadata {
85    fn span(&self) -> Span {
86        self.span
87    }
88}