diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index 1b0297f64..c6e153b0a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -3,11 +3,16 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::{ generator::{ naming::{namespace::NamespaceName, qobject::QObjectName, CombinedIdent}, - rust::qobject::GeneratedRustQObjectBlocks, - utils::rust::syn_type_is_cxx_bridge_unsafe, + rust::qobject::GeneratedRustQObject, + utils::rust::{ + syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified, + syn_type_is_cxx_bridge_unsafe, + }, }, parser::constructor::Constructor, }; @@ -15,7 +20,10 @@ use crate::{ use convert_case::{Case, Casing}; use proc_macro2::{Span, TokenStream}; use quote::{format_ident, quote}; -use syn::{parse_quote, parse_quote_spanned, spanned::Spanned, Expr, Ident, Item, Result, Type}; +use syn::{ + parse_quote, parse_quote_spanned, spanned::Spanned, Expr, FnArg, Ident, Item, Path, Result, + Type, +}; const CONSTRUCTOR_ARGUMENTS: &str = "CxxQtConstructorArguments"; const BASE_ARGUMENTS: &str = "CxxQtConstructorBaseArguments"; @@ -57,7 +65,7 @@ fn argument_members(args: &[Type]) -> Vec { fn generate_default_constructor( qobject_idents: &QObjectName, namespace: &NamespaceName, -) -> GeneratedRustQObjectBlocks { +) -> GeneratedRustQObject { let rust_struct_ident = &qobject_idents.rust_struct.rust; let create_rs_ident = format_ident!( @@ -66,7 +74,7 @@ fn generate_default_constructor( ); let namespace_internals = &namespace.internal; - GeneratedRustQObjectBlocks { + GeneratedRustQObject { cxx_mod_contents: vec![parse_quote! { extern "Rust" { #[cxx_name = "createRs"] @@ -136,16 +144,20 @@ pub fn generate( constructors: &[Constructor], qobject_idents: &QObjectName, namespace: &NamespaceName, -) -> Result { + qualified_mappings: &BTreeMap, + module_ident: &Ident, +) -> Result { if constructors.is_empty() { return Ok(generate_default_constructor(qobject_idents, namespace)); } - let mut result = GeneratedRustQObjectBlocks::default(); + let mut result = GeneratedRustQObject::default(); let namespace_internals = &namespace.internal; let qobject_name = &qobject_idents.cpp_class.cpp; let qobject_name_rust = &qobject_idents.cpp_class.rust; + let qobject_name_rust_qualified = + syn_ident_cxx_bridge_to_qualified_impl(qobject_name_rust, qualified_mappings); let qobject_name_snake = qobject_name.to_string().to_case(Case::Snake); let rust_struct_name_rust = &qobject_idents.rust_struct.rust; @@ -171,15 +183,30 @@ pub fn generate( let route_arguments_rust = format_ident!("route_arguments_{qobject_name_snake}_{index}"); let route_arguemnts_cxx = format!("routeArguments{index}"); - let argument_types = &constructor.arguments; + let argument_types_qualified: Vec = constructor + .arguments + .iter() + .map(|arg| syn_type_cxx_bridge_to_qualified(arg, qualified_mappings)) + .collect(); - let route_arguments_parameters: Vec = constructor + let route_arguments_parameters: Vec = constructor .arguments .iter() .enumerate() .map(|(index, ty)| { let name = format_ident!("arg{index}"); - quote! { #name: #ty } + parse_quote! { #name: #ty } + }) + .collect(); + let route_arguments_parameter_qualified: Vec = route_arguments_parameters + .iter() + .cloned() + .map(|mut parameter| { + if let FnArg::Typed(pat_type) = &mut parameter { + *pat_type.ty = + syn_type_cxx_bridge_to_qualified(&pat_type.ty, qualified_mappings); + } + parameter }) .collect(); let route_arguments_safety = if constructor @@ -273,7 +300,7 @@ pub fn generate( result.cxx_qt_mod_contents.append(&mut vec![parse_quote_spanned! { constructor.imp.span() => #[doc(hidden)] - pub fn #route_arguments_rust(#(#route_arguments_parameters),*) -> #arguments_rust { + pub fn #route_arguments_rust(#(#route_arguments_parameter_qualified),*) -> #module_ident::#arguments_rust { // These variables won't be used if the corresponding argument list is empty. #[allow(unused_variables)] #[allow(clippy::let_unit_value)] @@ -281,12 +308,12 @@ pub fn generate( new_arguments, base_arguments, initialize_arguments - ) = <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>> + ) = <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>> ::route_arguments((#(#assign_arguments,)*)); - #arguments_rust { - base: #init_base_arguments, - initialize: #init_initalize_arguments, - new: #init_new_arguments, + #module_ident::#arguments_rust { + base: #module_ident::#init_base_arguments, + initialize: #module_ident::#init_initalize_arguments, + new: #module_ident::#init_new_arguments, } } }, @@ -294,8 +321,8 @@ pub fn generate( constructor.imp.span() => #[doc(hidden)] #[allow(unused_variables)] - pub fn #new_rust(new_arguments: #new_arguments_rust) -> std::boxed::Box<#rust_struct_name_rust> { - std::boxed::Box::new(<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::new((#(#extract_new_arguments,)*))) + pub fn #new_rust(new_arguments: #module_ident::#new_arguments_rust) -> std::boxed::Box<#rust_struct_name_rust> { + std::boxed::Box::new(<#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::new((#(#extract_new_arguments,)*))) } }, parse_quote_spanned! { @@ -303,10 +330,10 @@ pub fn generate( #[doc(hidden)] #[allow(unused_variables)] pub fn #initialize_rust( - qobject: core::pin::Pin<&mut #qobject_name_rust>, - initialize_arguments: #initialize_arguments_rust + qobject: core::pin::Pin<&mut #qobject_name_rust_qualified>, + initialize_arguments: #module_ident::#initialize_arguments_rust ) { - <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( + <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::initialize( qobject, (#(#extract_initialize_arguments,)*)); } @@ -320,6 +347,8 @@ mod tests { use super::*; use crate::tests::assert_tokens_eq; + use quote::format_ident; + fn mock_constructor() -> Constructor { Constructor { new_arguments: vec![], @@ -339,8 +368,15 @@ mod tests { NamespaceName::from_pair_str("ffi", &format_ident!("MyObject")) } - fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObjectBlocks { - generate(constructors, &mock_name(), &mock_namespace()).unwrap() + fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObject { + generate( + constructors, + &mock_name(), + &mock_namespace(), + &BTreeMap::::default(), + &format_ident!("ffi"), + ) + .unwrap() } #[test] @@ -394,7 +430,7 @@ mod tests { // This is called by the `multiple_constructors` test so we don't have to // assert this in two separate tests. fn assert_empty_constructor_blocks( - blocks: &GeneratedRustQObjectBlocks, + blocks: &GeneratedRustQObject, namespace_attr: &TokenStream, ) { assert_tokens_eq( @@ -450,17 +486,17 @@ mod tests { &blocks.cxx_qt_mod_contents[0], quote! { #[doc(hidden)] - pub fn route_arguments_my_object_0() -> CxxQtConstructorArgumentsMyObject0 + pub fn route_arguments_my_object_0() -> ffi::CxxQtConstructorArgumentsMyObject0 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = >::route_arguments(()); - CxxQtConstructorArgumentsMyObject0 { - base: CxxQtConstructorBaseArgumentsMyObject0 { not_empty: 0 }, - initialize: CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, - new: CxxQtConstructorNewArgumentsMyObject0 { not_empty : 0 }, + ffi::CxxQtConstructorArgumentsMyObject0 { + base: ffi::CxxQtConstructorBaseArgumentsMyObject0 { not_empty: 0 }, + initialize: ffi::CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, + new: ffi::CxxQtConstructorNewArgumentsMyObject0 { not_empty : 0 }, } } }, @@ -470,7 +506,7 @@ mod tests { quote! { #[doc(hidden)] #[allow(unused_variables)] - pub fn new_rs_my_object_0(new_arguments: CxxQtConstructorNewArgumentsMyObject0) -> std::boxed::Box { + pub fn new_rs_my_object_0(new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject0) -> std::boxed::Box { std::boxed::Box::new( >::new(()) ) @@ -484,7 +520,7 @@ mod tests { #[allow(unused_variables)] pub fn initialize_my_object_0( qobject: core::pin::Pin<&mut MyObject>, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0) + initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject0) { >::initialize(qobject, ()); } @@ -492,10 +528,7 @@ mod tests { ); } - fn assert_full_constructor_blocks( - blocks: &GeneratedRustQObjectBlocks, - namespace_attr: &TokenStream, - ) { + fn assert_full_constructor_blocks(blocks: &GeneratedRustQObject, namespace_attr: &TokenStream) { // the index here starts with 5, as this is part of the larger multiple_constructors test. assert_tokens_eq( &blocks.cxx_mod_contents[5], @@ -571,24 +604,24 @@ mod tests { &blocks.cxx_qt_mod_contents[3], quote! { #[doc(hidden)] - pub fn route_arguments_my_object_1(arg0: *const QObject) -> CxxQtConstructorArgumentsMyObject1 + pub fn route_arguments_my_object_1(arg0: *const QObject) -> ffi::CxxQtConstructorArgumentsMyObject1 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = >::route_arguments((arg0,)); - CxxQtConstructorArgumentsMyObject1 { - base: CxxQtConstructorBaseArgumentsMyObject1 { + ffi::CxxQtConstructorArgumentsMyObject1 { + base: ffi::CxxQtConstructorBaseArgumentsMyObject1 { arg0: base_arguments.0, arg1: base_arguments.1, arg2: base_arguments.2, }, - initialize: CxxQtConstructorInitializeArgumentsMyObject1 { + initialize: ffi::CxxQtConstructorInitializeArgumentsMyObject1 { arg0: initialize_arguments.0, arg1: initialize_arguments.1, }, - new: CxxQtConstructorNewArgumentsMyObject1 { + new: ffi::CxxQtConstructorNewArgumentsMyObject1 { arg0: new_arguments.0, }, } @@ -600,7 +633,7 @@ mod tests { quote! { #[doc(hidden)] #[allow(unused_variables)] - pub fn new_rs_my_object_1(new_arguments: CxxQtConstructorNewArgumentsMyObject1) -> std::boxed::Box { + pub fn new_rs_my_object_1(new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject1) -> std::boxed::Box { std::boxed::Box::new( >::new( (new_arguments.arg0,))) @@ -614,7 +647,7 @@ mod tests { #[allow(unused_variables)] pub fn initialize_my_object_1( qobject: core::pin::Pin<&mut MyObject>, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject1) + initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject1) { >::initialize( qobject, diff --git a/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs new file mode 100644 index 000000000..6153bc796 --- /dev/null +++ b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs @@ -0,0 +1,152 @@ +// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company +// SPDX-FileContributor: Andrew Hayzen +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use std::collections::BTreeMap; + +use crate::generator::{ + naming::qobject::QObjectName, rust::qobject::GeneratedRustQObject, + utils::rust::syn_ident_cxx_bridge_to_qualified_impl, +}; +use quote::quote; +use syn::{Ident, Path, Result}; + +use super::fragment::RustFragmentPair; + +pub fn generate( + qobject_ident: &QObjectName, + qualified_mappings: &BTreeMap, +) -> Result { + let mut blocks = GeneratedRustQObject::default(); + + let cpp_struct_ident = &qobject_ident.cpp_class.rust; + let rust_struct_ident = &qobject_ident.rust_struct.rust; + let qualified_impl = + syn_ident_cxx_bridge_to_qualified_impl(cpp_struct_ident, qualified_mappings); + + let fragment = RustFragmentPair { + cxx_bridge: vec![ + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRust"] + #[doc(hidden)] + fn cxx_qt_ffi_rust(self: &#cpp_struct_ident) -> &#rust_struct_ident; + } + }, + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRustMut"] + #[doc(hidden)] + fn cxx_qt_ffi_rust_mut(self: Pin<&mut #cpp_struct_ident>) -> Pin<&mut #rust_struct_ident>; + } + }, + ], + implementation: vec![ + quote! { + impl core::ops::Deref for #qualified_impl { + type Target = #rust_struct_ident; + + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } + }, + quote! { + impl cxx_qt::CxxQtType for #qualified_impl { + type Rust = #rust_struct_ident; + + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() + } + + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() + } + } + }, + ], + }; + + blocks + .cxx_mod_contents + .append(&mut fragment.cxx_bridge_as_items()?); + blocks + .cxx_qt_mod_contents + .append(&mut fragment.implementation_as_items()?); + + Ok(blocks) +} + +#[cfg(test)] +mod tests { + use super::*; + + use crate::tests::assert_tokens_eq; + + use crate::parser::qobject::tests::create_parsed_qobject; + + #[test] + fn test_generate_rust_cxxqttype() { + let qobject = create_parsed_qobject(); + let qobject_idents = QObjectName::from(&qobject); + + let generated = generate(&qobject_idents, &BTreeMap::::default()).unwrap(); + + assert_eq!(generated.cxx_mod_contents.len(), 2); + assert_eq!(generated.cxx_qt_mod_contents.len(), 2); + + // CXX bridges + + assert_tokens_eq( + &generated.cxx_mod_contents[0], + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRust"] + #[doc(hidden)] + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; + } + }, + ); + assert_tokens_eq( + &generated.cxx_mod_contents[1], + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRustMut"] + #[doc(hidden)] + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; + } + }, + ); + + // CXX-Qt generated contents + assert_tokens_eq( + &generated.cxx_qt_mod_contents[0], + quote! { + impl core::ops::Deref for MyObject { + type Target = MyObjectRust; + + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } + } + }, + ); + assert_tokens_eq( + &generated.cxx_qt_mod_contents[1], + quote! { + impl cxx_qt::CxxQtType for MyObject { + type Rust = MyObjectRust; + + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() + } + + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() + } + } + }, + ); + } +} diff --git a/crates/cxx-qt-gen/src/generator/rust/inherit.rs b/crates/cxx-qt-gen/src/generator/rust/inherit.rs index cb6358a0b..ec066b106 100644 --- a/crates/cxx-qt-gen/src/generator/rust/inherit.rs +++ b/crates/cxx-qt-gen/src/generator/rust/inherit.rs @@ -4,7 +4,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 use crate::{ - generator::{naming::qobject::QObjectName, rust::qobject::GeneratedRustQObjectBlocks}, + generator::{naming::qobject::QObjectName, rust::qobject::GeneratedRustQObject}, parser::inherit::ParsedInheritedMethod, }; use proc_macro2::TokenStream; @@ -14,8 +14,8 @@ use syn::{Item, Result}; pub fn generate( qobject_ident: &QObjectName, methods: &[ParsedInheritedMethod], -) -> Result { - let mut blocks = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut blocks = GeneratedRustQObject::default(); let qobject_name = &qobject_ident.cpp_class.rust; let mut bridges = methods @@ -71,7 +71,7 @@ mod tests { fn generate_from_foreign( method: ForeignItemFn, safety: Safety, - ) -> Result { + ) -> Result { let inherited_methods = vec![ParsedInheritedMethod::parse(method, safety).unwrap()]; generate(&create_qobjectname(), &inherited_methods) } diff --git a/crates/cxx-qt-gen/src/generator/rust/invokable.rs b/crates/cxx-qt-gen/src/generator/rust/invokable.rs index e601bb957..3dc5c0375 100644 --- a/crates/cxx-qt-gen/src/generator/rust/invokable.rs +++ b/crates/cxx-qt-gen/src/generator/rust/invokable.rs @@ -6,7 +6,7 @@ use crate::{ generator::{ naming::{invokable::QInvokableName, qobject::QObjectName}, - rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObjectBlocks}, + rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObject}, }, parser::invokable::ParsedQInvokable, }; @@ -17,8 +17,8 @@ use syn::Result; pub fn generate_rust_invokables( invokables: &Vec, qobject_idents: &QObjectName, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut generated = GeneratedRustQObject::default(); let cpp_class_name_rust = &qobject_idents.cpp_class.rust; for invokable in invokables { diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index f212b85ab..5906c1f61 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -4,6 +4,7 @@ // SPDX-License-Identifier: MIT OR Apache-2.0 pub mod constructor; +pub mod cxxqttype; pub mod fragment; pub mod inherit; pub mod invokable; @@ -36,13 +37,19 @@ impl GeneratedRustBlocks { Ok(GeneratedRustBlocks { cxx_mod: parser.passthrough_module.clone(), cxx_mod_contents: vec![generate_include(parser)?], - cxx_qt_mod_contents: parser.cxx_qt_data.uses.clone(), + cxx_qt_mod_contents: vec![], namespace: parser.cxx_qt_data.namespace.clone(), qobjects: parser .cxx_qt_data .qobjects .values() - .map(GeneratedRustQObject::from) + .map(|qobject| { + GeneratedRustQObject::from( + qobject, + &parser.cxx_qt_data.qualified_mappings, + &parser.passthrough_module.ident, + ) + }) .collect::>>()?, }) } @@ -117,29 +124,6 @@ mod tests { assert_eq!(rust.qobjects.len(), 1); } - #[test] - fn test_generated_rust_blocks_uses() { - let module: ItemMod = parse_quote! { - #[cxx_qt::bridge(namespace = "cxx_qt")] - mod ffi { - use std::collections::HashMap; - - extern "RustQt" { - #[cxx_qt::qobject] - type MyObject = super::MyObjectRust; - } - } - }; - let parser = Parser::from(module).unwrap(); - - let rust = GeneratedRustBlocks::from(&parser).unwrap(); - assert_eq!(rust.cxx_mod.content.unwrap().1.len(), 0); - assert_eq!(rust.cxx_mod_contents.len(), 1); - assert_eq!(rust.cxx_qt_mod_contents.len(), 1); - assert_eq!(rust.namespace, "cxx_qt"); - assert_eq!(rust.qobjects.len(), 1); - } - #[test] fn test_generated_rust_blocks_cxx_file_stem() { let module: ItemMod = parse_quote! { diff --git a/crates/cxx-qt-gen/src/generator/rust/property/getter.rs b/crates/cxx-qt-gen/src/generator/rust/property/getter.rs index 256aeacea..6c995feca 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/getter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/getter.rs @@ -6,22 +6,26 @@ use crate::generator::{ naming::{property::QPropertyName, qobject::QObjectName}, rust::fragment::RustFragmentPair, - utils::rust::syn_type_cxx_bridge_to_qualified, + utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified}, }; use quote::quote; -use syn::Type; +use std::collections::BTreeMap; +use syn::{Ident, Path, Type}; pub fn generate( idents: &QPropertyName, qobject_idents: &QObjectName, cxx_ty: &Type, + qualified_mappings: &BTreeMap, ) -> RustFragmentPair { let cpp_class_name_rust = &qobject_idents.cpp_class.rust; let getter_wrapper_cpp = idents.getter_wrapper.cpp.to_string(); let getter_rust = &idents.getter.rust; let ident = &idents.name.rust; let ident_str = ident.to_string(); - let qualified_ty = syn_type_cxx_bridge_to_qualified(cxx_ty); + let qualified_ty = syn_type_cxx_bridge_to_qualified(cxx_ty, qualified_mappings); + let qualified_impl = + syn_ident_cxx_bridge_to_qualified_impl(cpp_class_name_rust, qualified_mappings); RustFragmentPair { cxx_bridge: vec![quote! { @@ -31,7 +35,7 @@ pub fn generate( } }], implementation: vec![quote! { - impl #cpp_class_name_rust { + impl #qualified_impl { #[doc = "Getter for the Q_PROPERTY "] #[doc = #ident_str] pub fn #getter_rust(&self) -> &#qualified_ty { diff --git a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs index a90da635e..e1215ceda 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs @@ -10,26 +10,28 @@ pub mod signal; use crate::{ generator::{ naming::{property::QPropertyName, qobject::QObjectName}, - rust::qobject::GeneratedRustQObjectBlocks, + rust::qobject::GeneratedRustQObject, }, parser::property::ParsedQProperty, }; -use syn::Result; +use std::collections::BTreeMap; +use syn::{Ident, Path, Result}; use super::signals::generate_rust_signals; pub fn generate_rust_properties( properties: &Vec, qobject_idents: &QObjectName, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); + qualified_mappings: &BTreeMap, +) -> Result { + let mut generated = GeneratedRustQObject::default(); let mut signals = vec![]; for property in properties { let idents = QPropertyName::from(property); // Getters - let getter = getter::generate(&idents, qobject_idents, &property.ty); + let getter = getter::generate(&idents, qobject_idents, &property.ty, qualified_mappings); generated .cxx_mod_contents .append(&mut getter.cxx_bridge_as_items()?); @@ -38,7 +40,7 @@ pub fn generate_rust_properties( .append(&mut getter.implementation_as_items()?); // Setters - let setter = setter::generate(&idents, qobject_idents, &property.ty); + let setter = setter::generate(&idents, qobject_idents, &property.ty, qualified_mappings); generated .cxx_mod_contents .append(&mut setter.cxx_bridge_as_items()?); @@ -50,7 +52,11 @@ pub fn generate_rust_properties( signals.push(signal::generate(&idents, qobject_idents)); } - generated.append(&mut generate_rust_signals(&signals, qobject_idents)?); + generated.append(&mut generate_rust_signals( + &signals, + qobject_idents, + qualified_mappings, + )?); Ok(generated) } @@ -81,7 +87,12 @@ mod tests { ]; let qobject_idents = create_qobjectname(); - let generated = generate_rust_properties(&properties, &qobject_idents).unwrap(); + let generated = generate_rust_properties( + &properties, + &qobject_idents, + &BTreeMap::::default(), + ) + .unwrap(); // Check that we have the expected number of blocks assert_eq!(generated.cxx_mod_contents.len(), 12); @@ -129,6 +140,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "trivial_property"] pub fn set_trivial_property(mut self: core::pin::Pin<&mut Self>, value: i32) { + use cxx_qt::CxxQtType; if self.trivial_property == value { return; } @@ -181,6 +193,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "opaque_property"] pub fn set_opaque_property(mut self: core::pin::Pin<&mut Self>, value: cxx::UniquePtr) { + use cxx_qt::CxxQtType; if self.opaque_property == value { return; } @@ -233,6 +246,7 @@ mod tests { #[doc = "Setter for the Q_PROPERTY "] #[doc = "unsafe_property"] pub fn set_unsafe_property(mut self: core::pin::Pin<&mut Self>, value: *mut T) { + use cxx_qt::CxxQtType; if self.unsafe_property == value { return; } diff --git a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs index bc8b4c40c..317fb08f1 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs @@ -6,15 +6,20 @@ use crate::generator::{ naming::{property::QPropertyName, qobject::QObjectName}, rust::fragment::RustFragmentPair, - utils::rust::{syn_type_cxx_bridge_to_qualified, syn_type_is_cxx_bridge_unsafe}, + utils::rust::{ + syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified, + syn_type_is_cxx_bridge_unsafe, + }, }; use quote::quote; -use syn::Type; +use std::collections::BTreeMap; +use syn::{Ident, Path, Type}; pub fn generate( idents: &QPropertyName, qobject_idents: &QObjectName, cxx_ty: &Type, + qualified_mappings: &BTreeMap, ) -> RustFragmentPair { let cpp_class_name_rust = &qobject_idents.cpp_class.rust; let setter_wrapper_cpp = idents.setter_wrapper.cpp.to_string(); @@ -22,7 +27,9 @@ pub fn generate( let ident = &idents.name.rust; let ident_str = ident.to_string(); let notify_ident = &idents.notify.rust; - let qualified_ty = syn_type_cxx_bridge_to_qualified(cxx_ty); + let qualified_ty = syn_type_cxx_bridge_to_qualified(cxx_ty, qualified_mappings); + let qualified_impl = + syn_ident_cxx_bridge_to_qualified_impl(cpp_class_name_rust, qualified_mappings); // Determine if unsafe is required due to an unsafe type let has_unsafe = if syn_type_is_cxx_bridge_unsafe(cxx_ty) { @@ -39,10 +46,11 @@ pub fn generate( } }], implementation: vec![quote! { - impl #cpp_class_name_rust { + impl #qualified_impl { #[doc = "Setter for the Q_PROPERTY "] #[doc = #ident_str] pub fn #setter_rust(mut self: core::pin::Pin<&mut Self>, value: #qualified_ty) { + use cxx_qt::CxxQtType; if self.#ident == value { // don't want to set the value again and reemit the signal, // as this can cause binding loops diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 488024510..21a1fafe1 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -3,95 +3,75 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::{ generator::{ naming::{namespace::NamespaceName, qobject::QObjectName}, rust::{ - constructor, fragment::RustFragmentPair, inherit, invokable::generate_rust_invokables, - property::generate_rust_properties, signals::generate_rust_signals, threading, + constructor, cxxqttype, fragment::RustFragmentPair, inherit, + invokable::generate_rust_invokables, property::generate_rust_properties, + signals::generate_rust_signals, threading, }, + utils::rust::syn_ident_cxx_bridge_to_qualified_impl, }, parser::qobject::ParsedQObject, }; use quote::quote; -use syn::{parse_quote, Ident, ImplItem, Item, Result}; +use syn::{Ident, ImplItem, Item, Path, Result}; #[derive(Default)] -pub struct GeneratedRustQObjectBlocks { +pub struct GeneratedRustQObject { /// Module for the CXX bridge pub cxx_mod_contents: Vec, /// Items for the CXX-Qt module pub cxx_qt_mod_contents: Vec, } -impl GeneratedRustQObjectBlocks { +impl GeneratedRustQObject { pub fn append(&mut self, other: &mut Self) { self.cxx_mod_contents.append(&mut other.cxx_mod_contents); self.cxx_qt_mod_contents .append(&mut other.cxx_qt_mod_contents); } -} - -pub struct GeneratedRustQObject { - /// Ident of the Rust name for the C++ object - pub cpp_struct_ident: Ident, - /// Ident of the namespace for CXX-Qt internals of the QObject - pub namespace_internals: String, - /// Ident of the Rust name for the Rust object - pub rust_struct_ident: Ident, - /// The blocks for this QObject - pub blocks: GeneratedRustQObjectBlocks, -} -impl GeneratedRustQObject { - pub fn from(qobject: &ParsedQObject) -> Result { + pub fn from( + qobject: &ParsedQObject, + qualified_mappings: &BTreeMap, + module_ident: &Ident, + ) -> Result { // Create the base object let qobject_idents = QObjectName::from(qobject); let namespace_idents = NamespaceName::from(qobject); let mut generated = GeneratedRustQObject { - cpp_struct_ident: qobject_idents.cpp_class.rust.clone(), - namespace_internals: namespace_idents.internal.clone(), - rust_struct_ident: qobject_idents.rust_struct.rust.clone(), - blocks: GeneratedRustQObjectBlocks { - cxx_mod_contents: vec![], - cxx_qt_mod_contents: qobject.others.clone(), - }, + cxx_mod_contents: vec![], + cxx_qt_mod_contents: qobject.others.clone(), }; - generated - .blocks - .append(&mut generate_qobject_definitions(&qobject_idents)?); - - // Add a type alias so that generated code can still find T - // - // TODO: this should be removed once generated methods aren't in the hidden module - generated.blocks.cxx_qt_mod_contents.push({ - let rust_struct_name_rust = &qobject_idents.rust_struct.rust; - parse_quote! { - type #rust_struct_name_rust = super::#rust_struct_name_rust; - } - }); + generated.append(&mut generate_qobject_definitions(&qobject_idents)?); // Generate methods for the properties, invokables, signals - generated.blocks.append(&mut generate_rust_properties( + generated.append(&mut generate_rust_properties( &qobject.properties, &qobject_idents, + qualified_mappings, )?); - generated.blocks.append(&mut generate_rust_invokables( + generated.append(&mut generate_rust_invokables( &qobject.invokables, &qobject_idents, )?); - generated.blocks.append(&mut generate_passthrough_impl( + generated.append(&mut generate_passthrough_impl( &qobject.passthrough_impl_items, &qobject_idents, )?); - generated.blocks.append(&mut inherit::generate( + generated.append(&mut inherit::generate( &qobject_idents, &qobject.inherited_methods, )?); - generated.blocks.append(&mut generate_rust_signals( + generated.append(&mut generate_rust_signals( &qobject.signals, &qobject_idents, + qualified_mappings, )?); // If this type is a singleton then we need to add an include @@ -106,7 +86,6 @@ impl GeneratedRustQObject { implementation: vec![], }; generated - .blocks .cxx_mod_contents .append(&mut fragment.cxx_bridge_as_items()?); } @@ -114,9 +93,11 @@ impl GeneratedRustQObject { // If this type has threading enabled then add generation if qobject.threading { - generated.blocks.append(&mut threading::generate( + generated.append(&mut threading::generate( &qobject_idents, &namespace_idents, + qualified_mappings, + module_ident, )?); } @@ -125,19 +106,26 @@ impl GeneratedRustQObject { // This could be implemented using an auto trait in the future once stable // https://doc.rust-lang.org/beta/unstable-book/language-features/auto-traits.html if qobject.locking { - let cpp_class_name_rust = &qobject_idents.cpp_class.rust; - generated - .blocks - .cxx_qt_mod_contents - .push(syn::parse_quote! { - impl cxx_qt::Locking for #cpp_class_name_rust {} - }); + let qualified_impl = syn_ident_cxx_bridge_to_qualified_impl( + &qobject_idents.cpp_class.rust, + qualified_mappings, + ); + generated.cxx_qt_mod_contents.push(syn::parse_quote! { + impl cxx_qt::Locking for #qualified_impl {} + }); } - generated.blocks.append(&mut constructor::generate( + generated.append(&mut constructor::generate( &qobject.constructors, &qobject_idents, &namespace_idents, + qualified_mappings, + module_ident, + )?); + + generated.append(&mut cxxqttype::generate( + &qobject_idents, + qualified_mappings, )?); Ok(generated) @@ -148,8 +136,8 @@ impl GeneratedRustQObject { pub fn generate_passthrough_impl( impl_items: &[ImplItem], qobject_idents: &QObjectName, -) -> Result { - let mut blocks = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut blocks = GeneratedRustQObject::default(); blocks.cxx_qt_mod_contents.extend_from_slice( &impl_items .iter() @@ -169,10 +157,8 @@ pub fn generate_passthrough_impl( } /// Generate the C++ and Rust CXX definitions for the QObject -fn generate_qobject_definitions( - qobject_idents: &QObjectName, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); +fn generate_qobject_definitions(qobject_idents: &QObjectName) -> Result { + let mut generated = GeneratedRustQObject::default(); let cpp_class_name_rust = &qobject_idents.cpp_class.rust; let rust_struct_name_rust = &qobject_idents.rust_struct.rust; let rust_struct_name_rust_str = rust_struct_name_rust.to_string(); @@ -211,48 +197,9 @@ mod tests { use crate::parser::Parser; use crate::tests::assert_tokens_eq; + use quote::format_ident; use syn::{parse_quote, ItemMod}; - #[test] - fn test_generated_rust_qobject_blocks() { - let module: ItemMod = parse_quote! { - #[cxx_qt::bridge] - mod ffi { - extern "RustQt" { - #[cxx_qt::qobject] - type MyObject = super::MyObjectRust; - } - } - }; - let parser = Parser::from(module).unwrap(); - - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); - assert_eq!(rust.cpp_struct_ident, "MyObject"); - assert_eq!(rust.namespace_internals, "cxx_qt_my_object"); - assert_eq!(rust.rust_struct_ident, "MyObjectRust"); - } - - #[test] - fn test_generated_rust_qobject_blocks_namespace() { - let module: ItemMod = parse_quote! { - #[cxx_qt::bridge(namespace = "cxx_qt")] - mod ffi { - extern "RustQt" { - #[cxx_qt::qobject] - type MyObject = super::MyObjectRust; - } - } - }; - let parser = Parser::from(module).unwrap(); - - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); - assert_eq!(rust.cpp_struct_ident, "MyObject"); - assert_eq!(rust.namespace_internals, "cxx_qt::cxx_qt_my_object"); - assert_eq!(rust.rust_struct_ident, "MyObjectRust"); - } - #[test] fn test_generated_rust_qobject_blocks_singleton() { let module: ItemMod = parse_quote! { @@ -266,11 +213,15 @@ mod tests { }; let parser = Parser::from(module).unwrap(); - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); - assert_eq!(rust.blocks.cxx_mod_contents.len(), 4); + let rust = GeneratedRustQObject::from( + parser.cxx_qt_data.qobjects.values().next().unwrap(), + &BTreeMap::::default(), + &format_ident!("ffi"), + ) + .unwrap(); + assert_eq!(rust.cxx_mod_contents.len(), 6); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[0], + &rust.cxx_mod_contents[0], quote! { unsafe extern "C++" { #[doc = "The C++ type for the QObject "] @@ -284,7 +235,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[1], + &rust.cxx_mod_contents[1], quote! { extern "Rust" { type MyObjectRust; @@ -292,7 +243,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[2], + &rust.cxx_mod_contents[2], quote! { unsafe extern "C++" { include!(); @@ -300,7 +251,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[3], + &rust.cxx_mod_contents[3], quote! { extern "Rust" { #[cxx_name = "createRs"] @@ -309,5 +260,25 @@ mod tests { } }, ); + assert_tokens_eq( + &rust.cxx_mod_contents[4], + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRust"] + #[doc(hidden)] + fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; + } + }, + ); + assert_tokens_eq( + &rust.cxx_mod_contents[5], + quote! { + unsafe extern "C++" { + #[cxx_name = "unsafeRustMut"] + #[doc(hidden)] + fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; + } + }, + ); } } diff --git a/crates/cxx-qt-gen/src/generator/rust/signals.rs b/crates/cxx-qt-gen/src/generator/rust/signals.rs index 7ff52ed25..4891d14cd 100644 --- a/crates/cxx-qt-gen/src/generator/rust/signals.rs +++ b/crates/cxx-qt-gen/src/generator/rust/signals.rs @@ -3,22 +3,25 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::{ generator::{ naming::{qobject::QObjectName, signals::QSignalName}, - rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObjectBlocks}, - utils::rust::syn_type_cxx_bridge_to_qualified, + rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObject}, + utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified}, }, parser::signals::ParsedSignal, }; use quote::quote; -use syn::{parse_quote, FnArg, Result}; +use syn::{parse_quote, FnArg, Ident, Path, Result}; pub fn generate_rust_signals( signals: &Vec, qobject_idents: &QObjectName, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); + qualified_mappings: &BTreeMap, +) -> Result { + let mut generated = GeneratedRustQObject::default(); let qobject_name = &qobject_idents.cpp_class.rust; // Create the methods for the other signals @@ -47,7 +50,8 @@ pub fn generate_rust_signals( .cloned() .map(|mut parameter| { if let FnArg::Typed(pat_type) = &mut parameter { - *pat_type.ty = syn_type_cxx_bridge_to_qualified(&pat_type.ty); + *pat_type.ty = + syn_type_cxx_bridge_to_qualified(&pat_type.ty, qualified_mappings); } parameter }) @@ -58,7 +62,10 @@ pub fn generate_rust_signals( } else { parse_quote! { &#qobject_name } }; - let self_type_qualified = syn_type_cxx_bridge_to_qualified(&self_type_cxx); + let self_type_qualified = + syn_type_cxx_bridge_to_qualified(&self_type_cxx, qualified_mappings); + let qualified_impl = + syn_ident_cxx_bridge_to_qualified_impl(qobject_name, qualified_mappings); let mut unsafe_block = None; let mut unsafe_call = Some(quote! { unsafe }); @@ -89,7 +96,7 @@ pub fn generate_rust_signals( }, ], implementation: vec![quote! { - impl #qobject_name { + impl #qualified_impl { #[doc = "Connect the given function pointer to the signal "] #[doc = #signal_name_cpp_str] #[doc = ", so that when the signal is emitted the function pointer is executed."] @@ -143,7 +150,12 @@ mod tests { }; let qobject_idents = create_qobjectname(); - let generated = generate_rust_signals(&vec![qsignal], &qobject_idents).unwrap(); + let generated = generate_rust_signals( + &vec![qsignal], + &qobject_idents, + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 1); @@ -217,7 +229,12 @@ mod tests { }; let qobject_idents = create_qobjectname(); - let generated = generate_rust_signals(&vec![qsignal], &qobject_idents).unwrap(); + let generated = generate_rust_signals( + &vec![qsignal], + &qobject_idents, + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 1); @@ -285,7 +302,12 @@ mod tests { }; let qobject_idents = create_qobjectname(); - let generated = generate_rust_signals(&vec![qsignal], &qobject_idents).unwrap(); + let generated = generate_rust_signals( + &vec![qsignal], + &qobject_idents, + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 1); @@ -350,7 +372,12 @@ mod tests { }; let qobject_idents = create_qobjectname(); - let generated = generate_rust_signals(&vec![qsignal], &qobject_idents).unwrap(); + let generated = generate_rust_signals( + &vec![qsignal], + &qobject_idents, + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 1); diff --git a/crates/cxx-qt-gen/src/generator/rust/threading.rs b/crates/cxx-qt-gen/src/generator/rust/threading.rs index 1f897dc3e..60f3b4a6d 100644 --- a/crates/cxx-qt-gen/src/generator/rust/threading.rs +++ b/crates/cxx-qt-gen/src/generator/rust/threading.rs @@ -3,23 +3,28 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::generator::{ naming::{ namespace::{namespace_combine_ident, NamespaceName}, qobject::QObjectName, }, - rust::qobject::GeneratedRustQObjectBlocks, + rust::qobject::GeneratedRustQObject, + utils::rust::syn_ident_cxx_bridge_to_qualified_impl, }; use quote::quote; -use syn::Result; +use syn::{Ident, Path, Result}; use super::fragment::RustFragmentPair; pub fn generate( qobject_ident: &QObjectName, namespace_ident: &NamespaceName, -) -> Result { - let mut blocks = GeneratedRustQObjectBlocks::default(); + qualified_mappings: &BTreeMap, + module_ident: &Ident, +) -> Result { + let mut blocks = GeneratedRustQObject::default(); let cpp_struct_ident = &qobject_ident.cpp_class.rust; let cxx_qt_thread_ident = &qobject_ident.cxx_qt_thread_class; @@ -30,6 +35,8 @@ pub fn generate( let namespace_internals = &namespace_ident.internal; let cxx_qt_thread_ident_type_id_str = namespace_combine_ident(&namespace_ident.namespace, cxx_qt_thread_ident); + let qualified_impl = + syn_ident_cxx_bridge_to_qualified_impl(cpp_struct_ident, qualified_mappings); let fragment = RustFragmentPair { cxx_bridge: vec![ @@ -81,19 +88,19 @@ pub fn generate( ], implementation: vec![ quote! { - impl cxx_qt::Threading for #cpp_struct_ident { + impl cxx_qt::Threading for #qualified_impl { type BoxedQueuedFn = #cxx_qt_thread_queued_fn_ident; type ThreadingTypeId = cxx::type_id!(#cxx_qt_thread_ident_type_id_str); - fn qt_thread(&self) -> #cxx_qt_thread_ident + fn qt_thread(&self) -> #module_ident::#cxx_qt_thread_ident { self.cxx_qt_ffi_qt_thread() } #[doc(hidden)] - fn queue(cxx_qt_thread: &#cxx_qt_thread_ident, f: F) -> std::result::Result<(), cxx::Exception> + fn queue(cxx_qt_thread: &#module_ident::#cxx_qt_thread_ident, f: F) -> std::result::Result<(), cxx::Exception> where - F: FnOnce(core::pin::Pin<&mut #cpp_struct_ident>), + F: FnOnce(core::pin::Pin<&mut #qualified_impl>), F: Send + 'static, { // Wrap the given closure and pass in to C++ function as an opaque type @@ -102,25 +109,25 @@ pub fn generate( #[allow(clippy::boxed_local)] #[doc(hidden)] fn func( - obj: core::pin::Pin<&mut #cpp_struct_ident>, + obj: core::pin::Pin<&mut #qualified_impl>, arg: std::boxed::Box<#cxx_qt_thread_queued_fn_ident>, ) { (arg.inner)(obj) } let arg = #cxx_qt_thread_queued_fn_ident { inner: std::boxed::Box::new(f) }; - #cxx_qt_thread_queue_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) + #module_ident::#cxx_qt_thread_queue_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) } #[doc(hidden)] - fn threading_clone(cxx_qt_thread: &#cxx_qt_thread_ident) -> #cxx_qt_thread_ident + fn threading_clone(cxx_qt_thread: &#module_ident::#cxx_qt_thread_ident) -> #module_ident::#cxx_qt_thread_ident { - #cxx_qt_thread_clone(cxx_qt_thread) + #module_ident::#cxx_qt_thread_clone(cxx_qt_thread) } #[doc(hidden)] - fn threading_drop(cxx_qt_thread: &mut #cxx_qt_thread_ident) + fn threading_drop(cxx_qt_thread: &mut #module_ident::#cxx_qt_thread_ident) { - #cxx_qt_thread_drop(cxx_qt_thread); + #module_ident::#cxx_qt_thread_drop(cxx_qt_thread); } } }, @@ -129,7 +136,7 @@ pub fn generate( pub struct #cxx_qt_thread_queued_fn_ident { // An opaque Rust type is required to be Sized. // https://github.com/dtolnay/cxx/issues/665 - inner: std::boxed::Box) + Send>, + inner: std::boxed::Box) + Send>, } }, ], @@ -153,13 +160,21 @@ mod tests { use crate::parser::qobject::tests::create_parsed_qobject; + use quote::format_ident; + #[test] fn test_generate_rust_threading() { let qobject = create_parsed_qobject(); let qobject_idents = QObjectName::from(&qobject); let namespace_ident = NamespaceName::from(&qobject); - let generated = generate(&qobject_idents, &namespace_ident).unwrap(); + let generated = generate( + &qobject_idents, + &namespace_ident, + &BTreeMap::::default(), + &format_ident!("ffi"), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 2); @@ -220,13 +235,13 @@ mod tests { type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; type ThreadingTypeId = cxx::type_id!("MyObjectCxxQtThread"); - fn qt_thread(&self) -> MyObjectCxxQtThread + fn qt_thread(&self) -> ffi::MyObjectCxxQtThread { self.cxx_qt_ffi_qt_thread() } #[doc(hidden)] - fn queue(cxx_qt_thread: &MyObjectCxxQtThread, f: F) -> std::result::Result<(), cxx::Exception> + fn queue(cxx_qt_thread: &ffi::MyObjectCxxQtThread, f: F) -> std::result::Result<(), cxx::Exception> where F: FnOnce(core::pin::Pin<&mut MyObject>), F: Send + 'static, @@ -243,19 +258,19 @@ mod tests { (arg.inner)(obj) } let arg = MyObjectCxxQtThreadQueuedFn { inner: std::boxed::Box::new(f) }; - cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) + ffi::cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) } #[doc(hidden)] - fn threading_clone(cxx_qt_thread: &MyObjectCxxQtThread) -> MyObjectCxxQtThread + fn threading_clone(cxx_qt_thread: &ffi::MyObjectCxxQtThread) -> ffi::MyObjectCxxQtThread { - cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) + ffi::cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) } #[doc(hidden)] - fn threading_drop(cxx_qt_thread: &mut MyObjectCxxQtThread) + fn threading_drop(cxx_qt_thread: &mut ffi::MyObjectCxxQtThread) { - cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread); + ffi::cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread); } } }, diff --git a/crates/cxx-qt-gen/src/generator/utils/rust.rs b/crates/cxx-qt-gen/src/generator/utils/rust.rs index 80ff3014f..93787f403 100644 --- a/crates/cxx-qt-gen/src/generator/utils/rust.rs +++ b/crates/cxx-qt-gen/src/generator/utils/rust.rs @@ -3,28 +3,55 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use syn::{GenericArgument, PathArguments, PathSegment, ReturnType, Type, TypeReference}; +use std::collections::BTreeMap; + +use syn::{ + GenericArgument, Ident, Path, PathArguments, PathSegment, ReturnType, Type, TypeReference, +}; + +/// Return a qualified version of the ident that can by used for impl T outside of a CXX bridge +/// +/// Eg MyObject -> ffi::MyObject +/// +/// Note that this does not handle CXX types such as UniquePtr -> cxx::UniquePtr. +/// This is just for resolving impl T {} -> impl module::T {} +pub(crate) fn syn_ident_cxx_bridge_to_qualified_impl( + ident: &syn::Ident, + qualified_mappings: &BTreeMap, +) -> syn::Path { + if let Some(qualified_path) = qualified_mappings.get(ident) { + qualified_path.clone() + } else { + Path::from(ident.clone()) + } +} /// Return a qualified version of the type that can by used outside of a CXX bridge /// /// Eg Pin -> core::pin::Pin or UniquePtr -> cxx::UniquePtr -pub(crate) fn syn_type_cxx_bridge_to_qualified(ty: &syn::Type) -> syn::Type { +/// +/// And also resolves any qualified mappings +/// +/// Eg MyObject -> ffi::MyObject +pub(crate) fn syn_type_cxx_bridge_to_qualified( + ty: &syn::Type, + qualified_mappings: &BTreeMap, +) -> syn::Type { match ty { Type::Array(ty_array) => { let mut ty_array = ty_array.clone(); - *ty_array.elem = syn_type_cxx_bridge_to_qualified(&ty_array.elem); + *ty_array.elem = syn_type_cxx_bridge_to_qualified(&ty_array.elem, qualified_mappings); return Type::Array(ty_array); } Type::BareFn(ty_bare_fn) => { let mut ty_bare_fn = ty_bare_fn.clone(); if let ReturnType::Type(_, ty) = &mut ty_bare_fn.output { - **ty = syn_type_cxx_bridge_to_qualified(ty); + **ty = syn_type_cxx_bridge_to_qualified(ty, qualified_mappings); } - ty_bare_fn - .inputs - .iter_mut() - .for_each(|arg| arg.ty = syn_type_cxx_bridge_to_qualified(&arg.ty)); + ty_bare_fn.inputs.iter_mut().for_each(|arg| { + arg.ty = syn_type_cxx_bridge_to_qualified(&arg.ty, qualified_mappings) + }); return Type::BareFn(ty_bare_fn); } @@ -36,7 +63,7 @@ pub(crate) fn syn_type_cxx_bridge_to_qualified(ty: &syn::Type) -> syn::Type { if let PathArguments::AngleBracketed(angled) = &mut segment.arguments { angled.args.iter_mut().for_each(|arg| { if let GenericArgument::Type(ty) = arg { - *ty = syn_type_cxx_bridge_to_qualified(ty); + *ty = syn_type_cxx_bridge_to_qualified(ty, qualified_mappings); } }); } @@ -66,29 +93,33 @@ pub(crate) fn syn_type_cxx_bridge_to_qualified(ty: &syn::Type) -> syn::Type { } } + // If the path matches a known ident then used the qualified mapping + if let Some(ident) = ty_path.path.get_ident() { + ty_path.path = syn_ident_cxx_bridge_to_qualified_impl(ident, qualified_mappings); + } + return Type::Path(ty_path); } Type::Ptr(ty_ptr) => { let mut ty_ptr = ty_ptr.clone(); - *ty_ptr.elem = syn_type_cxx_bridge_to_qualified(&ty_ptr.elem); + *ty_ptr.elem = syn_type_cxx_bridge_to_qualified(&ty_ptr.elem, qualified_mappings); return Type::Ptr(ty_ptr); } Type::Reference(ty_ref) => { let mut ty_ref = ty_ref.clone(); - *ty_ref.elem = syn_type_cxx_bridge_to_qualified(&ty_ref.elem); + *ty_ref.elem = syn_type_cxx_bridge_to_qualified(&ty_ref.elem, qualified_mappings); return Type::Reference(ty_ref); } Type::Slice(ty_slice) => { let mut ty_slice = ty_slice.clone(); - *ty_slice.elem = syn_type_cxx_bridge_to_qualified(&ty_slice.elem); + *ty_slice.elem = syn_type_cxx_bridge_to_qualified(&ty_slice.elem, qualified_mappings); return Type::Slice(ty_slice); } Type::Tuple(ty_tuple) => { let mut ty_tuple = ty_tuple.clone(); - ty_tuple - .elems - .iter_mut() - .for_each(|elem| *elem = syn_type_cxx_bridge_to_qualified(elem)); + ty_tuple.elems.iter_mut().for_each(|elem| { + *elem = syn_type_cxx_bridge_to_qualified(elem, qualified_mappings) + }); return Type::Tuple(ty_tuple); } _others => {} @@ -125,28 +156,30 @@ pub(crate) fn syn_type_is_cxx_bridge_unsafe(ty: &syn::Type) -> bool { mod tests { use super::*; + use quote::format_ident; use syn::parse_quote; #[test] fn test_syn_type_cxx_bridge_to_qualified_cxx() { + let mappings = BTreeMap::::default(); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { CxxString }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { CxxString }, &mappings), parse_quote! { cxx::CxxString } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { CxxVector }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { CxxVector }, &mappings), parse_quote! { cxx::CxxVector } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { SharedPtr }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { SharedPtr }, &mappings), parse_quote! { cxx::SharedPtr } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { UniquePtr }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { UniquePtr }, &mappings), parse_quote! { cxx::UniquePtr } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { WeakPtr }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { WeakPtr }, &mappings), parse_quote! { cxx::WeakPtr } ); } @@ -154,7 +187,10 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_core() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { Pin<&mut T> }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { Pin<&mut T> }, + &BTreeMap::::default() + ), parse_quote! { core::pin::Pin<&mut T> } ); } @@ -162,7 +198,10 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_array() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { [UniquePtr; 1] }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { [UniquePtr; 1] }, + &BTreeMap::::default() + ), parse_quote! { [cxx::UniquePtr; 1] } ); } @@ -170,7 +209,10 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_fn() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { fn(UniquePtr) -> SharedPtr }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { fn(UniquePtr) -> SharedPtr }, + &BTreeMap::::default() + ), parse_quote! { fn(cxx::UniquePtr) -> cxx::SharedPtr } ); } @@ -178,7 +220,10 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_nested() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { Pin> }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { Pin> }, + &BTreeMap::::default() + ), parse_quote! { core::pin::Pin> } ); } @@ -186,31 +231,36 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_ptr() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { *mut UniquePtr }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { *mut UniquePtr }, + &BTreeMap::::default() + ), parse_quote! { *mut cxx::UniquePtr } ); } #[test] fn test_syn_type_cxx_bridge_to_qualified_reference() { + let mappings = BTreeMap::::default(); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { &UniquePtr<*mut T> }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { &UniquePtr<*mut T> }, &mappings), parse_quote! { &cxx::UniquePtr<*mut T> } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { &mut UniquePtr<*mut T> }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { &mut UniquePtr<*mut T> }, &mappings), parse_quote! { &mut cxx::UniquePtr<*mut T> } ); } #[test] fn test_syn_type_cxx_bridge_to_qualified_slice() { + let mappings = BTreeMap::::default(); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { &[UniquePtr] }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { &[UniquePtr] }, &mappings), parse_quote! { &[cxx::UniquePtr] } ); assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { &mut [UniquePtr] }), + syn_type_cxx_bridge_to_qualified(&parse_quote! { &mut [UniquePtr] }, &mappings), parse_quote! { &mut [cxx::UniquePtr] } ); } @@ -218,11 +268,34 @@ mod tests { #[test] fn test_syn_type_cxx_bridge_to_qualified_tuple() { assert_eq!( - syn_type_cxx_bridge_to_qualified(&parse_quote! { (UniquePtr, ) }), + syn_type_cxx_bridge_to_qualified( + &parse_quote! { (UniquePtr, ) }, + &BTreeMap::::default() + ), parse_quote! { (cxx::UniquePtr, ) } ); } + #[test] + fn test_syn_type_cxx_bridge_to_qualified_mapped() { + let mut mappings = BTreeMap::::default(); + mappings.insert(format_ident!("A"), parse_quote! { ffi::B }); + assert_eq!( + syn_type_cxx_bridge_to_qualified(&parse_quote! { A }, &mappings), + parse_quote! { ffi::B } + ); + } + + #[test] + fn test_syn_ident_cxx_bridge_to_qualified_impl_mapped() { + let mut mappings = BTreeMap::::default(); + mappings.insert(format_ident!("A"), parse_quote! { ffi::B }); + assert_eq!( + syn_ident_cxx_bridge_to_qualified_impl(&parse_quote! { A }, &mappings), + parse_quote! { ffi::B } + ); + } + #[test] fn test_syn_type_is_cxx_bridge_unsafe_path() { assert!(!syn_type_is_cxx_bridge_unsafe(&parse_quote! { i32 })); diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index 6098db63f..65a3b7ee1 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -10,9 +10,12 @@ use crate::{ parser::{inherit::ParsedInheritedMethod, qobject::ParsedQObject, signals::ParsedSignal}, syntax::expr::expr_to_string, }; +use quote::format_ident; use std::collections::BTreeMap; -use syn::ForeignItem; -use syn::{Attribute, Error, Ident, Item, ItemForeignMod, ItemImpl, Result, Type, TypePath}; +use syn::{ + parse_quote, spanned::Spanned, Attribute, Error, ForeignItem, Ident, Item, ItemForeignMod, + ItemImpl, Path, Result, Type, TypePath, +}; use super::invokable::ParsedQInvokable; @@ -48,8 +51,10 @@ impl ParsedCxxMappings { #[derive(Default)] pub struct ParsedCxxQtData { - /// Mappings for + /// Mappings for CXX types when used in C++ pub cxx_mappings: ParsedCxxMappings, + /// Mappings for CXX types when used outside the bridge + pub qualified_mappings: BTreeMap, /// Map of the QObjects defined in the module that will be used for code generation // // We have to use a BTreeMap here, instead of a HashMap, to keep the order of QObjects stable. @@ -57,8 +62,6 @@ pub struct ParsedCxxQtData { pub qobjects: BTreeMap, /// The namespace of the CXX-Qt module pub namespace: String, - /// Any `use` statements end up in the CXX-Qt generated module - pub uses: Vec, } impl ParsedCxxQtData { @@ -100,21 +103,23 @@ impl ParsedCxxQtData { Ok(()) } - /// Search through Item's and look for a cxx_name or namespace attribute on a type + /// Search through Item's and look for a cxx_name, rust_name, or namespace attribute on a type /// /// We need to know this as it affects the type name used in the C++ generation - pub fn populate_cxx_mappings_from_item( + /// And it is used to create the qualified Rust name + pub fn populate_mappings_from_item( &mut self, item: &Item, bridge_namespace: &str, + module_ident: &Ident, ) -> Result<()> { // Consider if shared types have mappings match item { Item::Enum(item) => { - self.populate_cxx_mappings(&item.ident, &item.attrs, bridge_namespace)?; + self.populate_mappings(&item.ident, &item.attrs, bridge_namespace, module_ident)?; } Item::Struct(item) => { - self.populate_cxx_mappings(&item.ident, &item.attrs, bridge_namespace)?; + self.populate_mappings(&item.ident, &item.attrs, bridge_namespace, module_ident)?; } _others => {} } @@ -131,10 +136,11 @@ impl ParsedCxxQtData { // Read each of the types in the mod (type A;) for foreign_type in foreign_mod_to_foreign_item_types(foreign_mod)? { - self.populate_cxx_mappings( + self.populate_mappings( &foreign_type.ident, &foreign_type.attrs, &block_namespace, + module_ident, )?; } } @@ -142,12 +148,13 @@ impl ParsedCxxQtData { Ok(()) } - /// Helper which adds cxx_name and namespace mappings from the ident, attrs, and parent namespace - fn populate_cxx_mappings( + /// Helper which adds cxx_name, rust_name, and namespace mappings from the ident, attrs, parent namespace, and module ident + fn populate_mappings( &mut self, ident: &Ident, attrs: &[Attribute], parent_namespace: &str, + module_ident: &Ident, ) -> Result<()> { // Retrieve the namespace for the type itself if there is one let namespace = if let Some(index) = attribute_find_path(attrs, &["namespace"]) { @@ -171,6 +178,19 @@ impl ParsedCxxQtData { .insert(ident.to_string(), namespace); } + // Add type to qualified mappings + let rust_ident = if let Some(index) = attribute_find_path(attrs, &["rust_name"]) { + format_ident!( + "{}", + expr_to_string(&attrs[index].meta.require_name_value()?.value)?, + span = attrs[index].span() + ) + } else { + ident.clone() + }; + self.qualified_mappings + .insert(ident.clone(), parse_quote! { #module_ident::#rust_ident }); + Ok(()) } @@ -180,11 +200,6 @@ impl ParsedCxxQtData { pub fn parse_cxx_qt_item(&mut self, item: Item) -> Result> { match item { Item::Impl(imp) => self.parse_impl(imp), - Item::Use(_) => { - // Any use statements go into the CXX-Qt generated block - self.uses.push(item); - Ok(None) - } Item::ForeignMod(foreign_mod) => self.parse_foreign_mod(foreign_mod), _ => Ok(Some(item)), } @@ -501,18 +516,6 @@ mod tests { assert_eq!(cxx_qt_data.qobjects[&qobject_ident()].others.len(), 1); } - #[test] - fn test_find_and_merge_cxx_qt_item_uses() { - let mut cxx_qt_data = create_parsed_cxx_qt_data(); - - let item: Item = parse_quote! { - use std::collections::HashMap; - }; - let result = cxx_qt_data.parse_cxx_qt_item(item).unwrap(); - assert!(result.is_none()); - assert_eq!(cxx_qt_data.uses.len(), 1); - } - #[test] fn test_find_and_merge_cxx_qt_item_passthrough() { let mut cxx_qt_data = create_parsed_cxx_qt_data(); @@ -549,9 +552,18 @@ mod tests { } }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert!(cxx_qt_data.cxx_mappings.cxx_names.is_empty()); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); } #[test] @@ -565,10 +577,19 @@ mod tests { } }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 1); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.get("A").unwrap(), "B"); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); } #[test] @@ -582,10 +603,19 @@ mod tests { } }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 1); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.get("A").unwrap(), "B"); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); } #[test] @@ -601,7 +631,7 @@ mod tests { } }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "bridge_namespace") + .populate_mappings_from_item(&item, "bridge_namespace", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 1); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.get("B").unwrap(), "C"); @@ -615,6 +645,22 @@ mod tests { cxx_qt_data.cxx_mappings.namespaces.get("B").unwrap(), "bridge_namespace" ); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 2); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("B")) + .unwrap(), + &parse_quote! { ffi::B } + ); } #[test] @@ -632,7 +678,7 @@ mod tests { }; // Also ensure item namespace is chosen instead of bridge namespace assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "namespace") + .populate_mappings_from_item(&item, "namespace", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 0); @@ -645,6 +691,22 @@ mod tests { cxx_qt_data.cxx_mappings.namespaces.get("B").unwrap(), "type_namespace" ); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 2); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("B")) + .unwrap(), + &parse_quote! { ffi::B } + ); } #[test] @@ -663,7 +725,7 @@ mod tests { } }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 2); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.get("A").unwrap(), "B"); @@ -678,6 +740,22 @@ mod tests { cxx_qt_data.cxx_mappings.namespaces.get("C").unwrap(), "extern_namespace" ); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 2); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::A } + ); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("C")) + .unwrap(), + &parse_quote! { ffi::C } + ); } #[test] @@ -693,7 +771,7 @@ mod tests { }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 1); assert_eq!( @@ -706,6 +784,15 @@ mod tests { cxx_qt_data.cxx_mappings.namespaces.get("EnumA").unwrap(), "enum_namespace" ); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("EnumA")) + .unwrap(), + &parse_quote! { ffi::EnumA } + ); } #[test] @@ -721,7 +808,7 @@ mod tests { }; assert!(cxx_qt_data - .populate_cxx_mappings_from_item(&item, "") + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) .is_ok()); assert_eq!(cxx_qt_data.cxx_mappings.cxx_names.len(), 1); assert_eq!( @@ -734,6 +821,40 @@ mod tests { cxx_qt_data.cxx_mappings.namespaces.get("StructA").unwrap(), "struct_namespace" ); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("StructA")) + .unwrap(), + &parse_quote! { ffi::StructA } + ); + } + + #[test] + fn test_cxx_mappings_rust_name_normal() { + let mut cxx_qt_data = create_parsed_cxx_qt_data(); + + let item: Item = parse_quote! { + extern "C++" { + #[rust_name = "B"] + type A; + } + }; + assert!(cxx_qt_data + .populate_mappings_from_item(&item, "", &format_ident!("ffi")) + .is_ok()); + assert!(cxx_qt_data.cxx_mappings.cxx_names.is_empty()); + + assert_eq!(cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + cxx_qt_data + .qualified_mappings + .get(&format_ident!("A")) + .unwrap(), + &parse_quote! { ffi::B } + ); } #[test] diff --git a/crates/cxx-qt-gen/src/parser/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 270338142..7fbd1b398 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -14,7 +14,9 @@ pub mod signals; use crate::syntax::attribute::{attribute_find_path, attribute_tokens_to_map, AttributeDefault}; use cxxqtdata::ParsedCxxQtData; -use syn::{spanned::Spanned, token::Brace, Error, Ident, ItemMod, LitStr, Result}; +use syn::{ + spanned::Spanned, token::Brace, Error, Ident, ItemMod, LitStr, Path, PathSegment, Result, +}; /// A struct representing a module block with CXX-Qt relevant [syn::Item]'s /// parsed into ParsedCxxQtData, to be used later to generate Rust & C++ code. @@ -77,7 +79,11 @@ impl Parser { // qobject. Otherwise return them to be added to other if let Some(other) = cxx_qt_data.parse_cxx_qt_item(item)? { // Load any CXX name mappings - cxx_qt_data.populate_cxx_mappings_from_item(&other, &bridge_namespace)?; + cxx_qt_data.populate_mappings_from_item( + &other, + &bridge_namespace, + &module.ident, + )?; // Unknown item so add to the other list others.push(other); @@ -86,12 +92,23 @@ impl Parser { } else { // Load any CXX name mappings for item in &items.1 { - cxx_qt_data.populate_cxx_mappings_from_item(item, &bridge_namespace)?; + cxx_qt_data.populate_mappings_from_item( + item, + &bridge_namespace, + &module.ident, + )?; } // No qobjects found so pass everything through others.extend(items.1); } + + // Add all the QObject types to the qualified mappings + for ident in cxx_qt_data.qobjects.keys() { + let mut path = Path::from(module.ident.clone()); + path.segments.push(PathSegment::from(ident.clone())); + cxx_qt_data.qualified_mappings.insert(ident.clone(), path); + } } // Create a new module using only items that are not CXX-Qt items @@ -110,6 +127,7 @@ impl Parser { mod tests { use super::*; + use quote::format_ident; use syn::{parse_quote, ItemMod, Type}; /// Helper which returns a f64 as a [syn::Type] @@ -180,6 +198,15 @@ mod tests { assert_eq!(parser.passthrough_module.content.unwrap().1.len(), 0); assert_eq!(parser.cxx_qt_data.namespace, "cxx_qt"); assert_eq!(parser.cxx_qt_data.qobjects.len(), 1); + assert_eq!(parser.cxx_qt_data.qualified_mappings.len(), 1); + assert_eq!( + parser + .cxx_qt_data + .qualified_mappings + .get(&format_ident!("MyObject")) + .unwrap(), + &parse_quote! { ffi::MyObject } + ); } #[test] diff --git a/crates/cxx-qt-gen/src/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 194e4f100..9586d9e8d 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -3,70 +3,12 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::generator::rust::{qobject::GeneratedRustQObject, GeneratedRustBlocks}; +use crate::generator::rust::GeneratedRustBlocks; use proc_macro2::TokenStream; -use quote::{format_ident, quote, ToTokens}; - -/// Return common blocks for CXX bridge which the C++ writer adds as well -fn cxx_bridge_common_blocks(qobject: &GeneratedRustQObject) -> Vec { - let cpp_struct_ident = &qobject.cpp_struct_ident; - let rust_struct_ident = &qobject.rust_struct_ident; - - vec![ - quote! { - unsafe extern "C++" { - #[cxx_name = "unsafeRust"] - #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &#cpp_struct_ident) -> &#rust_struct_ident; - } - }, - quote! { - unsafe extern "C++" { - #[cxx_name = "unsafeRustMut"] - #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut #cpp_struct_ident>) -> Pin<&mut #rust_struct_ident>; - } - }, - ] -} - -/// Return common blocks for CXX-Qt implementation which the C++ writer adds as well -fn cxx_qt_common_blocks(qobject: &GeneratedRustQObject) -> Vec { - let cpp_struct_ident = &qobject.cpp_struct_ident; - let rust_struct_ident = &qobject.rust_struct_ident; - - vec![ - quote! { - impl core::ops::Deref for #cpp_struct_ident { - type Target = #rust_struct_ident; - - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } - }, - quote! { - impl cxx_qt::CxxQtType for #cpp_struct_ident { - type Rust = #rust_struct_ident; - - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } - } - }, - ] -} +use quote::{quote, ToTokens}; /// For a given GeneratedRustBlocks write this into a Rust TokenStream pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { - // Build the module idents - let cxx_mod_ident = &generated.cxx_mod.ident; - let cxx_qt_mod_ident = format_ident!("cxx_qt_{cxx_mod_ident}"); - // Retrieve the module contents and namespace let mut cxx_mod = generated.cxx_mod.clone(); let mut cxx_mod_contents = generated.cxx_mod_contents.clone(); @@ -98,38 +40,10 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { .expect("Could not build CXX common block"), ); - let mut qobject_types = vec![]; for qobject in &generated.qobjects { - // Add the common blocks into the bridge which we need - cxx_mod_contents.extend_from_slice(&qobject.blocks.cxx_mod_contents); - cxx_mod_contents.append( - &mut cxx_bridge_common_blocks(qobject) - .into_iter() - .map(|block| syn::parse2(block).expect("Could not build CXX common block")) - .collect(), - ); - - // Inject the common blocks into the implementation we need - cxx_qt_mod_contents.extend_from_slice(&qobject.blocks.cxx_qt_mod_contents); - cxx_qt_mod_contents.append( - &mut cxx_qt_common_blocks(qobject) - .into_iter() - .map(|block| syn::parse2(block).expect("Could not build CXX-Qt common block")) - .collect(), - ); - - // Add the type alias to the C++ struct - let cpp_struct_ident = &qobject.cpp_struct_ident; - let cpp_struct_ident_str = cpp_struct_ident.to_string(); - qobject_types.push(quote! { - #[doc = "The C++ type for the QObject "] - #[doc = #cpp_struct_ident_str] - #[doc = "\n"] - #[doc = "Use this type when referring to the QObject as a pointer"] - #[doc = "\n"] - #[doc = "See the book for more information: "] - pub type #cpp_struct_ident = super::#cpp_struct_ident; - }) + // Add the blocks from the QObject + cxx_mod_contents.extend_from_slice(&qobject.cxx_mod_contents); + cxx_qt_mod_contents.extend_from_slice(&qobject.cxx_qt_mod_contents); } // Inject the CXX blocks @@ -139,28 +53,11 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { cxx_mod.content = Some((syn::token::Brace::default(), cxx_mod_contents)); } - // Copy the visiblity of the module so we re-export things in the same way - let cxx_mod_visiblity = &generated.cxx_mod.vis; - quote! { #[cxx::bridge(namespace = #namespace)] #cxx_mod - #cxx_mod_visiblity use self::#cxx_qt_mod_ident::*; - // TODO: for now mark as public - // as we need to reach the generated getters and setters - // but later we'll likely implement things outside the module - // - /// Internal CXX-Qt module, made public temporarily between API changes - pub mod #cxx_qt_mod_ident { - use super::#cxx_mod_ident::*; - use cxx_qt::CxxQtType; - - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - - #(#cxx_qt_mod_contents)* - } + #(#cxx_qt_mod_contents)* } .into_token_stream() } @@ -169,9 +66,8 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { mod tests { use super::*; - use crate::generator::rust::qobject::{GeneratedRustQObject, GeneratedRustQObjectBlocks}; + use crate::generator::rust::qobject::GeneratedRustQObject; use pretty_assertions::assert_str_eq; - use quote::format_ident; use syn::parse_quote; /// Helper to create a GeneratedRustBlocks for testing @@ -190,36 +86,31 @@ mod tests { }], namespace: "cxx_qt::my_object".to_owned(), qobjects: vec![GeneratedRustQObject { - cpp_struct_ident: format_ident!("MyObject"), - namespace_internals: "cxx_qt::my_object::cxx_qt_my_object".to_owned(), - rust_struct_ident: format_ident!("MyObjectRust"), - blocks: GeneratedRustQObjectBlocks { - cxx_mod_contents: vec![ - parse_quote! { - unsafe extern "C++" { - type MyObject; - } - }, - parse_quote! { - extern "Rust" { - type MyObjectRust; - } - }, - ], - cxx_qt_mod_contents: vec![ - parse_quote! { - #[derive(Default)] - pub struct MyObjectRust; - }, - parse_quote! { - impl MyObjectRust { - fn rust_method(&self) { + cxx_mod_contents: vec![ + parse_quote! { + unsafe extern "C++" { + type MyObject; + } + }, + parse_quote! { + extern "Rust" { + type MyObjectRust; + } + }, + ], + cxx_qt_mod_contents: vec![ + parse_quote! { + #[derive(Default)] + pub struct MyObjectRust; + }, + parse_quote! { + impl MyObjectRust { + fn rust_method(&self) { - } } - }, - ], - }, + } + }, + ], }], } } @@ -241,68 +132,58 @@ mod tests { namespace: "cxx_qt".to_owned(), qobjects: vec![ GeneratedRustQObject { - cpp_struct_ident: format_ident!("FirstObject"), - namespace_internals: "cxx_qt::cxx_qt_first_object".to_owned(), - rust_struct_ident: format_ident!("FirstObjectRust"), - blocks: GeneratedRustQObjectBlocks { - cxx_mod_contents: vec![ - parse_quote! { - unsafe extern "C++" { - type FirstObject; - } - }, - parse_quote! { - extern "Rust" { - type FirstObjectRust; - } - }, - ], - cxx_qt_mod_contents: vec![ - parse_quote! { - #[derive(Default)] - pub struct FirstObjectRust; - }, - parse_quote! { - impl FirstObjectRust { - fn rust_method(&self) { - - } + cxx_mod_contents: vec![ + parse_quote! { + unsafe extern "C++" { + type FirstObject; + } + }, + parse_quote! { + extern "Rust" { + type FirstObjectRust; + } + }, + ], + cxx_qt_mod_contents: vec![ + parse_quote! { + #[derive(Default)] + pub struct FirstObjectRust; + }, + parse_quote! { + impl FirstObjectRust { + fn rust_method(&self) { + } - }, - ], - }, + } + }, + ], }, GeneratedRustQObject { - cpp_struct_ident: format_ident!("SecondObject"), - namespace_internals: "cxx_qt::cxx_qt_second_object".to_owned(), - rust_struct_ident: format_ident!("SecondObjectRust"), - blocks: GeneratedRustQObjectBlocks { - cxx_mod_contents: vec![ - parse_quote! { - unsafe extern "C++" { - type SecondObject; - } - }, - parse_quote! { - extern "Rust" { - type SecondObjectRust; - } - }, - ], - cxx_qt_mod_contents: vec![ - parse_quote! { - #[derive(Default)] - pub struct SecondObjectRust; - }, - parse_quote! { - impl SecondObjectRust { - fn rust_method(&self) { - - } + cxx_mod_contents: vec![ + parse_quote! { + unsafe extern "C++" { + type SecondObject; + } + }, + parse_quote! { + extern "Rust" { + type SecondObjectRust; + } + }, + ], + cxx_qt_mod_contents: vec![ + parse_quote! { + #[derive(Default)] + pub struct SecondObjectRust; + }, + parse_quote! { + impl SecondObjectRust { + fn rust_method(&self) { + } - }, - ], - }, + } + }, + ], }, ], } @@ -340,56 +221,16 @@ mod tests { extern "Rust" { type MyObjectRust; } - - unsafe extern "C++" { - #[cxx_name = "unsafeRust"] - #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &MyObject) -> &MyObjectRust; - } - - unsafe extern "C++" { - #[cxx_name = "unsafeRustMut"] - #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; - } } - use self::cxx_qt_ffi::*; - #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] - pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; - - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; + use module::Struct; - use module::Struct; + #[derive(Default)] + pub struct MyObjectRust; - #[derive(Default)] - pub struct MyObjectRust; + impl MyObjectRust { + fn rust_method(&self) { - impl MyObjectRust { - fn rust_method(&self) { - - } - } - - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } - - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } } } } @@ -430,17 +271,6 @@ mod tests { type FirstObjectRust; } - unsafe extern "C++" { - #[cxx_name = "unsafeRust"] - #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &FirstObject) -> &FirstObjectRust; - } - - unsafe extern "C++" { - #[cxx_name = "unsafeRustMut"] - #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut FirstObject>) -> Pin<&mut FirstObjectRust>; - } unsafe extern "C++" { type SecondObject; } @@ -448,83 +278,25 @@ mod tests { extern "Rust" { type SecondObjectRust; } - - unsafe extern "C++" { - #[cxx_name = "unsafeRust"] - #[doc(hidden)] - fn cxx_qt_ffi_rust(self: &SecondObject) -> &SecondObjectRust; - } - - unsafe extern "C++" { - #[cxx_name = "unsafeRustMut"] - #[doc(hidden)] - fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObject>) -> Pin<&mut SecondObjectRust>; - } } - use self::cxx_qt_ffi::*; - #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] - pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; - - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - - use module::Struct; - - #[derive(Default)] - pub struct FirstObjectRust; - - impl FirstObjectRust { - fn rust_method(&self) { + use module::Struct; - } - } - - impl core::ops::Deref for FirstObject { - type Target = FirstObjectRust; + #[derive(Default)] + pub struct FirstObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } + impl FirstObjectRust { + fn rust_method(&self) { - impl cxx_qt::CxxQtType for FirstObject { - type Rust = FirstObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } - } - - #[derive(Default)] - pub struct SecondObjectRust; - - impl SecondObjectRust { - fn rust_method(&self) { - - } } + } - impl core::ops::Deref for SecondObject { - type Target = SecondObjectRust; + #[derive(Default)] + pub struct SecondObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } + impl SecondObjectRust { + fn rust_method(&self) { - impl cxx_qt::CxxQtType for SecondObject { - type Rust = SecondObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } } } } diff --git a/crates/cxx-qt-gen/test_inputs/invokables.rs b/crates/cxx-qt-gen/test_inputs/invokables.rs index eb274c479..a445362ed 100644 --- a/crates/cxx-qt-gen/test_inputs/invokables.rs +++ b/crates/cxx-qt-gen/test_inputs/invokables.rs @@ -6,6 +6,8 @@ mod ffi { type QColor = cxx_qt_lib::QColor; include!("cxx-qt-lib/qpoint.h"); type QPoint = cxx_qt_lib::QPoint; + include!(); + type QObject; } unsafe extern "RustQt" { diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 75f2a8fbc..fa5e5a156 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -70,32 +70,23 @@ mod inheritance { fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } -use self::cxx_qt_inheritance::*; -#[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] -pub mod cxx_qt_inheritance { - use super::inheritance::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - impl cxx_qt::Locking for MyObject {} - #[doc(hidden)] - pub fn create_rs_my_object_rust() -> std::boxed::Box { - std::boxed::Box::new(core::default::Default::default()) +impl cxx_qt::Locking for inheritance::MyObject {} +#[doc(hidden)] +pub fn create_rs_my_object_rust() -> std::boxed::Box { + std::boxed::Box::new(core::default::Default::default()) +} +impl core::ops::Deref for inheritance::MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() } - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } +} +impl cxx_qt::CxxQtType for inheritance::MyObject { + type Rust = MyObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() } - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } } diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index f0b7c0c52..ca8125c49 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -6,6 +6,8 @@ mod ffi { type QColor = cxx_qt_lib::QColor; include!("cxx-qt-lib/qpoint.h"); type QPoint = cxx_qt_lib::QPoint; + include ! (< QtCore / QObject >); + type QObject; } unsafe extern "C++" { include ! (< QtCore / QObject >); @@ -170,105 +172,99 @@ mod ffi { fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } -use self::cxx_qt_ffi::*; -#[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] -pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; +impl cxx_qt::Threading for ffi::MyObject { + type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; + type ThreadingTypeId = cxx::type_id!("cxx_qt::my_object::MyObjectCxxQtThread"); + fn qt_thread(&self) -> ffi::MyObjectCxxQtThread { + self.cxx_qt_ffi_qt_thread() + } #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - impl cxx_qt::Threading for MyObject { - type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; - type ThreadingTypeId = cxx::type_id!("cxx_qt::my_object::MyObjectCxxQtThread"); - fn qt_thread(&self) -> MyObjectCxxQtThread { - self.cxx_qt_ffi_qt_thread() - } - #[doc(hidden)] - fn queue( - cxx_qt_thread: &MyObjectCxxQtThread, - f: F, - ) -> std::result::Result<(), cxx::Exception> - where - F: FnOnce(core::pin::Pin<&mut MyObject>), - F: Send + 'static, - { - #[allow(clippy::boxed_local)] - #[doc(hidden)] - fn func( - obj: core::pin::Pin<&mut MyObject>, - arg: std::boxed::Box, - ) { - (arg.inner)(obj) - } - let arg = MyObjectCxxQtThreadQueuedFn { - inner: std::boxed::Box::new(f), - }; - cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) - } + fn queue( + cxx_qt_thread: &ffi::MyObjectCxxQtThread, + f: F, + ) -> std::result::Result<(), cxx::Exception> + where + F: FnOnce(core::pin::Pin<&mut ffi::MyObject>), + F: Send + 'static, + { + #[allow(clippy::boxed_local)] #[doc(hidden)] - fn threading_clone(cxx_qt_thread: &MyObjectCxxQtThread) -> MyObjectCxxQtThread { - cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) - } - #[doc(hidden)] - fn threading_drop(cxx_qt_thread: &mut MyObjectCxxQtThread) { - cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread); + fn func( + obj: core::pin::Pin<&mut ffi::MyObject>, + arg: std::boxed::Box, + ) { + (arg.inner)(obj) } + let arg = MyObjectCxxQtThreadQueuedFn { + inner: std::boxed::Box::new(f), + }; + ffi::cxx_qt_ffi_my_object_queue_boxed_fn(cxx_qt_thread, func, std::boxed::Box::new(arg)) } #[doc(hidden)] - pub struct MyObjectCxxQtThreadQueuedFn { - inner: std::boxed::Box) + Send>, + fn threading_clone(cxx_qt_thread: &ffi::MyObjectCxxQtThread) -> ffi::MyObjectCxxQtThread { + ffi::cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) } - impl cxx_qt::Locking for MyObject {} #[doc(hidden)] - pub fn route_arguments_my_object_0( - arg0: i32, - arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObject0 { - #[allow(unused_variables)] - #[allow(clippy::let_unit_value)] - let (new_arguments, base_arguments, initialize_arguments) = - >::route_arguments((arg0, arg1)); - CxxQtConstructorArgumentsMyObject0 { - base: CxxQtConstructorBaseArgumentsMyObject0 { - arg0: base_arguments.0, - }, - initialize: CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, - new: CxxQtConstructorNewArgumentsMyObject0 { - arg0: new_arguments.0, - }, - } + fn threading_drop(cxx_qt_thread: &mut ffi::MyObjectCxxQtThread) { + ffi::cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread); } - #[doc(hidden)] +} +#[doc(hidden)] +pub struct MyObjectCxxQtThreadQueuedFn { + inner: std::boxed::Box) + Send>, +} +impl cxx_qt::Locking for ffi::MyObject {} +#[doc(hidden)] +pub fn route_arguments_my_object_0( + arg0: i32, + arg1: *mut ffi::QObject, +) -> ffi::CxxQtConstructorArgumentsMyObject0 { #[allow(unused_variables)] - pub fn new_rs_my_object_0( - new_arguments: CxxQtConstructorNewArgumentsMyObject0, - ) -> std::boxed::Box { - std::boxed::Box::new(>::new( - (new_arguments.arg0,), - )) + #[allow(clippy::let_unit_value)] + let (new_arguments, base_arguments, initialize_arguments) = + >::route_arguments(( + arg0, arg1, + )); + ffi::CxxQtConstructorArgumentsMyObject0 { + base: ffi::CxxQtConstructorBaseArgumentsMyObject0 { + arg0: base_arguments.0, + }, + initialize: ffi::CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, + new: ffi::CxxQtConstructorNewArgumentsMyObject0 { + arg0: new_arguments.0, + }, } - #[doc(hidden)] - #[allow(unused_variables)] - pub fn initialize_my_object_0( - qobject: core::pin::Pin<&mut MyObject>, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0, - ) { - >::initialize(qobject, ()); - } - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } +} +#[doc(hidden)] +#[allow(unused_variables)] +pub fn new_rs_my_object_0( + new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject0, +) -> std::boxed::Box { + std::boxed::Box::new(>::new((new_arguments.arg0,))) +} +#[doc(hidden)] +#[allow(unused_variables)] +pub fn initialize_my_object_0( + qobject: core::pin::Pin<&mut ffi::MyObject>, + initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject0, +) { + >::initialize(qobject, ()); +} +impl core::ops::Deref for ffi::MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() } - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } +} +impl cxx_qt::CxxQtType for ffi::MyObject { + type Rust = MyObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() + } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } } diff --git a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs index 588ee27d0..d5ba286bd 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -41,6 +41,7 @@ pub mod ffi { x: A, y: B, } + use super::MyTrait; unsafe extern "C++" { include ! (< QtCore / QStringListModel >); } @@ -208,145 +209,136 @@ pub mod ffi { fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObject>) -> Pin<&mut SecondObjectRust>; } } -pub use self::cxx_qt_ffi::*; -#[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] -pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - use super::MyTrait; - type MyObjectRust = super::MyObjectRust; - impl MyObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "property_name"] - pub fn property_name(&self) -> &i32 { - &self.property_name - } +impl ffi::MyObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "property_name"] + pub fn property_name(&self) -> &i32 { + &self.property_name } - impl MyObject { - #[doc = "Setter for the Q_PROPERTY "] - #[doc = "property_name"] - pub fn set_property_name(mut self: core::pin::Pin<&mut Self>, value: i32) { - if self.property_name == value { - return; - } - self.as_mut().rust_mut().property_name = value; - self.as_mut().property_name_changed(); +} +impl ffi::MyObject { + #[doc = "Setter for the Q_PROPERTY "] + #[doc = "property_name"] + pub fn set_property_name(mut self: core::pin::Pin<&mut Self>, value: i32) { + use cxx_qt::CxxQtType; + if self.property_name == value { + return; } + self.as_mut().rust_mut().property_name = value; + self.as_mut().property_name_changed(); } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "propertyNameChanged"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_property_name_changed( - self: core::pin::Pin<&mut MyObject>, - func: fn(core::pin::Pin<&mut MyObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "propertyNameChanged"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_property_name_changed( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn(core::pin::Pin<&mut ffi::MyObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "ready"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_ready( - self: core::pin::Pin<&mut MyObject>, - func: fn(core::pin::Pin<&mut MyObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "ready"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_ready( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn(core::pin::Pin<&mut ffi::MyObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl cxx_qt::Locking for MyObject {} - #[doc(hidden)] - pub fn create_rs_my_object_rust() -> std::boxed::Box { - std::boxed::Box::new(core::default::Default::default()) +} +impl cxx_qt::Locking for ffi::MyObject {} +#[doc(hidden)] +pub fn create_rs_my_object_rust() -> std::boxed::Box { + std::boxed::Box::new(core::default::Default::default()) +} +impl core::ops::Deref for ffi::MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() } - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } +} +impl cxx_qt::CxxQtType for ffi::MyObject { + type Rust = MyObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() } - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } - type SecondObjectRust = super::SecondObjectRust; - impl SecondObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "property_name"] - pub fn property_name(&self) -> &i32 { - &self.property_name - } +} +impl ffi::SecondObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "property_name"] + pub fn property_name(&self) -> &i32 { + &self.property_name } - impl SecondObject { - #[doc = "Setter for the Q_PROPERTY "] - #[doc = "property_name"] - pub fn set_property_name(mut self: core::pin::Pin<&mut Self>, value: i32) { - if self.property_name == value { - return; - } - self.as_mut().rust_mut().property_name = value; - self.as_mut().property_name_changed(); +} +impl ffi::SecondObject { + #[doc = "Setter for the Q_PROPERTY "] + #[doc = "property_name"] + pub fn set_property_name(mut self: core::pin::Pin<&mut Self>, value: i32) { + use cxx_qt::CxxQtType; + if self.property_name == value { + return; } + self.as_mut().rust_mut().property_name = value; + self.as_mut().property_name_changed(); } - impl SecondObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "propertyNameChanged"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_property_name_changed( - self: core::pin::Pin<&mut SecondObject>, - func: fn(core::pin::Pin<&mut SecondObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::SecondObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "propertyNameChanged"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_property_name_changed( + self: core::pin::Pin<&mut ffi::SecondObject>, + func: fn(core::pin::Pin<&mut ffi::SecondObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl SecondObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "ready"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_ready( - self: core::pin::Pin<&mut SecondObject>, - func: fn(core::pin::Pin<&mut SecondObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::SecondObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "ready"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_ready( + self: core::pin::Pin<&mut ffi::SecondObject>, + func: fn(core::pin::Pin<&mut ffi::SecondObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) } - #[doc(hidden)] - pub fn create_rs_second_object_rust() -> std::boxed::Box { - std::boxed::Box::new(core::default::Default::default()) +} +#[doc(hidden)] +pub fn create_rs_second_object_rust() -> std::boxed::Box { + std::boxed::Box::new(core::default::Default::default()) +} +impl core::ops::Deref for ffi::SecondObject { + type Target = SecondObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() } - impl core::ops::Deref for SecondObject { - type Target = SecondObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } +} +impl cxx_qt::CxxQtType for ffi::SecondObject { + type Rust = SecondObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() } - impl cxx_qt::CxxQtType for SecondObject { - type Rust = SecondObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 17f47e321..674e174f4 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -99,96 +99,89 @@ mod ffi { fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } -use self::cxx_qt_ffi::*; -#[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] -pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - impl MyObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "primitive"] - pub fn primitive(&self) -> &i32 { - &self.primitive - } +impl ffi::MyObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "primitive"] + pub fn primitive(&self) -> &i32 { + &self.primitive } - impl MyObject { - #[doc = "Setter for the Q_PROPERTY "] - #[doc = "primitive"] - pub fn set_primitive(mut self: core::pin::Pin<&mut Self>, value: i32) { - if self.primitive == value { - return; - } - self.as_mut().rust_mut().primitive = value; - self.as_mut().primitive_changed(); +} +impl ffi::MyObject { + #[doc = "Setter for the Q_PROPERTY "] + #[doc = "primitive"] + pub fn set_primitive(mut self: core::pin::Pin<&mut Self>, value: i32) { + use cxx_qt::CxxQtType; + if self.primitive == value { + return; } + self.as_mut().rust_mut().primitive = value; + self.as_mut().primitive_changed(); } - impl MyObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "trivial"] - pub fn trivial(&self) -> &QPoint { - &self.trivial - } +} +impl ffi::MyObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "trivial"] + pub fn trivial(&self) -> &ffi::QPoint { + &self.trivial } - impl MyObject { - #[doc = "Setter for the Q_PROPERTY "] - #[doc = "trivial"] - pub fn set_trivial(mut self: core::pin::Pin<&mut Self>, value: QPoint) { - if self.trivial == value { - return; - } - self.as_mut().rust_mut().trivial = value; - self.as_mut().trivial_changed(); +} +impl ffi::MyObject { + #[doc = "Setter for the Q_PROPERTY "] + #[doc = "trivial"] + pub fn set_trivial(mut self: core::pin::Pin<&mut Self>, value: ffi::QPoint) { + use cxx_qt::CxxQtType; + if self.trivial == value { + return; } + self.as_mut().rust_mut().trivial = value; + self.as_mut().trivial_changed(); } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "primitiveChanged"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_primitive_changed( - self: core::pin::Pin<&mut MyObject>, - func: fn(core::pin::Pin<&mut MyObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_primitive_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "primitiveChanged"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_primitive_changed( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn(core::pin::Pin<&mut ffi::MyObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_primitive_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "trivialChanged"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_trivial_changed( - self: core::pin::Pin<&mut MyObject>, - func: fn(core::pin::Pin<&mut MyObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_trivial_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "trivialChanged"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_trivial_changed( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn(core::pin::Pin<&mut ffi::MyObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_trivial_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl cxx_qt::Locking for MyObject {} - #[doc(hidden)] - pub fn create_rs_my_object_rust() -> std::boxed::Box { - std::boxed::Box::new(core::default::Default::default()) +} +impl cxx_qt::Locking for ffi::MyObject {} +#[doc(hidden)] +pub fn create_rs_my_object_rust() -> std::boxed::Box { + std::boxed::Box::new(core::default::Default::default()) +} +impl core::ops::Deref for ffi::MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() } - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } +} +impl cxx_qt::CxxQtType for ffi::MyObject { + type Rust = MyObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() } - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } } diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 3b3d10af3..1a57d2f11 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -126,86 +126,77 @@ mod ffi { fn cxx_qt_ffi_rust_mut(self: Pin<&mut MyObject>) -> Pin<&mut MyObjectRust>; } } -use self::cxx_qt_ffi::*; -#[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] -pub mod cxx_qt_ffi { - use super::ffi::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "ready"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_ready( - self: core::pin::Pin<&mut MyObject>, - func: fn(core::pin::Pin<&mut MyObject>), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) - } - } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "dataChanged"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_data_changed( - self: core::pin::Pin<&mut MyObject>, - func: fn( - core::pin::Pin<&mut MyObject>, - first: i32, - second: cxx::UniquePtr, - third: QPoint, - fourth: &'a QPoint, - ), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_data_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) - } +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "ready"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_ready( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn(core::pin::Pin<&mut ffi::MyObject>), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) } - impl MyObject { - #[doc = "Connect the given function pointer to the signal "] - #[doc = "newData"] - #[doc = ", so that when the signal is emitted the function pointer is executed."] - #[doc = "\n"] - #[doc = "Note that this method uses a AutoConnection connection type."] - #[must_use] - pub fn on_base_class_new_data( - self: core::pin::Pin<&mut MyObject>, - func: fn( - core::pin::Pin<&mut MyObject>, - first: i32, - second: cxx::UniquePtr, - third: QPoint, - fourth: &'a QPoint, - ), - ) -> cxx_qt_lib::QMetaObjectConnection { - self.connect_base_class_new_data(func, cxx_qt_lib::ConnectionType::AutoConnection) - } - } - impl cxx_qt::Locking for MyObject {} - #[doc(hidden)] - pub fn create_rs_my_object_rust() -> std::boxed::Box { - std::boxed::Box::new(core::default::Default::default()) - } - impl core::ops::Deref for MyObject { - type Target = MyObjectRust; - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } - impl cxx_qt::CxxQtType for MyObject { - type Rust = MyObjectRust; - fn rust(&self) -> &Self::Rust { - self.cxx_qt_ffi_rust() - } - fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { - self.cxx_qt_ffi_rust_mut() - } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "dataChanged"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_data_changed( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn( + core::pin::Pin<&mut ffi::MyObject>, + first: i32, + second: cxx::UniquePtr, + third: ffi::QPoint, + fourth: &'a ffi::QPoint, + ), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_data_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) + } +} +impl ffi::MyObject { + #[doc = "Connect the given function pointer to the signal "] + #[doc = "newData"] + #[doc = ", so that when the signal is emitted the function pointer is executed."] + #[doc = "\n"] + #[doc = "Note that this method uses a AutoConnection connection type."] + #[must_use] + pub fn on_base_class_new_data( + self: core::pin::Pin<&mut ffi::MyObject>, + func: fn( + core::pin::Pin<&mut ffi::MyObject>, + first: i32, + second: cxx::UniquePtr, + third: ffi::QPoint, + fourth: &'a ffi::QPoint, + ), + ) -> cxx_qt_lib::QMetaObjectConnection { + self.connect_base_class_new_data(func, cxx_qt_lib::ConnectionType::AutoConnection) + } +} +impl cxx_qt::Locking for ffi::MyObject {} +#[doc(hidden)] +pub fn create_rs_my_object_rust() -> std::boxed::Box { + std::boxed::Box::new(core::default::Default::default()) +} +impl core::ops::Deref for ffi::MyObject { + type Target = MyObjectRust; + fn deref(&self) -> &Self::Target { + self.cxx_qt_ffi_rust() + } +} +impl cxx_qt::CxxQtType for ffi::MyObject { + type Rust = MyObjectRust; + fn rust(&self) -> &Self::Rust { + self.cxx_qt_ffi_rust() + } + fn rust_mut(self: core::pin::Pin<&mut Self>) -> core::pin::Pin<&mut Self::Rust> { + self.cxx_qt_ffi_rust_mut() } }