Skip to main content

gdscript_api/
model.rs

1//! The normalized in-memory Godot engine model — the shape of `extension_api.json` after
2//! `xtask` has resolved its asymmetries (Playbook §4.1/§4.2).
3//!
4//! [`ApiData`] is the serializable root: a set of flat tables (classes, builtins, …) keyed
5//! by integer ids ([`ClassId`]/[`BuiltinId`]). It is what `xtask codegen-api` `rkyv`-encodes
6//! into the bundled blob, and what [`crate::EngineApi`] deserializes and indexes at load.
7//!
8//! Strings are owned (`String`) rather than interned here: the model is built once and
9//! `Arc`-shared, its names are read by reference and never cloned on a hot path, so interning
10//! buys nothing — `SmolStr` is reserved for `gdscript-hir`, where source names *are* cloned
11//! and compared. Keeping the archived form free of custom string/hash types also keeps the
12//! `rkyv` blob trivially portable.
13
14// `rkyv`'s derive emits public `Archived*` companion types we never name; allowing the
15// missing-Debug lint here keeps it on everywhere else. Our own owned types still derive Debug.
16#![allow(missing_debug_implementations)]
17
18use rkyv::{Archive, Deserialize, Serialize};
19
20/// Index of an engine class in [`ApiData::classes`].
21#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)]
22pub struct ClassId(pub u32);
23
24/// Index of a builtin (Variant) type in [`ApiData::builtins`].
25#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)]
26pub struct BuiltinId(pub u32);
27
28/// Index into the lazy documentation store. The Phase-2 thin slice never populates the
29/// store, so every `doc` field is `None`; the fields exist now so wiring docs in is additive
30/// (Playbook §4.6).
31#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Archive, Serialize, Deserialize)]
32pub struct DocId(pub u32);
33
34/// The Godot version the model was generated from.
35#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
36pub struct ApiVersion {
37    /// Major version (e.g. `4`).
38    pub major: u32,
39    /// Minor version (e.g. `5`).
40    pub minor: u32,
41    /// Patch version (e.g. `0`).
42    pub patch: u32,
43    /// Release status (e.g. `stable`).
44    pub status: String,
45}
46
47/// Whether a symbol is part of the runtime API or editor-only (Playbook §4.2 — gate
48/// editor-only symbols out of runtime completion).
49#[derive(Debug, Clone, Copy, PartialEq, Eq, Archive, Serialize, Deserialize)]
50pub enum ApiType {
51    /// Available at runtime.
52    Core,
53    /// Editor-only.
54    Editor,
55}
56
57/// The element type of a typed container. Non-recursive on purpose: Phase 2 does not track
58/// nested element types, so a nested typed container (`Array[Array[int]]`) collapses to its
59/// bare builtin (`Array`) here (Playbook §2). Keeping this flat also keeps the `rkyv` archive
60/// free of recursive `Box` bounds.
61#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
62pub enum ElemRef {
63    /// The dynamic `Variant` top type (a bare container's element).
64    Variant,
65    /// A builtin Variant type (includes bare `Array`/`Dictionary` collapsed from nesting).
66    Builtin(BuiltinId),
67    /// An engine class.
68    Class(ClassId),
69    /// `enum::…` / `bitfield::…` — kept qualified.
70    Enum {
71        /// The dotted name as written after `enum::`/`bitfield::`.
72        qualified: String,
73        /// Whether the source prefix was `bitfield::`.
74        bitfield: bool,
75    },
76}
77
78/// An unresolved API type reference, parsed from the `extension_api.json` type-string grammar
79/// (Playbook §4.2). `Builtin`/`Class` are already resolved to ids at codegen time (second
80/// pass, after the name tables are built); `Enum` keeps its qualified string for `gdscript-hir`
81/// to resolve against a class's / the global enum set.
82#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
83pub enum TyRef {
84    /// No value (`void` return).
85    Void,
86    /// The dynamic `Variant` top type.
87    Variant,
88    /// A builtin Variant type.
89    Builtin(BuiltinId),
90    /// An engine class.
91    Class(ClassId),
92    /// `typedarray::T` → `Array[T]`.
93    TypedArray(ElemRef),
94    /// `typeddictionary::K::V` → `Dictionary[K, V]`.
95    TypedDict(ElemRef, ElemRef),
96    /// `enum::Class.Enum`, `enum::GlobalEnum`, or `bitfield::…` — kept qualified.
97    Enum {
98        /// The dotted name as written after `enum::`/`bitfield::`.
99        qualified: String,
100        /// Whether the source prefix was `bitfield::`.
101        bitfield: bool,
102    },
103}
104
105/// A function/method parameter.
106#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
107pub struct Param {
108    /// The parameter name.
109    pub name: String,
110    /// The parameter type.
111    pub ty: TyRef,
112    /// The default-value **source string** (e.g. `"Vector2(0, 0)"`), displayed verbatim and
113    /// never evaluated (Playbook §4.2). `None` when the parameter is required.
114    pub default: Option<String>,
115}
116
117/// A method signature (engine class method, builtin method, or — without the receiver — a
118/// utility function shares the same shape via [`UtilityFn`]).
119// The four `is_*` flags faithfully mirror the engine's per-method flags; folding them into a
120// bitfield would only obscure that one-to-one mapping.
121#[allow(clippy::struct_excessive_bools)]
122#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
123pub struct MethodSig {
124    /// The method name.
125    pub name: String,
126    /// The parameters, in order.
127    pub params: Vec<Param>,
128    /// The return type (`Void` when the source had no return field).
129    pub return_ty: TyRef,
130    /// `const` (does not mutate the receiver).
131    pub is_const: bool,
132    /// A `static` method (callable on the type).
133    pub is_static: bool,
134    /// Accepts a variable number of trailing arguments.
135    pub is_vararg: bool,
136    /// A virtual method (a `_`-prefixed hook the user overrides).
137    pub is_virtual: bool,
138    /// Documentation handle, when the doc store is populated.
139    pub doc: Option<DocId>,
140}
141
142/// A class property. `enum_of` carries the qualified enum name recovered from the property's
143/// getter (Playbook §4.2 — the JSON reports an enum property's storage type as `int`, but its
144/// getter's return type is `enum::…`).
145#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
146pub struct PropertyInfo {
147    /// The property name.
148    pub name: String,
149    /// The storage type as reported by the JSON (`int` for enum properties).
150    pub ty: TyRef,
151    /// The setter method name, if any.
152    pub setter: Option<String>,
153    /// The getter method name, if any.
154    pub getter: Option<String>,
155    /// The qualified enum name when this property is actually enum-typed (from the getter).
156    pub enum_of: Option<String>,
157    /// Documentation handle, when the doc store is populated.
158    pub doc: Option<DocId>,
159}
160
161/// A signal declaration.
162#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
163pub struct SignalSig {
164    /// The signal name.
165    pub name: String,
166    /// The signal parameters, in order.
167    pub params: Vec<Param>,
168    /// Documentation handle, when the doc store is populated.
169    pub doc: Option<DocId>,
170}
171
172/// One named enum value.
173#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
174pub struct EnumValue {
175    /// The value name (e.g. `SIDE_LEFT`).
176    pub name: String,
177    /// The integer value.
178    pub value: i64,
179}
180
181/// An enum (class enum, builtin enum, or global enum).
182#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
183pub struct EnumInfo {
184    /// The enum name (unqualified).
185    pub name: String,
186    /// Whether the enum is a bitfield (flags).
187    pub is_bitfield: bool,
188    /// The enum values, in declaration order.
189    pub values: Vec<EnumValue>,
190    /// Documentation handle, when the doc store is populated.
191    pub doc: Option<DocId>,
192}
193
194/// A constant. Engine-class constants are integers (notification/flag values); builtin
195/// constants carry a typed source-literal expression (`Vector2(0, 0)`).
196#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
197pub struct ConstInfo {
198    /// The constant name.
199    pub name: String,
200    /// The constant type (`Builtin(int)` for engine-class integer constants).
201    pub ty: TyRef,
202    /// The integer value, for engine-class constants.
203    pub int_value: Option<i64>,
204    /// The source-literal expression, for builtin constants (displayed verbatim).
205    pub value_expr: Option<String>,
206    /// Documentation handle, when the doc store is populated.
207    pub doc: Option<DocId>,
208}
209
210/// An engine class and its members.
211#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
212pub struct ClassData {
213    /// The class name.
214    pub name: String,
215    /// The resolved base class, if any (only `Object` has none).
216    pub base: Option<ClassId>,
217    /// Whether instances are reference-counted (`RefCounted` subtree).
218    pub is_refcounted: bool,
219    /// Whether the class can be instantiated directly.
220    pub is_instantiable: bool,
221    /// Runtime vs. editor-only.
222    pub api_type: ApiType,
223    /// Declared methods (not including inherited).
224    pub methods: Vec<MethodSig>,
225    /// Declared properties.
226    pub properties: Vec<PropertyInfo>,
227    /// Declared signals.
228    pub signals: Vec<SignalSig>,
229    /// Nested enums.
230    pub enums: Vec<EnumInfo>,
231    /// Integer constants.
232    pub constants: Vec<ConstInfo>,
233    /// Documentation handle, when the doc store is populated.
234    pub doc: Option<DocId>,
235}
236
237/// One field of a builtin Variant type (e.g. `Vector2.x`).
238#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
239pub struct BuiltinMember {
240    /// The member name.
241    pub name: String,
242    /// The member type.
243    pub ty: TyRef,
244}
245
246/// A builtin-type operator overload. `right` is `None` for unary operators (`unary-`, `not`).
247#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
248pub struct OperatorSig {
249    /// The operator token as the JSON spells it (`+`, `==`, `unary-`, `and`, …).
250    pub op: String,
251    /// The right-hand operand type, or `None` for a unary operator.
252    pub right: Option<TyRef>,
253    /// The result type.
254    pub result: TyRef,
255}
256
257/// A builtin (Variant) type and its members.
258#[derive(Debug, Clone, Archive, Serialize, Deserialize)]
259pub struct BuiltinData {
260    /// The builtin type name (`Vector2`, `String`, …).
261    pub name: String,
262    /// Named fields (`Vector2.x`).
263    pub members: Vec<BuiltinMember>,
264    /// Methods.
265    pub methods: Vec<MethodSig>,
266    /// Named constants (`Vector2.ZERO`).
267    pub constants: Vec<ConstInfo>,
268    /// Nested enums (`Vector2.Axis`).
269    pub enums: Vec<EnumInfo>,
270    /// Operator overloads.
271    pub operators: Vec<OperatorSig>,
272    /// The element type yielded by `[]` indexing, if the type is indexable.
273    pub indexing_return: Option<TyRef>,
274    /// Whether the type is keyed (dictionary-like indexing).
275    pub is_keyed: bool,
276    /// Documentation handle, when the doc store is populated.
277    pub doc: Option<DocId>,
278}
279
280/// A `@GlobalScope` utility function (`sin`, `print`, `range`, …).
281#[derive(Debug, Clone, PartialEq, Eq, Archive, Serialize, Deserialize)]
282pub struct UtilityFn {
283    /// The function name.
284    pub name: String,
285    /// The parameters, in order.
286    pub params: Vec<Param>,
287    /// The return type.
288    pub return_ty: TyRef,
289    /// Accepts a variable number of trailing arguments.
290    pub is_vararg: bool,
291    /// The JSON `category` (`math`, `random`, `general`).
292    pub category: String,
293    /// Documentation handle, when the doc store is populated.
294    pub doc: Option<DocId>,
295}
296
297/// The serializable engine-model root: flat tables addressed by [`ClassId`]/[`BuiltinId`].
298/// `xtask codegen-api` builds this from `extension_api.json` and `rkyv`-encodes it; the name
299/// indices are rebuilt at load by [`crate::EngineApi`], so they are intentionally absent here.
300#[derive(Debug, Archive, Serialize, Deserialize)]
301pub struct ApiData {
302    /// The source Godot version.
303    pub version: ApiVersion,
304    /// All engine classes, in `extension_api.json` order (alphabetical).
305    pub classes: Vec<ClassData>,
306    /// All builtin Variant types.
307    pub builtins: Vec<BuiltinData>,
308    /// Singletons: `(symbol name, the class it is an instance of)`.
309    pub singletons: Vec<(String, ClassId)>,
310    /// `@GlobalScope` utility functions.
311    pub utilities: Vec<UtilityFn>,
312    /// Global (`@GlobalScope`) enums.
313    pub global_enums: Vec<EnumInfo>,
314}