From 1d7a1b50aa13659ad250cb48f7c946b1df2296fe Mon Sep 17 00:00:00 2001 From: Leon Matthes Date: Sat, 15 Jul 2023 11:54:21 +0200 Subject: [PATCH] cxx_qt::Constructor: Add tests --- crates/.gitignore | 6 + .../src/generator/cpp/constructor.rs | 311 ++++++++++++- .../cxx-qt-gen/src/generator/cpp/fragment.rs | 1 + .../src/generator/naming/qobject.rs | 21 +- .../src/generator/rust/constructor.rs | 431 ++++++++++++++++-- crates/cxx-qt-gen/src/parser/constructor.rs | 123 ++++- .../cxx-qt-gen/test_outputs/inheritance.cpp | 2 +- crates/cxx-qt-gen/test_outputs/inheritance.rs | 4 +- crates/cxx-qt-gen/test_outputs/invokables.cpp | 14 +- crates/cxx-qt-gen/test_outputs/invokables.h | 2 +- crates/cxx-qt-gen/test_outputs/invokables.rs | 58 +-- .../test_outputs/passthrough_and_naming.cpp | 5 +- .../test_outputs/passthrough_and_naming.rs | 8 +- crates/cxx-qt-gen/test_outputs/properties.cpp | 2 +- crates/cxx-qt-gen/test_outputs/properties.rs | 4 +- crates/cxx-qt-gen/test_outputs/signals.cpp | 2 +- crates/cxx-qt-gen/test_outputs/signals.rs | 4 +- 17 files changed, 858 insertions(+), 140 deletions(-) create mode 100644 crates/.gitignore diff --git a/crates/.gitignore b/crates/.gitignore new file mode 100644 index 000000000..f24372702 --- /dev/null +++ b/crates/.gitignore @@ -0,0 +1,6 @@ +# SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company +# SPDX-FileContributor: Leon Matthes +# +# SPDX-License-Identifier: MIT OR Apache-2.0 + +.lspconfig.lua diff --git a/crates/cxx-qt-gen/src/generator/cpp/constructor.rs b/crates/cxx-qt-gen/src/generator/cpp/constructor.rs index 79a2c614c..4006b0d77 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/constructor.rs @@ -27,10 +27,8 @@ fn default_constructor( r#" {class_name}::{class_name}(QObject* parent) : {base_class}(parent) - , m_rustObj({namespace_internals}::createRs()) - {initializers} - {{ - }} + , m_rustObj(::{namespace_internals}::createRs()){initializers} + {{ }} "#, class_name = qobject.ident, base_class = qobject.base_class, @@ -60,15 +58,15 @@ fn expand_arguments(arguments: &[Type], cxx_mappings: &ParsedCxxMappings) -> Res pub fn generate( qobject: &GeneratedCppQObject, - constructors: &Vec, + constructors: &[Constructor], member_initializers: &[String], cxx_mappings: &ParsedCxxMappings, ) -> Result { let initializers = member_initializers .iter() - .map(|initializer| format!(", {initializer}")) + .map(|initializer| format!("\n , {initializer}")) .collect::>() - .join("\n"); + .join(""); if constructors.is_empty() { return Ok(default_constructor(qobject, initializers)); @@ -88,17 +86,17 @@ pub fn generate( source: formatdoc! { r#" {class_name}::{class_name}({argument_list}) - : {class_name}({namespace_internals}::routeArguments{index}({move_arguments})) - {{ }} + : {class_name}(::{namespace_internals}::routeArguments{index}({move_arguments})) + {{ }} "#, - move_arguments = constructor_argument_names.iter().map(|arg| format!("std::move({arg})")).collect::>().join(", "), + move_arguments = constructor_argument_names.iter().map(|arg| format!("::std::move({arg})")).collect::>().join(", "), }, }); - let base_args = if let Some(base_args) = &constructor.base_arguments { - argument_names(base_args) + let base_args = if !constructor.base_arguments.is_empty() { + argument_names(&constructor.base_arguments) .into_iter() - .map(|arg| format!("std::move(args.baseArguments.{arg})")) + .map(|arg| format!("::std::move(args.base.{arg})")) .collect::>() .join(", ") } else { @@ -113,17 +111,16 @@ pub fn generate( // can use it. generated.private_methods.push(CppFragment::Pair { header: format!( - "explicit {class_name}({namespace_internals}::CxxQtConstructorArguments{index}&& args);" + "explicit {class_name}(::{namespace_internals}::CxxQtConstructorArguments{index}&& args);" ), source: formatdoc! { r#" - {class_name}::{class_name}({namespace_internals}::CxxQtConstructorArguments{index}&& args) - : {base_class}({base_args}) - , m_rustObj({namespace_internals}::newRs{index}(std::move(args.newArguments))) - {initializers} - {{ - {namespace_internals}::initialize{index}(*this, std::move(args.initializeArguments)); - }} + {class_name}::{class_name}(::{namespace_internals}::CxxQtConstructorArguments{index}&& args) + : {base_class}({base_args}) + , m_rustObj(::{namespace_internals}::newRs{index}(::std::move(args.new_))){initializers} + {{ + ::{namespace_internals}::initialize{index}(*this, ::std::move(args.initialize)); + }} "#, }, }) @@ -131,3 +128,275 @@ pub fn generate( Ok(generated) } + +#[cfg(test)] +mod tests { + use super::*; + + use std::assert_eq; + use syn::parse_quote; + + fn qobject_for_testing() -> GeneratedCppQObject { + GeneratedCppQObject { + ident: "MyObject".to_string(), + rust_ident: "MyObjectQt".to_string(), + namespace_internals: "rust".to_string(), + base_class: "BaseClass".to_string(), + blocks: GeneratedCppQObjectBlocks::default(), + locking: true, + } + } + + fn mock_constructor() -> Constructor { + Constructor { + arguments: vec![], + base_arguments: vec![], + new_arguments: vec![], + initialize_arguments: vec![], + imp: parse_quote! { impl X {} }, + } + } + + fn assert_empty_blocks(blocks: &GeneratedCppQObjectBlocks) { + assert!(blocks.members.is_empty()); + assert!(blocks.metaobjects.is_empty()); + assert!(blocks.forward_declares.is_empty()); + assert!(blocks.deconstructors.is_empty()); + } + + #[test] + fn default_constructor_with_initializers() { + let blocks = generate( + &qobject_for_testing(), + &[], + &["member1(1)".to_string(), "member2{ 2 }".to_string()], + &ParsedCxxMappings::default(), + ) + .unwrap(); + + assert_empty_blocks(&blocks); + assert!(blocks.private_methods.is_empty()); + assert_eq!( + blocks.methods, + vec![CppFragment::Pair { + header: "explicit MyObject(QObject* parent = nullptr);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(QObject* parent) + : BaseClass(parent) + , m_rustObj(::rust::createRs()) + , member1(1) + , member2{{ 2 }} + {{ }} + " + ), + }] + ); + } + #[test] + fn default_constructor_without_initializers() { + let blocks = generate( + &qobject_for_testing(), + &[], + &[], + &ParsedCxxMappings::default(), + ) + .unwrap(); + + assert_empty_blocks(&blocks); + assert!(blocks.private_methods.is_empty()); + assert_eq!( + blocks.methods, + vec![CppFragment::Pair { + header: "explicit MyObject(QObject* parent = nullptr);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(QObject* parent) + : BaseClass(parent) + , m_rustObj(::rust::createRs()) + {{ }} + " + ), + }] + ); + } + + #[test] + fn constructor_without_base_arguments() { + let blocks = generate( + &qobject_for_testing(), + &[Constructor { + arguments: vec![parse_quote! { i32 }, parse_quote! { *mut QObject }], + ..mock_constructor() + }], + &[], + &ParsedCxxMappings::default(), + ) + .unwrap(); + + assert_empty_blocks(&blocks); + assert_eq!( + blocks.private_methods, + vec![CppFragment::Pair { + header: "explicit MyObject(::rust::CxxQtConstructorArguments0&& args);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(::rust::CxxQtConstructorArguments0&& args) + : BaseClass() + , m_rustObj(::rust::newRs0(::std::move(args.new_))) + {{ + ::rust::initialize0(*this, ::std::move(args.initialize)); + }} + " + ), + }] + ); + assert_eq!( + blocks.methods, + vec![CppFragment::Pair { + header: "explicit MyObject(::std::int32_t arg0, QObject* arg1);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(::std::int32_t arg0, QObject* arg1) + : MyObject(::rust::routeArguments0(::std::move(arg0), ::std::move(arg1))) + {{ }} + " + ), + }] + ); + } + + #[test] + fn constructor_with_all_arguments() { + let blocks = generate( + &qobject_for_testing(), + &[Constructor { + arguments: vec![parse_quote! { i8 }, parse_quote! { i16 }], + new_arguments: vec![parse_quote! { i16}, parse_quote! { i32 }], + initialize_arguments: vec![parse_quote! { i32 }, parse_quote! { i64 }], + base_arguments: vec![parse_quote! { i64 }, parse_quote! { *mut QObject }], + ..mock_constructor() + }], + &["initializer".to_string()], + &ParsedCxxMappings::default(), + ) + .unwrap(); + + assert_empty_blocks(&blocks); + assert_eq!( + blocks.methods, + vec![CppFragment::Pair { + header: "explicit MyObject(::std::int8_t arg0, ::std::int16_t arg1);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(::std::int8_t arg0, ::std::int16_t arg1) + : MyObject(::rust::routeArguments0(::std::move(arg0), ::std::move(arg1))) + {{ }} + " + ) + }] + ); + assert_eq!( + blocks.private_methods, + vec![CppFragment::Pair { + header: "explicit MyObject(::rust::CxxQtConstructorArguments0&& args);".to_string(), + source: formatdoc!( + " + MyObject::MyObject(::rust::CxxQtConstructorArguments0&& args) + : BaseClass(::std::move(args.base.arg0), ::std::move(args.base.arg1)) + , m_rustObj(::rust::newRs0(::std::move(args.new_))) + , initializer + {{ + ::rust::initialize0(*this, ::std::move(args.initialize)); + }} + " + ) + }] + ); + } + + #[test] + fn multiple_constructors() { + let blocks = generate( + &qobject_for_testing(), + &[ + Constructor { + arguments: vec![], + ..mock_constructor() + }, + Constructor { + arguments: vec![parse_quote! { *mut QObject }], + base_arguments: vec![parse_quote! { *mut QObject }], + ..mock_constructor() + }, + ], + &["initializer".to_string()], + &ParsedCxxMappings::default(), + ) + .unwrap(); + + assert_empty_blocks(&blocks); + assert_eq!(blocks.methods.len(), 2); + assert_eq!( + blocks.methods, + vec![ + CppFragment::Pair { + header: "explicit MyObject();".to_string(), + source: formatdoc!( + " + MyObject::MyObject() + : MyObject(::rust::routeArguments0()) + {{ }} + " + ), + }, + CppFragment::Pair { + header: "explicit MyObject(QObject* arg0);".to_string(), + source: formatdoc! { + " + MyObject::MyObject(QObject* arg0) + : MyObject(::rust::routeArguments1(::std::move(arg0))) + {{ }} + " + } + } + ] + ); + assert_eq!(blocks.private_methods.len(), 2); + assert_eq!( + blocks.private_methods, + vec![ + CppFragment::Pair { + header: "explicit MyObject(::rust::CxxQtConstructorArguments0&& args);" + .to_string(), + source: formatdoc!( + " + MyObject::MyObject(::rust::CxxQtConstructorArguments0&& args) + : BaseClass() + , m_rustObj(::rust::newRs0(::std::move(args.new_))) + , initializer + {{ + ::rust::initialize0(*this, ::std::move(args.initialize)); + }} + " + ) + }, + CppFragment::Pair { + header: "explicit MyObject(::rust::CxxQtConstructorArguments1&& args);" + .to_string(), + source: formatdoc!( + " + MyObject::MyObject(::rust::CxxQtConstructorArguments1&& args) + : BaseClass(::std::move(args.base.arg0)) + , m_rustObj(::rust::newRs1(::std::move(args.new_))) + , initializer + {{ + ::rust::initialize1(*this, ::std::move(args.initialize)); + }} + " + ) + } + ] + ); + } +} diff --git a/crates/cxx-qt-gen/src/generator/cpp/fragment.rs b/crates/cxx-qt-gen/src/generator/cpp/fragment.rs index 3847fd45e..b62bf3b6b 100644 --- a/crates/cxx-qt-gen/src/generator/cpp/fragment.rs +++ b/crates/cxx-qt-gen/src/generator/cpp/fragment.rs @@ -3,6 +3,7 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +#[derive(PartialEq, Eq, Debug)] pub enum CppFragment { Pair { header: String, source: String }, Header(String), diff --git a/crates/cxx-qt-gen/src/generator/naming/qobject.rs b/crates/cxx-qt-gen/src/generator/naming/qobject.rs index c6792cca4..58af2d02e 100644 --- a/crates/cxx-qt-gen/src/generator/naming/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/naming/qobject.rs @@ -24,19 +24,24 @@ pub struct QObjectName { impl From<&ParsedQObject> for QObjectName { fn from(qobject: &ParsedQObject) -> Self { - let ident_left = &qobject.qobject_ty.ident_left; + Self::from_idents( + qobject.qobject_ty.ident_left.clone(), + qobject.qobject_ty.ident_right.clone(), + ) + } +} + +impl QObjectName { + pub fn from_idents(ident_left: Ident, ident_right: Ident) -> Self { Self { - ident: ident_left.clone(), - // TODO: later we may support cxx_name or rust_name so keep these are CombinedIdents for now cpp_class: CombinedIdent::from_ident(ident_left.clone()), - rust_struct: CombinedIdent::from_ident(qobject.qobject_ty.ident_right.clone()), - cxx_qt_thread_class: cxx_qt_thread_class_from_ident(ident_left), - cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(ident_left), + rust_struct: CombinedIdent::from_ident(ident_right), + cxx_qt_thread_class: cxx_qt_thread_class_from_ident(&ident_left), + cxx_qt_thread_queued_fn_struct: cxx_qt_thread_queued_fn_struct_from_ident(&ident_left), + ident: ident_left, } } -} -impl QObjectName { /// For a given ident generate the mangled threading suffix ident pub fn cxx_qt_thread_method(&self, suffix: &str) -> Ident { format_ident!( diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index 92dac3351..1b0297f64 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -22,16 +22,11 @@ const BASE_ARGUMENTS: &str = "CxxQtConstructorBaseArguments"; const NEW_ARGUMENTS: &str = "CxxQtConstructorNewArguments"; const INITIALIZE_ARGUMENTS: &str = "CxxQtConstructorInitializeArguments"; -fn map_types TokenStream>( - args: &Option>, - f: F, -) -> Vec { - args.as_ref() - .map(|args| args.iter().enumerate().map(f).collect()) - .unwrap_or_default() +fn map_types TokenStream>(args: &[Type], f: F) -> Vec { + args.iter().enumerate().map(f).collect() } -fn extract_arguments_from_tuple(args: &Option>, tuple_name: Ident) -> Vec { +fn extract_arguments_from_tuple(args: &[Type], tuple_name: Ident) -> Vec { map_types(args, |(index, _ty)| { let arg_name = format_ident!("arg{index}"); let index = syn::LitInt::new(index.to_string().as_str(), Span::call_site()); @@ -41,7 +36,7 @@ fn extract_arguments_from_tuple(args: &Option>, tuple_name: Ident) -> }) } -fn extract_arguments_from_struct(args: &Option>, struct_name: Ident) -> Vec { +fn extract_arguments_from_struct(args: &[Type], struct_name: Ident) -> Vec { map_types(args, |(index, _ty)| { let arg_name = format_ident!("arg{index}"); quote! { @@ -50,7 +45,7 @@ fn extract_arguments_from_struct(args: &Option>, struct_name: Ident) - }) } -fn argument_members(args: &Option>) -> Vec { +fn argument_members(args: &[Type]) -> Vec { map_types(args, |(index, ty)| { let arg_name = format_ident!("arg{index}"); quote! { @@ -64,6 +59,7 @@ fn generate_default_constructor( namespace: &NamespaceName, ) -> GeneratedRustQObjectBlocks { let rust_struct_ident = &qobject_idents.rust_struct.rust; + let create_rs_ident = format_ident!( "create_rs_{object_name}", object_name = rust_struct_ident.to_string().to_case(Case::Snake) @@ -79,9 +75,12 @@ fn generate_default_constructor( } }], cxx_qt_mod_contents: vec![parse_quote! { - /// Generated CXX-Qt method which creates a boxed rust struct of a QObject + #[doc(hidden)] pub fn #create_rs_ident() -> std::boxed::Box<#rust_struct_ident> { - core::default::Default::default() + // Wrapping the call to Default::default in a Box::new call leads + // to a nicer error message, as it's not trying to infer trait bounds + // on Box, but directly on the given type. + std::boxed::Box::new(core::default::Default::default()) } }], } @@ -90,13 +89,13 @@ fn generate_default_constructor( fn generate_arguments_struct( namespace_internals: &str, struct_name: &CombinedIdent, - argument_list: &Option>, + argument_list: &[Type], ) -> Item { let argument_members = argument_members(argument_list); - let not_empty = if argument_list.as_ref().is_some_and(|list| !list.is_empty()) { - None - } else { + let not_empty = if argument_list.is_empty() { Some(quote! { not_empty: i8 }) + } else { + None }; let rust_name = &struct_name.rust; // use to_string here, as the cxx_name needs to be in quotes for the attribute macro. @@ -116,14 +115,13 @@ fn generate_arguments_struct( fn generate_arguments_initialization( struct_name: &Ident, instance_name: Ident, - argument_list: &Option>, + argument_list: &[Type], ) -> Expr { let init_arguments = extract_arguments_from_tuple(argument_list, instance_name); - println!("init_arguments: {:?}", init_arguments); - let not_empty = if argument_list.as_ref().is_some_and(|list| !list.is_empty()) { - None - } else { + let not_empty = if argument_list.is_empty() { Some(quote! { not_empty: 0 }) + } else { + None }; parse_quote! { @@ -145,34 +143,32 @@ pub fn generate( let mut result = GeneratedRustQObjectBlocks::default(); let namespace_internals = &namespace.internal; - let rust_struct_name_rust = &qobject_idents.rust_struct.rust; - let rust_struct_name_snake = &qobject_idents - .rust_struct - .rust - .to_string() - .to_case(Case::Snake); + + let qobject_name = &qobject_idents.cpp_class.cpp; let qobject_name_rust = &qobject_idents.cpp_class.rust; + let qobject_name_snake = qobject_name.to_string().to_case(Case::Snake); + + let rust_struct_name_rust = &qobject_idents.rust_struct.rust; for (index, constructor) in constructors.iter().enumerate() { - let arguments_rust = format_ident!("{CONSTRUCTOR_ARGUMENTS}{rust_struct_name_rust}{index}"); - let base_arguments_rust = format_ident!("{BASE_ARGUMENTS}{rust_struct_name_rust}{index}"); - let new_arguments_rust = format_ident!("{NEW_ARGUMENTS}{rust_struct_name_rust}{index}"); + let arguments_rust = format_ident!("{CONSTRUCTOR_ARGUMENTS}{qobject_name}{index}"); + let base_arguments_rust = format_ident!("{BASE_ARGUMENTS}{qobject_name}{index}"); + let new_arguments_rust = format_ident!("{NEW_ARGUMENTS}{qobject_name}{index}"); let initialize_arguments_rust = - format_ident!("{INITIALIZE_ARGUMENTS}{rust_struct_name_rust}{index}"); + format_ident!("{INITIALIZE_ARGUMENTS}{qobject_name}{index}"); let arguments_cxx = format!("{CONSTRUCTOR_ARGUMENTS}{index}"); let base_arguments_cxx = format_ident!("{BASE_ARGUMENTS}{index}"); let new_arguments_cxx = format_ident!("{NEW_ARGUMENTS}{index}"); let initialize_arguments_cxx = format_ident!("{INITIALIZE_ARGUMENTS}{index}"); - let new_rust = format_ident!("new_rs_{rust_struct_name_snake}_{index}"); + let new_rust = format_ident!("new_rs_{qobject_name_snake}_{index}"); let new_cxx = format!("newRs{index}"); - let initialize_rust = format_ident!("initialize_{rust_struct_name_snake}_{index}"); + let initialize_rust = format_ident!("initialize_{qobject_name_snake}_{index}"); let initialize_cxx = format!("initialize{index}"); - let route_arguments_rust = - format_ident!("route_arguments_{rust_struct_name_snake}_{index}"); + let route_arguments_rust = format_ident!("route_arguments_{qobject_name_snake}_{index}"); let route_arguemnts_cxx = format!("routeArguments{index}"); let argument_types = &constructor.arguments; @@ -238,9 +234,11 @@ pub fn generate( #[cxx_name = #arguments_cxx] #[doc(hidden)] struct #arguments_rust { - baseArguments: #base_arguments_rust, - newArguments: #new_arguments_rust, - initializeArguments: #initialize_arguments_rust, + base: #base_arguments_rust, + // new a keyword in C++, so we use `new_` here + #[cxx_name = "new_"] + new: #new_arguments_rust, + initialize: #initialize_arguments_rust, } }, generate_arguments_struct(&namespace.internal, &CombinedIdent { @@ -259,7 +257,7 @@ pub fn generate( extern "Rust" { #[namespace = #namespace_internals] #[cxx_name = #route_arguemnts_cxx] - // This function needs to marked unsafe, as some arguments may be pointers. + // This function may need to be marked unsafe, as some arguments may be pointers. #route_arguments_safety fn #route_arguments_rust(#(#route_arguments_parameters),*) -> #arguments_rust; #[namespace = #namespace_internals] @@ -286,9 +284,9 @@ pub fn generate( ) = <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>> ::route_arguments((#(#assign_arguments,)*)); #arguments_rust { - baseArguments: #init_base_arguments, - initializeArguments: #init_initalize_arguments, - newArguments: #init_new_arguments, + base: #init_base_arguments, + initialize: #init_initalize_arguments, + new: #init_new_arguments, } } }, @@ -297,9 +295,7 @@ pub fn generate( #[doc(hidden)] #[allow(unused_variables)] pub fn #new_rust(new_arguments: #new_arguments_rust) -> std::boxed::Box<#rust_struct_name_rust> { - #[allow(clippy::let_unit_value)] - let new_arguments = (#(#extract_new_arguments,)*); - std::boxed::Box::new(<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::new(new_arguments)) + std::boxed::Box::new(<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::new((#(#extract_new_arguments,)*))) } }, parse_quote_spanned! { @@ -310,11 +306,350 @@ pub fn generate( qobject: core::pin::Pin<&mut #qobject_name_rust>, initialize_arguments: #initialize_arguments_rust ) { - #[allow(clippy::let_unit_value)] - let initialize_arguments = (#(#extract_initialize_arguments,)*); - <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize(qobject, initialize_arguments) + <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( + qobject, + (#(#extract_initialize_arguments,)*)); } }]) } Ok(result) } + +#[cfg(test)] +mod tests { + use super::*; + use crate::tests::assert_tokens_eq; + + fn mock_constructor() -> Constructor { + Constructor { + new_arguments: vec![], + base_arguments: vec![], + initialize_arguments: vec![], + arguments: vec![], + // dummy impl for testing + imp: parse_quote! {impl X {}}, + } + } + + fn mock_name() -> QObjectName { + QObjectName::from_idents(format_ident!("MyObject"), format_ident!("MyObjectRust")) + } + + fn mock_namespace() -> NamespaceName { + NamespaceName::from_pair_str("ffi", &format_ident!("MyObject")) + } + + fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObjectBlocks { + generate(constructors, &mock_name(), &mock_namespace()).unwrap() + } + + #[test] + fn default_constructor() { + let blocks = generate_mocked(&[]); + + assert_eq!(blocks.cxx_mod_contents.len(), 1); + assert_eq!(blocks.cxx_qt_mod_contents.len(), 1); + + assert_tokens_eq( + &blocks.cxx_mod_contents[0], + quote! { + extern "Rust" { + #[cxx_name="createRs"] + #[namespace="ffi::cxx_qt_my_object"] + fn create_rs_my_object_rust() -> Box; + } + }, + ); + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[0], + quote! { + #[doc(hidden)] + pub fn create_rs_my_object_rust() -> std::boxed::Box + { + std::boxed::Box::new(core::default::Default::default()) + } + }, + ); + } + + fn assert_empty_argument_struct( + tokens: &T, + rust_name: &str, + cxx_name: &str, + ) { + let rust_name = format_ident!("{rust_name}"); + assert_tokens_eq( + tokens, + quote! { + #[namespace = "ffi::cxx_qt_my_object"] + #[cxx_name = #cxx_name] + #[doc(hidden)] + struct #rust_name { + not_empty: i8 + } + }, + ); + } + + // 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, + namespace_attr: &TokenStream, + ) { + assert_tokens_eq( + &blocks.cxx_mod_contents[0], + quote! { + #namespace_attr + #[cxx_name = "CxxQtConstructorArguments0"] + #[doc(hidden)] + struct CxxQtConstructorArgumentsMyObject0 { + base: CxxQtConstructorBaseArgumentsMyObject0, + #[cxx_name="new_"] + new: CxxQtConstructorNewArgumentsMyObject0, + initialize : CxxQtConstructorInitializeArgumentsMyObject0, + } + }, + ); + + assert_empty_argument_struct( + &blocks.cxx_mod_contents[1], + "CxxQtConstructorBaseArgumentsMyObject0", + "CxxQtConstructorBaseArguments0", + ); + assert_empty_argument_struct( + &blocks.cxx_mod_contents[2], + "CxxQtConstructorNewArgumentsMyObject0", + "CxxQtConstructorNewArguments0", + ); + assert_empty_argument_struct( + &blocks.cxx_mod_contents[3], + "CxxQtConstructorInitializeArgumentsMyObject0", + "CxxQtConstructorInitializeArguments0", + ); + assert_tokens_eq( + &blocks.cxx_mod_contents[4], + quote! { + extern "Rust" { + #namespace_attr + #[cxx_name = "routeArguments0"] + fn route_arguments_my_object_0() -> CxxQtConstructorArgumentsMyObject0; + + #namespace_attr + #[cxx_name = "newRs0"] + fn new_rs_my_object_0(args: CxxQtConstructorNewArgumentsMyObject0) -> Box; + + #namespace_attr + #[cxx_name = "initialize0"] + fn initialize_my_object_0(qobject: Pin<&mut MyObject>, args: CxxQtConstructorInitializeArgumentsMyObject0); + } + }, + ); + + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[0], + quote! { + #[doc(hidden)] + pub fn route_arguments_my_object_0() -> 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 }, + } + } + }, + ); + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[1], + quote! { + #[doc(hidden)] + #[allow(unused_variables)] + pub fn new_rs_my_object_0(new_arguments: CxxQtConstructorNewArgumentsMyObject0) -> std::boxed::Box { + std::boxed::Box::new( + >::new(()) + ) + } + }, + ); + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[2], + quote! { + #[doc(hidden)] + #[allow(unused_variables)] + pub fn initialize_my_object_0( + qobject: core::pin::Pin<&mut MyObject>, + initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0) + { + >::initialize(qobject, ()); + } + }, + ); + } + + fn assert_full_constructor_blocks( + blocks: &GeneratedRustQObjectBlocks, + 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], + quote! { + #namespace_attr + #[cxx_name = "CxxQtConstructorArguments1"] + #[doc(hidden)] + struct CxxQtConstructorArgumentsMyObject1 { + base: CxxQtConstructorBaseArgumentsMyObject1, + #[cxx_name="new_"] + new: CxxQtConstructorNewArgumentsMyObject1, + initialize : CxxQtConstructorInitializeArgumentsMyObject1, + } + }, + ); + + assert_tokens_eq( + &blocks.cxx_mod_contents[6], + quote! { + #namespace_attr + #[cxx_name="CxxQtConstructorBaseArguments1"] + #[doc(hidden)] + struct CxxQtConstructorBaseArgumentsMyObject1 { + arg0: i64, + arg1: *mut QObject, + arg2: f32, + } + }, + ); + assert_tokens_eq( + &blocks.cxx_mod_contents[7], + quote! { + #namespace_attr + #[cxx_name="CxxQtConstructorNewArguments1"] + #[doc(hidden)] + struct CxxQtConstructorNewArgumentsMyObject1 { + arg0: i16, + } + }, + ); + assert_tokens_eq( + &blocks.cxx_mod_contents[8], + quote! { + #namespace_attr + #[cxx_name="CxxQtConstructorInitializeArguments1"] + #[doc(hidden)] + struct CxxQtConstructorInitializeArgumentsMyObject1 { + arg0: i32, + arg1: i64, + } + }, + ); + assert_tokens_eq( + &blocks.cxx_mod_contents[9], + quote! { + extern "Rust" { + #namespace_attr + #[cxx_name = "routeArguments1"] + unsafe fn route_arguments_my_object_1(arg0: *const QObject) -> CxxQtConstructorArgumentsMyObject1; + + #namespace_attr + #[cxx_name = "newRs1"] + fn new_rs_my_object_1(args: CxxQtConstructorNewArgumentsMyObject1) -> Box; + + #namespace_attr + #[cxx_name = "initialize1"] + fn initialize_my_object_1(qobject: Pin<&mut MyObject>, args: CxxQtConstructorInitializeArgumentsMyObject1); + } + }, + ); + + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[3], + quote! { + #[doc(hidden)] + pub fn route_arguments_my_object_1(arg0: *const QObject) -> CxxQtConstructorArgumentsMyObject1 + { + #[allow(unused_variables)] + #[allow(clippy::let_unit_value)] + let (new_arguments, base_arguments, initialize_arguments) = + >::route_arguments((arg0,)); + + CxxQtConstructorArgumentsMyObject1 { + base: CxxQtConstructorBaseArgumentsMyObject1 { + arg0: base_arguments.0, + arg1: base_arguments.1, + arg2: base_arguments.2, + }, + initialize: CxxQtConstructorInitializeArgumentsMyObject1 { + arg0: initialize_arguments.0, + arg1: initialize_arguments.1, + }, + new: CxxQtConstructorNewArgumentsMyObject1 { + arg0: new_arguments.0, + }, + } + } + }, + ); + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[4], + quote! { + #[doc(hidden)] + #[allow(unused_variables)] + pub fn new_rs_my_object_1(new_arguments: CxxQtConstructorNewArgumentsMyObject1) -> std::boxed::Box { + std::boxed::Box::new( + >::new( + (new_arguments.arg0,))) + } + }, + ); + assert_tokens_eq( + &blocks.cxx_qt_mod_contents[5], + quote! { + #[doc(hidden)] + #[allow(unused_variables)] + pub fn initialize_my_object_1( + qobject: core::pin::Pin<&mut MyObject>, + initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject1) + { + >::initialize( + qobject, + (initialize_arguments.arg0, initialize_arguments.arg1,)); + } + }, + ); + } + + #[test] + fn multiple_constructors() { + let blocks = generate_mocked(&[ + mock_constructor(), + Constructor { + arguments: vec![parse_quote! { *const QObject }], + new_arguments: vec![parse_quote! { i16 }], + initialize_arguments: vec![parse_quote! { i32 }, parse_quote! { i64 }], + base_arguments: vec![ + parse_quote! { i64 }, + parse_quote! { *mut QObject }, + parse_quote! { f32 }, + ], + ..mock_constructor() + }, + ]); + + assert_eq!(blocks.cxx_mod_contents.len(), 10); + assert_eq!(blocks.cxx_qt_mod_contents.len(), 6); + + let namespace_attr = quote! { + #[namespace = "ffi::cxx_qt_my_object"] + }; + + assert_empty_constructor_blocks(&blocks, &namespace_attr); + + assert_full_constructor_blocks(&blocks, &namespace_attr); + } +} diff --git a/crates/cxx-qt-gen/src/parser/constructor.rs b/crates/cxx-qt-gen/src/parser/constructor.rs index 7c9f92293..a7f22f559 100644 --- a/crates/cxx-qt-gen/src/parser/constructor.rs +++ b/crates/cxx-qt-gen/src/parser/constructor.rs @@ -26,12 +26,12 @@ pub struct Constructor { /// Arguments to the new function. /// The `new` function needs to return the inner Rust struct for the QObject. - pub new_arguments: Option>, + pub new_arguments: Vec, /// Arguments to be passed to the base class constructor. - pub base_arguments: Option>, + pub base_arguments: Vec, /// Arguments to the initialize function. /// The `initialize` function is run after the QObject is created. - pub initialize_arguments: Option>, + pub initialize_arguments: Vec, /// The original impl that this constructor was parse from. pub imp: ItemImpl, @@ -150,10 +150,121 @@ impl Constructor { let (argument_list, arguments) = Self::parse_arguments(trait_path)?; Ok(Constructor { arguments: argument_list, - new_arguments: arguments.new, - base_arguments: arguments.base, - initialize_arguments: arguments.initialize, + new_arguments: arguments.new.unwrap_or_default(), + base_arguments: arguments.base.unwrap_or_default(), + initialize_arguments: arguments.initialize.unwrap_or_default(), imp, }) } } + +#[cfg(test)] +mod tests { + use syn::parse_quote; + + use super::*; + + fn assert_parse_error(item: ItemImpl, message: &str) { + assert!( + Constructor::parse(item).is_err(), + "Constructor shouldn't have parsed because '{message}'." + ); + } + + #[test] + fn parse_invalid_constructors() { + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor for X {} + }, + "missing type arguments", + ); + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor for X {} + }, + "missing main argument list", + ); + + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor<()> for X { + fn some_impl() {} + } + }, + "item in impl block", + ); + + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor<()> for T {} + }, + "generics on impl block", + ); + // TODO This should be allowed at some point if the lifetime is actually used. + assert_parse_error( + parse_quote! { + impl<'a> cxx_qt::Constructor<()> for T {} + }, + "lifetime on impl block", + ); + + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor<(), UnknownArguments=()> for X {} + }, + "unknown named type argument", + ); + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor<(), NewArguments=(), NewArguments=()> for X {} + }, + "duplicate named type argument", + ); + + // Not a tuple, missing `,` + assert_parse_error( + parse_quote! { + impl cxx_qt::Constructor<(i32)> for X {} + }, + "type argument is not a tuple", + ); + } + + #[test] + fn parse_arguments_with_default_associated_types() { + let constructor = Constructor::parse(parse_quote! { + impl cxx_qt::Constructor<(i32, QString)> for X {} + }) + .unwrap(); + + assert_eq!( + constructor.arguments, + vec![parse_quote!(i32), parse_quote!(QString)] + ); + assert!(constructor.new_arguments.is_empty()); + assert!(constructor.base_arguments.is_empty()); + assert!(constructor.initialize_arguments.is_empty()); + } + + #[test] + fn parse_full_argument_list() { + let constructor = Constructor::parse(parse_quote! { + impl cxx_qt::Constructor< + (i32,), + NewArguments=(i8,QString), + InitializeArguments=(), + BaseArguments=(i64,) + > for X {} + }) + .unwrap(); + + assert_eq!(constructor.arguments, vec![parse_quote!(i32)]); + assert_eq!( + constructor.new_arguments, + vec![parse_quote!(i8), parse_quote!(QString)] + ); + assert!(constructor.initialize_arguments.is_empty()); + assert_eq!(constructor.base_arguments, vec![parse_quote!(i64)]); + } +} diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.cpp b/crates/cxx-qt-gen/test_outputs/inheritance.cpp index ca7e0f10a..fd128f285 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.cpp +++ b/crates/cxx-qt-gen/test_outputs/inheritance.cpp @@ -30,7 +30,7 @@ MyObject::hasChildren(QModelIndex const& _parent) const MyObject::MyObject(QObject* parent) : QAbstractItemModel(parent) - , m_rustObj(cxx_qt_my_object::createRs()) + , m_rustObj(::cxx_qt_my_object::createRs()) , m_rustObjMutex(::std::make_shared<::std::recursive_mutex>()) { } diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index d5ea6d28e..75f2a8fbc 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -79,9 +79,9 @@ pub mod cxx_qt_inheritance { type UniquePtr = cxx::UniquePtr; type MyObjectRust = super::MyObjectRust; impl cxx_qt::Locking for MyObject {} - #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] + #[doc(hidden)] pub fn create_rs_my_object_rust() -> std::boxed::Box { - core::default::Default::default() + std::boxed::Box::new(core::default::Default::default()) } impl core::ops::Deref for MyObject { type Target = MyObjectRust; diff --git a/crates/cxx-qt-gen/test_outputs/invokables.cpp b/crates/cxx-qt-gen/test_outputs/invokables.cpp index 8640cd2cd..f88f97d76 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.cpp +++ b/crates/cxx-qt-gen/test_outputs/invokables.cpp @@ -105,23 +105,23 @@ MyObject::qtThread() const MyObject::MyObject(::std::int32_t arg0, QObject* arg1) : MyObject( - cxx_qt::my_object::cxx_qt_my_object::routeArguments0(std::move(arg0), - std::move(arg1))) + ::cxx_qt::my_object::cxx_qt_my_object::routeArguments0(::std::move(arg0), + ::std::move(arg1))) { } MyObject::MyObject( - cxx_qt::my_object::cxx_qt_my_object::CxxQtConstructorArguments0&& args) - : QObject(std::move(args.baseArguments.arg0)) + ::cxx_qt::my_object::cxx_qt_my_object::CxxQtConstructorArguments0&& args) + : QObject(::std::move(args.base.arg0)) , m_rustObj( - cxx_qt::my_object::cxx_qt_my_object::newRs0(std::move(args.newArguments))) + ::cxx_qt::my_object::cxx_qt_my_object::newRs0(::std::move(args.new_))) , m_rustObjMutex(::std::make_shared<::std::recursive_mutex>()) , m_cxxQtThreadObj( ::std::make_shared<::rust::cxxqtlib1::CxxQtGuardedPointer>( this)) { - cxx_qt::my_object::cxx_qt_my_object::initialize0( - *this, std::move(args.initializeArguments)); + ::cxx_qt::my_object::cxx_qt_my_object::initialize0( + *this, ::std::move(args.initialize)); } } // namespace cxx_qt::my_object diff --git a/crates/cxx-qt-gen/test_outputs/invokables.h b/crates/cxx-qt-gen/test_outputs/invokables.h index 1bb9ccb83..d4cc9c92f 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.h +++ b/crates/cxx-qt-gen/test_outputs/invokables.h @@ -55,7 +55,7 @@ class MyObject : public QObject void invokableResultTupleWrapper() const; ::rust::String invokableResultTypeWrapper() const; explicit MyObject( - cxx_qt::my_object::cxx_qt_my_object::CxxQtConstructorArguments0&& args); + ::cxx_qt::my_object::cxx_qt_my_object::CxxQtConstructorArguments0&& args); private: ::rust::Box m_rustObj; diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index f5a6a1c99..f0b7c0c52 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -118,46 +118,45 @@ mod ffi { #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorArguments0"] #[doc(hidden)] - struct CxxQtConstructorArgumentsMyObjectRust0 { - baseArguments: CxxQtConstructorBaseArgumentsMyObjectRust0, - newArguments: CxxQtConstructorNewArgumentsMyObjectRust0, - initializeArguments: CxxQtConstructorInitializeArgumentsMyObjectRust0, + struct CxxQtConstructorArgumentsMyObject0 { + base: CxxQtConstructorBaseArgumentsMyObject0, + #[cxx_name = "new_"] + new: CxxQtConstructorNewArgumentsMyObject0, + initialize: CxxQtConstructorInitializeArgumentsMyObject0, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorBaseArguments0"] #[doc(hidden)] - struct CxxQtConstructorBaseArgumentsMyObjectRust0 { + struct CxxQtConstructorBaseArgumentsMyObject0 { arg0: *mut QObject, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorNewArguments0"] #[doc(hidden)] - struct CxxQtConstructorNewArgumentsMyObjectRust0 { + struct CxxQtConstructorNewArgumentsMyObject0 { arg0: i32, } #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "CxxQtConstructorInitializeArguments0"] #[doc(hidden)] - struct CxxQtConstructorInitializeArgumentsMyObjectRust0 { + struct CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: i8, } extern "Rust" { #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "routeArguments0"] - unsafe fn route_arguments_my_object_rust_0( + unsafe fn route_arguments_my_object_0( arg0: i32, arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObjectRust0; + ) -> CxxQtConstructorArgumentsMyObject0; #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "newRs0"] - fn new_rs_my_object_rust_0( - args: CxxQtConstructorNewArgumentsMyObjectRust0, - ) -> Box; + fn new_rs_my_object_0(args: CxxQtConstructorNewArgumentsMyObject0) -> Box; #[namespace = "cxx_qt::my_object::cxx_qt_my_object"] #[cxx_name = "initialize0"] - fn initialize_my_object_rust_0( + fn initialize_my_object_0( qobject: Pin<&mut MyObject>, - args: CxxQtConstructorInitializeArgumentsMyObjectRust0, + args: CxxQtConstructorInitializeArgumentsMyObject0, ); } unsafe extern "C++" { @@ -222,47 +221,40 @@ pub mod cxx_qt_ffi { } impl cxx_qt::Locking for MyObject {} #[doc(hidden)] - pub fn route_arguments_my_object_rust_0( + pub fn route_arguments_my_object_0( arg0: i32, arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObjectRust0 { + ) -> CxxQtConstructorArgumentsMyObject0 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = >::route_arguments((arg0, arg1)); - CxxQtConstructorArgumentsMyObjectRust0 { - baseArguments: CxxQtConstructorBaseArgumentsMyObjectRust0 { + CxxQtConstructorArgumentsMyObject0 { + base: CxxQtConstructorBaseArgumentsMyObject0 { arg0: base_arguments.0, }, - initializeArguments: CxxQtConstructorInitializeArgumentsMyObjectRust0 { not_empty: 0 }, - newArguments: CxxQtConstructorNewArgumentsMyObjectRust0 { + initialize: CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, + new: CxxQtConstructorNewArgumentsMyObject0 { arg0: new_arguments.0, }, } } #[doc(hidden)] #[allow(unused_variables)] - pub fn new_rs_my_object_rust_0( - new_arguments: CxxQtConstructorNewArgumentsMyObjectRust0, + pub fn new_rs_my_object_0( + new_arguments: CxxQtConstructorNewArgumentsMyObject0, ) -> std::boxed::Box { - #[allow(clippy::let_unit_value)] - let new_arguments = (new_arguments.arg0,); std::boxed::Box::new(>::new( - new_arguments, + (new_arguments.arg0,), )) } #[doc(hidden)] #[allow(unused_variables)] - pub fn initialize_my_object_rust_0( + pub fn initialize_my_object_0( qobject: core::pin::Pin<&mut MyObject>, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObjectRust0, + initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0, ) { - #[allow(clippy::let_unit_value)] - let initialize_arguments = (); - >::initialize( - qobject, - initialize_arguments, - ) + >::initialize(qobject, ()); } impl core::ops::Deref for MyObject { type Target = MyObjectRust; diff --git a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.cpp b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.cpp index 10e08382b..02515b394 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.cpp +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.cpp @@ -69,7 +69,7 @@ MyObject::readyConnect(::rust::Fn func, MyObject::MyObject(QObject* parent) : QStringListModel(parent) - , m_rustObj(cxx_qt::multi_object::cxx_qt_my_object::createRs()) + , m_rustObj(::cxx_qt::multi_object::cxx_qt_my_object::createRs()) , m_rustObjMutex(::std::make_shared<::std::recursive_mutex>()) { } @@ -139,8 +139,7 @@ SecondObject::readyConnect(::rust::Fn func, SecondObject::SecondObject(QObject* parent) : QObject(parent) - , m_rustObj(cxx_qt::multi_object::cxx_qt_second_object::createRs()) - + , m_rustObj(::cxx_qt::multi_object::cxx_qt_second_object::createRs()) { } 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 139cb0eb7..cd412478c 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -264,9 +264,9 @@ pub mod cxx_qt_ffi { } } impl cxx_qt::Locking for MyObject {} - #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] + #[doc(hidden)] pub fn create_rs_my_object_rust() -> std::boxed::Box { - core::default::Default::default() + std::boxed::Box::new(core::default::Default::default()) } impl core::ops::Deref for MyObject { type Target = MyObjectRust; @@ -330,9 +330,9 @@ pub mod cxx_qt_ffi { self.connect_ready(func, CxxQtConnectionType::AutoConnection) } } - #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] + #[doc(hidden)] pub fn create_rs_second_object_rust() -> std::boxed::Box { - core::default::Default::default() + std::boxed::Box::new(core::default::Default::default()) } impl core::ops::Deref for SecondObject { type Target = SecondObjectRust; diff --git a/crates/cxx-qt-gen/test_outputs/properties.cpp b/crates/cxx-qt-gen/test_outputs/properties.cpp index 96b411ef3..f30d1d71a 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.cpp +++ b/crates/cxx-qt-gen/test_outputs/properties.cpp @@ -76,7 +76,7 @@ MyObject::trivialChangedConnect(::rust::Fn func, MyObject::MyObject(QObject* parent) : QObject(parent) - , m_rustObj(cxx_qt::my_object::cxx_qt_my_object::createRs()) + , m_rustObj(::cxx_qt::my_object::cxx_qt_my_object::createRs()) , m_rustObjMutex(::std::make_shared<::std::recursive_mutex>()) { } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index e73842a18..3a7d4307e 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -172,9 +172,9 @@ pub mod cxx_qt_ffi { } } impl cxx_qt::Locking for MyObject {} - #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] + #[doc(hidden)] pub fn create_rs_my_object_rust() -> std::boxed::Box { - core::default::Default::default() + std::boxed::Box::new(core::default::Default::default()) } impl core::ops::Deref for MyObject { type Target = MyObjectRust; diff --git a/crates/cxx-qt-gen/test_outputs/signals.cpp b/crates/cxx-qt-gen/test_outputs/signals.cpp index ca664eca5..379b61997 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.cpp +++ b/crates/cxx-qt-gen/test_outputs/signals.cpp @@ -92,7 +92,7 @@ MyObject::newDataConnect(::rust::Fn()) { } diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index f3d499e89..4a3633041 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -189,9 +189,9 @@ pub mod cxx_qt_ffi { } } impl cxx_qt::Locking for MyObject {} - #[doc = r" Generated CXX-Qt method which creates a boxed rust struct of a QObject"] + #[doc(hidden)] pub fn create_rs_my_object_rust() -> std::boxed::Box { - core::default::Default::default() + std::boxed::Box::new(core::default::Default::default()) } impl core::ops::Deref for MyObject { type Target = MyObjectRust;