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    pub const fn is_repeatable(&self) -> bool {
57        self.contains(Self::IS_REPEATABLE)
58    }
59
60    /// Checks if the `TARGET_CLASS` flag is set, indicating the attribute
61    /// can be applied to classes, interfaces, traits, or enums.
62    pub const fn targets_class(&self) -> bool {
63        self.contains(Self::TARGET_CLASS)
64    }
65
66    /// Checks if the `TARGET_FUNCTION` flag is set, indicating the attribute
67    /// can be applied to functions or closures.
68    pub const fn targets_function(&self) -> bool {
69        self.contains(Self::TARGET_FUNCTION)
70    }
71
72    /// Checks if the `TARGET_METHOD` flag is set, indicating the attribute
73    /// can be applied to class or interface methods.
74    pub const fn targets_method(&self) -> bool {
75        self.contains(Self::TARGET_METHOD)
76    }
77
78    /// Checks if the `TARGET_PROPERTY` flag is set, indicating the attribute
79    /// can be applied to class properties.
80    pub const fn targets_property(&self) -> bool {
81        self.contains(Self::TARGET_PROPERTY)
82    }
83
84    /// Checks if the `TARGET_CLASS_CONSTANT` flag is set, indicating the attribute
85    /// can be applied to class constants.
86    pub const fn targets_class_constant(&self) -> bool {
87        self.contains(Self::TARGET_CLASS_CONSTANT)
88    }
89
90    /// Checks if the `TARGET_PARAMETER` flag is set, indicating the attribute
91    /// can be applied to function or method parameters.
92    pub const fn targets_parameter(&self) -> bool {
93        self.contains(Self::TARGET_PARAMETER)
94    }
95
96    /// Checks if the `TARGET_CONSTANT` flag is set, indicating the attribute
97    /// can be applied to global constants.
98    pub const fn targets_constant(&self) -> bool {
99        self.contains(Self::TARGET_CONSTANT)
100    }
101
102    /// Returns a list of human-readable strings for each target flag set.
103    pub fn get_target_names(&self) -> Vec<&'static str> {
104        let mut targets = Vec::with_capacity(7);
105
106        if self.targets_class() {
107            targets.push("classes");
108        }
109
110        if self.targets_function() {
111            targets.push("functions");
112        }
113
114        if self.targets_method() {
115            targets.push("methods");
116        }
117
118        if self.targets_property() {
119            targets.push("properties");
120        }
121
122        if self.targets_class_constant() {
123            targets.push("class constants");
124        }
125
126        if self.targets_parameter() {
127            targets.push("parameters");
128        }
129
130        if self.targets_constant() {
131            targets.push("global constants");
132        }
133
134        targets
135    }
136}