Skip to content

Commit 32f0e2c

Browse files
Merge branch 'master' into rust_vs_godot_hashes
2 parents 2dd05c0 + 6a01f75 commit 32f0e2c

File tree

18 files changed

+198
-177
lines changed

18 files changed

+198
-177
lines changed

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ which = "7"
3939
# * quote: 1.0.37 allows tokenizing CStr.
4040
# * venial: 0.6.1 contains some bugfixes.
4141
heck = "0.5"
42-
litrs = "0.4"
42+
litrs = { version = "1.0", features = ["proc-macro2"] }
4343
markdown = "=1.0.0-alpha.23"
4444
nanoserde = "0.2"
4545
proc-macro2 = "1.0.80"

godot-codegen/src/context.rs

Lines changed: 8 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use quote::{format_ident, ToTokens};
1212

1313
use crate::generator::method_tables::MethodTableKey;
1414
use crate::generator::notifications;
15-
use crate::generator::sys::SYS_PARAMS;
1615
use crate::models::domain::{ArgPassing, GodotTy, RustTy, TyName};
1716
use crate::models::json::{
1817
JsonBuiltinClass, JsonBuiltinMethod, JsonClass, JsonClassConstant, JsonClassMethod,
@@ -29,9 +28,6 @@ pub struct Context<'a> {
2928
/// Which interface traits are generated (`false` for "Godot-abstract"/final classes).
3029
classes_final: HashMap<TyName, bool>,
3130
cached_rust_types: HashMap<GodotTy, RustTy>,
32-
/// Various pointers defined in `gdextension_interface`, for example `GDExtensionInitializationFunction`.
33-
/// Used in some APIs that are not exposed to GDScript.
34-
sys_types: HashSet<&'a str>,
3531
notifications_by_class: HashMap<TyName, Vec<(Ident, i32)>>,
3632
classes_with_signals: HashSet<TyName>,
3733
notification_enum_names_by_class: HashMap<TyName, NotificationEnum>,
@@ -47,8 +43,6 @@ impl<'a> Context<'a> {
4743
ctx.singletons.insert(class.name.as_str());
4844
}
4945

50-
Self::populate_sys_types(&mut ctx);
51-
5246
ctx.builtin_types.insert("Variant"); // not part of builtin_classes
5347
for builtin in api.builtin_classes.iter() {
5448
let ty_name = builtin.name.as_str();
@@ -158,14 +152,6 @@ impl<'a> Context<'a> {
158152
ctx
159153
}
160154

161-
/// Adds Godot pointer types to [`Context`].
162-
///
163-
/// Godot pointer types, for example `GDExtensionInitializationFunction`, are defined in `gdextension_interface`
164-
/// but aren't described in `extension_api.json` – despite being used as parameters in various APIs.
165-
fn populate_sys_types(ctx: &mut Context) {
166-
ctx.sys_types.extend(SYS_PARAMS.iter().map(|p| p.type_()));
167-
}
168-
169155
fn populate_notification_constants(
170156
class_name: &TyName,
171157
constants: &[JsonClassConstant],
@@ -266,6 +252,14 @@ impl<'a> Context<'a> {
266252
.unwrap_or_else(|| panic!("did not register table index for key {key:?}"))
267253
}
268254

255+
/// Yields cached sys pointer types – various pointer types declared in `gdextension_interface`
256+
/// and used as parameters in exposed Godot APIs.
257+
pub fn cached_sys_pointer_types(&self) -> impl Iterator<Item = &RustTy> {
258+
self.cached_rust_types
259+
.values()
260+
.filter(|rust_ty| rust_ty.is_sys_pointer())
261+
}
262+
269263
/// Whether an interface trait is generated for a class.
270264
///
271265
/// False if the class is "Godot-abstract"/final, thus there are no virtual functions to inherit.
@@ -307,10 +301,6 @@ impl<'a> Context<'a> {
307301
self.native_structures_types.contains(ty_name)
308302
}
309303

310-
pub fn is_sys(&self, ty_name: &str) -> bool {
311-
self.sys_types.contains(ty_name)
312-
}
313-
314304
pub fn is_singleton(&self, class_name: &TyName) -> bool {
315305
self.singletons.contains(class_name.godot_ty.as_str())
316306
}

godot-codegen/src/conv/type_conversions.rs

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -170,17 +170,20 @@ fn to_rust_type_uncached(full_ty: &GodotTy, ctx: &mut Context) -> RustTy {
170170
ty = ty.replace("const ", "");
171171
}
172172

173-
// .trim() is necessary here, as Godot places a space between a type and the stars when representing a double pointer.
174-
// Example: "int*" but "int **".
175-
if ctx.is_sys(ty.trim()) {
173+
// Sys pointer type defined in `gdextension_interface` and used as param for given method, e.g. `GDExtensionInitializationFunction`.
174+
// Note: we branch here to avoid clashes with actual GDExtension classes.
175+
if ty.starts_with("GDExtension") {
176176
let ty = rustify_ty(&ty);
177177
return RustTy::RawPointer {
178-
inner: Box::new(RustTy::SysIdent {
178+
inner: Box::new(RustTy::SysPointerType {
179179
tokens: quote! { sys::#ty },
180180
}),
181181
is_const,
182182
};
183183
}
184+
185+
// .trim() is necessary here, as Godot places a space between a type and the stars when representing a double pointer.
186+
// Example: "int*" but "int **".
184187
let inner_type = to_rust_type(ty.trim(), None, ctx);
185188
return RustTy::RawPointer {
186189
inner: Box::new(inner_type),

godot-codegen/src/generator/central_files.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use quote::{format_ident, quote, ToTokens};
1010

1111
use crate::context::Context;
1212
use crate::conv;
13-
use crate::generator::sys::make_godotconvert_for_systypes;
13+
use crate::generator::sys_pointer_types::make_godotconvert_for_systypes;
1414
use crate::generator::{enums, gdext_build_struct};
1515
use crate::models::domain::ExtensionApi;
1616
use crate::util::ident;
@@ -61,7 +61,7 @@ pub fn make_core_central_code(api: &ExtensionApi, ctx: &mut Context) -> TokenStr
6161

6262
let (global_enum_defs, global_reexported_enum_defs) = make_global_enums(api);
6363
let variant_type_traits = make_variant_type_enum(api, false);
64-
let sys_types_godotconvert_impl = make_godotconvert_for_systypes();
64+
let sys_types_godotconvert_impl = make_godotconvert_for_systypes(ctx);
6565

6666
// TODO impl Clone, Debug, PartialEq, PartialOrd, Hash for VariantDispatch
6767
// TODO could use try_to().unwrap_unchecked(), since type is already verified. Also directly overload from_variant().
@@ -124,7 +124,10 @@ pub fn make_core_central_code(api: &ExtensionApi, ctx: &mut Context) -> TokenStr
124124
#( #global_reexported_enum_defs )*
125125
}
126126

127-
#( #sys_types_godotconvert_impl )*
127+
pub mod sys_pointer_types {
128+
use crate::sys;
129+
#( #sys_types_godotconvert_impl )*
130+
}
128131
}
129132
}
130133

godot-codegen/src/generator/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ pub mod method_tables;
2828
pub mod native_structures;
2929
pub mod notifications;
3030
pub mod signals;
31-
pub mod sys;
31+
pub mod sys_pointer_types;
3232
pub mod utility_functions;
3333
pub mod virtual_definitions;
3434
pub mod virtual_traits;

godot-codegen/src/generator/sys.rs

Lines changed: 0 additions & 82 deletions
This file was deleted.
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
/*
2+
* Copyright (c) godot-rust; Bromeon and contributors.
3+
* This Source Code Form is subject to the terms of the Mozilla Public
4+
* License, v. 2.0. If a copy of the MPL was not distributed with this
5+
* file, You can obtain one at https://mozilla.org/MPL/2.0/.
6+
*/
7+
8+
use proc_macro2::TokenStream;
9+
use quote::quote;
10+
11+
use crate::context::Context;
12+
13+
/// Creates `GodotConvert`, `ToGodot` and `FromGodot` impl
14+
/// for SysPointerTypes – various pointer types declared in `gdextension_interface`
15+
/// and used as parameters in exposed Godot APIs.
16+
pub fn make_godotconvert_for_systypes(ctx: &mut Context) -> Vec<TokenStream> {
17+
ctx.cached_sys_pointer_types().map(|sys_pointer_type| {
18+
quote! {
19+
impl crate::meta::GodotConvert for #sys_pointer_type {
20+
type Via = i64;
21+
}
22+
23+
impl crate::meta::ToGodot for #sys_pointer_type {
24+
type Pass = crate::meta::ByValue;
25+
fn to_godot(&self) -> Self::Via {
26+
*self as i64
27+
}
28+
}
29+
30+
impl crate::meta::FromGodot for #sys_pointer_type {
31+
fn try_from_godot(via: Self::Via) -> Result <Self, crate::meta::error::ConvertError> {
32+
Ok(via as Self)
33+
}
34+
}
35+
}
36+
}).collect()
37+
}

godot-codegen/src/lib.rs

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -167,19 +167,6 @@ pub fn generate_core_files(core_gen_path: &Path) {
167167
// Deallocate all the JSON models; no longer needed for codegen.
168168
// drop(json_api);
169169

170-
generate_core_central_file(&api, &mut ctx, core_gen_path, &mut submit_fn);
171-
watch.record("generate_central_file");
172-
173-
generate_utilities_file(&api, core_gen_path, &mut submit_fn);
174-
watch.record("generate_utilities_file");
175-
176-
// From 4.4 onward, generate table that maps all virtual methods to their known hashes.
177-
// This allows Godot to fall back to an older compatibility function if one is not supported.
178-
// Also expose tuple signatures of virtual methods.
179-
let code = virtual_definitions::make_virtual_definitions_file(&api, &mut ctx);
180-
submit_fn(core_gen_path.join("virtuals.rs"), code);
181-
watch.record("generate_virtual_definitions");
182-
183170
// Class files -- currently output in godot-core; could maybe be separated cleaner
184171
// Note: deletes entire generated directory!
185172
generate_class_files(
@@ -207,6 +194,22 @@ pub fn generate_core_files(core_gen_path: &Path) {
207194
);
208195
watch.record("generate_native_structures_files");
209196

197+
// Note – generated at the very end since context could be updated while processing other files.
198+
// For example – SysPointerTypes (ones defined in gdextension_interface) are declared only
199+
// as parameters for various APIs.
200+
generate_core_central_file(&api, &mut ctx, core_gen_path, &mut submit_fn);
201+
watch.record("generate_central_file");
202+
203+
generate_utilities_file(&api, core_gen_path, &mut submit_fn);
204+
watch.record("generate_utilities_file");
205+
206+
// From 4.4 onward, generate table that maps all virtual methods to their known hashes.
207+
// This allows Godot to fall back to an older compatibility function if one is not supported.
208+
// Also expose tuple signatures of virtual methods.
209+
let code = virtual_definitions::make_virtual_definitions_file(&api, &mut ctx);
210+
submit_fn(core_gen_path.join("virtuals.rs"), code);
211+
watch.record("generate_virtual_definitions");
212+
210213
#[cfg(feature = "codegen-rustfmt")]
211214
{
212215
rustfmt_files();

godot-codegen/src/models/domain.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -728,7 +728,7 @@ pub enum RustTy {
728728
BuiltinIdent { ty: Ident, arg_passing: ArgPassing },
729729
/// Pointers declared in `gdextension_interface` such as `sys::GDExtensionInitializationFunction`
730730
/// used as parameters in some APIs.
731-
SysIdent { tokens: TokenStream },
731+
SysPointerType { tokens: TokenStream },
732732

733733
/// `Array<i32>`
734734
///
@@ -825,6 +825,13 @@ impl RustTy {
825825
"i8" | "i16" | "i32" | "i64" | "u8" | "u16" | "u32" | "u64" | "isize" | "usize"
826826
)
827827
}
828+
829+
pub fn is_sys_pointer(&self) -> bool {
830+
let RustTy::RawPointer { inner, .. } = self else {
831+
return false;
832+
};
833+
matches!(**inner, RustTy::SysPointerType { .. })
834+
}
828835
}
829836

830837
impl ToTokens for RustTy {
@@ -845,7 +852,7 @@ impl ToTokens for RustTy {
845852
RustTy::EngineClass { tokens: path, .. } => path.to_tokens(tokens),
846853
RustTy::ExtenderReceiver { tokens: path } => path.to_tokens(tokens),
847854
RustTy::GenericArray => quote! { Array<Ret> }.to_tokens(tokens),
848-
RustTy::SysIdent { tokens: path } => path.to_tokens(tokens),
855+
RustTy::SysPointerType { tokens: path } => path.to_tokens(tokens),
849856
}
850857
}
851858
}

godot-codegen/src/special_cases/codegen_special_cases.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ fn is_type_excluded(ty: &str, ctx: &mut Context) -> bool {
5050
RustTy::BuiltinArray { .. } => false,
5151
RustTy::GenericArray => false,
5252
RustTy::RawPointer { inner, .. } => is_rust_type_excluded(inner),
53-
RustTy::SysIdent { .. } => true,
53+
RustTy::SysPointerType { .. } => true,
5454
RustTy::EngineArray { elem_class, .. } => is_class_excluded(elem_class.as_str()),
5555
RustTy::EngineEnum {
5656
surrounding_class, ..

0 commit comments

Comments
 (0)