Skip to main content

mago_codex/flags/
attribute.rs

1use serde::Deserialize;
2use serde::Serialize;
3
4bitflags::bitflags! {
5    /// Represents the flags defined in a PHP `#[Attribute]` declaration,
6    /// specifying the targets where the attribute can be applied and whether it's repeatable.
7    #[derive(Clone, Copy, Debug, PartialEq, Eq, Serialize, Deserialize)]
8    pub struct AttributeFlags: u8 {
9        /// Flag indicating the attribute can be applied to classes, interfaces, traits, and enums.
10        /// Corresponds to `Attribute::TARGET_CLASS`.
11        const TARGET_CLASS          = 1 << 0; //  1
12
13        /// Flag indicating the attribute can be applied to functions (including closures and arrow functions).
14        /// Corresponds to `Attribute::TARGET_FUNCTION`.
15        const TARGET_FUNCTION       = 1 << 1; //  2
16
17        /// Flag indicating the attribute can be applied to methods.
18        /// Corresponds to `Attribute::TARGET_METHOD`.
19        const TARGET_METHOD         = 1 << 2; //  4
20
21        /// Flag indicating the attribute can be applied to properties.
22        /// Corresponds to `Attribute::TARGET_PROPERTY`.
23        const TARGET_PROPERTY       = 1 << 3; //  8
24
25        /// Flag indicating the attribute can be applied to class constants.
26        /// Corresponds to `Attribute::TARGET_CLASS_CONSTANT`.
27        const TARGET_CLASS_CONSTANT = 1 << 4; // 16
28
29        /// Flag indicating the attribute can be applied to function or method parameters.
30        /// Corresponds to `Attribute::TARGET_PARAMETER`.
31        const TARGET_PARAMETER      = 1 << 5; // 32
32
33        /// Flag indicating the attribute can be applied to global constants (defined with `const`).
34        /// Corresponds to `Attribute::TARGET_CONSTANT`.
35        const TARGET_CONSTANT       = 1 << 6; // 64
36
37        /// A combination of all `TARGET_*` flags, indicating the attribute can be applied anywhere.
38        /// Corresponds to `Attribute::TARGET_ALL`.
39        const TARGET_ALL = Self::TARGET_CLASS.bits()
40            | Self::TARGET_FUNCTION.bits()
41            | Self::TARGET_METHOD.bits()
42            | Self::TARGET_PROPERTY.bits()
43            | Self::TARGET_CLASS_CONSTANT.bits()
44            | Self::TARGET_PARAMETER.bits()
45            | Self::TARGET_CONSTANT.bits(); // 127
46
47        /// Flag indicating the attribute can be repeated on the same declaration.
48        /// Corresponds to `Attribute::IS_REPEATABLE`.
49        const IS_REPEATABLE         = 1 << 7; // 128
50    }
51}
52
53impl AttributeFlags {
54    /// Checks if the `IS_REPEATABLE` flag is set, meaning the attribute
55    /// can be declared multiple times on the same target.
56    #[must_use]
57    pub const fn is_repeatable(&self) -> bool {
58        self.contains(Self::IS_REPEATABLE)
59    }
60
61    /// Checks if the `TARGET_CLASS` flag is set, indicating the attribute
62    /// can be applied to classes, interfaces, traits, or enums.
63    #[must_use]
64    pub const fn targets_class(&self) -> bool {
65        self.contains(Self::TARGET_CLASS)
66    }
67
68    /// Checks if the `TARGET_FUNCTION` flag is set, indicating the attribute
69    /// can be applied to functions or closures.
70    #[must_use]
71    pub const fn targets_function(&self) -> bool {
72        self.contains(Self::TARGET_FUNCTION)
73    }
74
75    /// Checks if the `TARGET_METHOD` flag is set, indicating the attribute
76    /// can be applied to class or interface methods.
77    #[must_use]
78    pub const fn targets_method(&self) -> bool {
79        self.contains(Self::TARGET_METHOD)
80    }
81
82    /// Checks if the `TARGET_PROPERTY` flag is set, indicating the attribute
83    /// can be applied to class properties.
84    #[must_use]
85    pub const fn targets_property(&self) -> bool {
86        self.contains(Self::TARGET_PROPERTY)
87    }
88
89    /// Checks if the `TARGET_CLASS_CONSTANT` flag is set, indicating the attribute
90    /// can be applied to class constants.
91    #[must_use]
92    pub const fn targets_class_constant(&self) -> bool {
93        self.contains(Self::TARGET_CLASS_CONSTANT)
94    }
95
96    /// Checks if the `TARGET_PARAMETER` flag is set, indicating the attribute
97    /// can be applied to function or method parameters.
98    #[must_use]
99    pub const fn targets_parameter(&self) -> bool {
100        self.contains(Self::TARGET_PARAMETER)
101    }
102
103    /// Checks if the `TARGET_CONSTANT` flag is set, indicating the attribute
104    /// can be applied to global constants.
105    #[must_use]
106    pub const fn targets_constant(&self) -> bool {
107        self.contains(Self::TARGET_CONSTANT)
108    }
109
110    /// Returns a list of human-readable strings for each target flag set.
111    #[must_use]
112    pub fn get_target_names(&self) -> Vec<&'static str> {
113        let mut targets = Vec::with_capacity(7);
114
115        if self.targets_class() {
116            targets.push("classes");
117        }
118
119        if self.targets_function() {
120            targets.push("functions");
121        }
122
123        if self.targets_method() {
124            targets.push("methods");
125        }
126
127        if self.targets_property() {
128            targets.push("properties");
129        }
130
131        if self.targets_class_constant() {
132            targets.push("class constants");
133        }
134
135        if self.targets_parameter() {
136            targets.push("parameters");
137        }
138
139        if self.targets_constant() {
140            targets.push("global constants");
141        }
142
143        targets
144    }
145}