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}