1use crate::EngineApi;
7use crate::gdscript_layer::{BuiltinFn, GlobalConst};
8use crate::model::{
9 BuiltinData, BuiltinId, ClassData, ClassId, ConstInfo, EnumInfo, MethodSig, OperatorSig,
10 PropertyInfo, SignalSig, UtilityFn,
11};
12use rustc_hash::FxHashSet;
13
14#[derive(Debug, Clone, Copy)]
16pub enum MemberRef<'a> {
17 Method(&'a MethodSig),
19 Property(&'a PropertyInfo),
21 Signal(&'a SignalSig),
23 Const(&'a ConstInfo),
25 Enum(&'a EnumInfo),
27}
28
29impl MemberRef<'_> {
30 #[must_use]
32 pub fn name(&self) -> &str {
33 match self {
34 Self::Method(m) => &m.name,
35 Self::Property(p) => &p.name,
36 Self::Signal(s) => &s.name,
37 Self::Const(c) => &c.name,
38 Self::Enum(e) => &e.name,
39 }
40 }
41}
42
43impl EngineApi {
44 #[must_use]
48 pub fn classes(&self) -> &[ClassData] {
49 &self.data.classes
50 }
51
52 #[must_use]
54 pub fn builtins(&self) -> &[BuiltinData] {
55 &self.data.builtins
56 }
57
58 #[must_use]
60 pub fn class(&self, id: ClassId) -> &ClassData {
61 &self.data.classes[id.0 as usize]
62 }
63
64 #[must_use]
66 pub fn builtin(&self, id: BuiltinId) -> &BuiltinData {
67 &self.data.builtins[id.0 as usize]
68 }
69
70 #[must_use]
74 pub fn class_by_name(&self, name: &str) -> Option<ClassId> {
75 self.class_by_name.get(name).copied()
76 }
77
78 #[must_use]
80 pub fn builtin_by_name(&self, name: &str) -> Option<BuiltinId> {
81 self.builtin_by_name.get(name).copied()
82 }
83
84 #[must_use]
86 pub fn int_builtin(&self) -> Option<BuiltinId> {
87 self.int_builtin
88 }
89
90 #[must_use]
92 pub fn singleton(&self, name: &str) -> Option<ClassId> {
93 self.singleton_by_name.get(name).copied()
94 }
95
96 #[must_use]
98 pub fn utility(&self, name: &str) -> Option<&UtilityFn> {
99 let i = *self.utility_by_name.get(name)?;
100 self.data.utilities.get(i as usize)
101 }
102
103 #[must_use]
105 pub fn global_enum(&self, name: &str) -> Option<&EnumInfo> {
106 let i = *self.global_enum_by_name.get(name)?;
107 self.data.global_enums.get(i as usize)
108 }
109
110 #[must_use]
112 pub fn global_const(&self, name: &str) -> Option<&GlobalConst> {
113 self.global_consts.iter().find(|c| c.name == name)
114 }
115
116 #[must_use]
118 pub fn gdscript_builtin(&self, name: &str) -> Option<&BuiltinFn> {
119 self.gdscript_builtins.iter().find(|f| f.name == name)
120 }
121
122 #[must_use]
126 pub fn lookup_member(&self, class: ClassId, name: &str) -> Option<MemberRef<'_>> {
127 let mut cur = Some(class);
128 while let Some(cid) = cur {
129 let c = self.class(cid);
130 if let Some(m) = c.methods.iter().find(|m| m.name == name) {
131 return Some(MemberRef::Method(m));
132 }
133 if let Some(p) = c.properties.iter().find(|p| p.name == name) {
134 return Some(MemberRef::Property(p));
135 }
136 if let Some(s) = c.signals.iter().find(|s| s.name == name) {
137 return Some(MemberRef::Signal(s));
138 }
139 if let Some(k) = c.constants.iter().find(|k| k.name == name) {
140 return Some(MemberRef::Const(k));
141 }
142 if let Some(e) = c.enums.iter().find(|e| e.name == name) {
143 return Some(MemberRef::Enum(e));
144 }
145 cur = c.base;
146 }
147 None
148 }
149
150 #[must_use]
152 pub fn is_subclass(&self, sub: ClassId, sup: ClassId) -> bool {
153 let mut cur = Some(sub);
154 while let Some(cid) = cur {
155 if cid == sup {
156 return true;
157 }
158 cur = self.class(cid).base;
159 }
160 false
161 }
162
163 #[must_use]
166 pub fn members_of(&self, class: ClassId) -> Vec<MemberRef<'_>> {
167 let mut seen: FxHashSet<&str> = FxHashSet::default();
168 let mut out = Vec::new();
169 let mut cur = Some(class);
170 while let Some(cid) = cur {
171 let c = self.class(cid);
172 for m in &c.methods {
173 if seen.insert(&m.name) {
174 out.push(MemberRef::Method(m));
175 }
176 }
177 for p in &c.properties {
178 if seen.insert(&p.name) {
179 out.push(MemberRef::Property(p));
180 }
181 }
182 for s in &c.signals {
183 if seen.insert(&s.name) {
184 out.push(MemberRef::Signal(s));
185 }
186 }
187 for k in &c.constants {
188 if seen.insert(&k.name) {
189 out.push(MemberRef::Const(k));
190 }
191 }
192 for e in &c.enums {
193 if seen.insert(&e.name) {
194 out.push(MemberRef::Enum(e));
195 }
196 }
197 cur = c.base;
198 }
199 out
200 }
201
202 #[must_use]
206 pub fn builtin_member(&self, builtin: BuiltinId, name: &str) -> Option<&crate::BuiltinMember> {
207 self.builtin(builtin)
208 .members
209 .iter()
210 .find(|m| m.name == name)
211 }
212
213 #[must_use]
215 pub fn builtin_method(&self, builtin: BuiltinId, name: &str) -> Option<&MethodSig> {
216 self.builtin(builtin)
217 .methods
218 .iter()
219 .find(|m| m.name == name)
220 }
221
222 #[must_use]
224 pub fn builtin_operators(&self, builtin: BuiltinId) -> &[OperatorSig] {
225 &self.builtin(builtin).operators
226 }
227}