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}