mago_reflection/class_like/
inheritance.rs1use ahash::HashMap;
2use ahash::HashSet;
3
4use mago_interner::StringIdentifier;
5use mago_interner::ThreadedInterner;
6use serde::Deserialize;
7use serde::Serialize;
8
9use crate::identifier::ClassLikeName;
10use crate::identifier::Name;
11
12use super::ClassLikeReflection;
13
14#[derive(Debug, Clone, Eq, PartialEq, Serialize, Deserialize, Default)]
17pub struct InheritanceReflection {
18 pub direct_implemented_interfaces: HashSet<Name>,
20
21 pub all_implemented_interfaces: HashSet<Name>,
24
25 pub direct_extended_class: Option<Name>,
27
28 pub all_extended_classes: HashSet<Name>,
31
32 pub direct_extended_interfaces: HashSet<Name>,
34
35 pub all_extended_interfaces: HashSet<Name>,
38
39 pub require_implementations: HashSet<StringIdentifier>,
42
43 pub require_extensions: HashSet<StringIdentifier>,
46
47 pub children: HashSet<ClassLikeName>,
49
50 pub names: HashMap<StringIdentifier, Name>,
52}
53
54impl InheritanceReflection {
55 #[inline]
56 pub fn implements_interfaces(&self) -> bool {
57 !self.all_implemented_interfaces.is_empty()
58 }
59
60 #[inline]
61 pub fn extends_classes(&self) -> bool {
62 !self.all_extended_classes.is_empty()
63 }
64
65 #[inline]
66 pub fn has_children(&self) -> bool {
67 !self.children.is_empty()
68 }
69
70 #[inline]
71 pub fn is_instance_of(&self, interner: &ThreadedInterner, other: &ClassLikeReflection) -> bool {
72 let Some(other_name) = other.name.inner() else {
73 return false;
74 };
75
76 let other_identifier = interner.lowered(&other_name.value);
77 if let Some(this_name) = self.direct_extended_class {
78 let this_identifier = interner.lowered(&this_name.value);
79 if this_identifier == other_identifier {
80 return true;
81 }
82 }
83
84 let Some(other_fqcn) = self.names.get(&other_identifier) else {
85 return false;
86 };
87
88 self.all_extended_classes.contains(other_fqcn)
89 || self.all_implemented_interfaces.contains(other_fqcn)
90 || self.all_extended_interfaces.contains(other_fqcn)
91 }
92
93 #[inline]
94 pub fn extends_class(&self, interner: &ThreadedInterner, other: &ClassLikeReflection) -> bool {
95 let Some(name) = other.name.inner() else {
96 return false; };
98
99 self.extends_class_with_name(interner, &name.value)
100 }
101
102 #[inline]
103 pub fn extends_class_with_name(&self, interner: &ThreadedInterner, other: &StringIdentifier) -> bool {
104 let identifier = interner.lowered(other);
105 let Some(other) = self.names.get(&identifier) else {
106 return false;
107 };
108
109 self.all_extended_classes.contains(other)
110 }
111
112 #[inline]
113 pub fn extends_interface(&self, interner: &ThreadedInterner, other: &ClassLikeReflection) -> bool {
114 let Some(name) = other.name.inner() else {
115 return false;
116 };
117
118 self.extends_interface_with_name(interner, &name.value)
119 }
120
121 #[inline]
122 pub fn extends_interface_with_name(&self, interner: &ThreadedInterner, other: &StringIdentifier) -> bool {
123 let identifier = interner.lowered(other);
124 let Some(other) = self.names.get(&identifier) else {
125 return false;
126 };
127
128 self.all_extended_interfaces.contains(other)
129 }
130
131 #[inline]
132 pub fn implements_interface(&self, interner: &ThreadedInterner, other: &ClassLikeReflection) -> bool {
133 let Some(name) = other.name.inner() else {
134 return false;
135 };
136
137 self.implements_interface_with_name(interner, &name.value)
138 }
139
140 #[inline]
141 pub fn implements_interface_with_name(&self, interner: &ThreadedInterner, other: &StringIdentifier) -> bool {
142 let identifier = interner.lowered(other);
143 let Some(other) = self.names.get(&identifier) else {
144 return false;
145 };
146
147 self.all_implemented_interfaces.contains(other)
148 }
149}