From c121ce5a43fa702568088d710fbb789b6f5fa487 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 14:22:21 +0100 Subject: [PATCH 01/11] cxx-qt-gen: move impl Deref and impl CxxQtType to generator phase This allows us later to be able to used qualified mappings. Related to #404 --- .../src/generator/rust/cxxqttype.rs | 142 +++++++++++++++ crates/cxx-qt-gen/src/generator/rust/mod.rs | 1 + .../cxx-qt-gen/src/generator/rust/qobject.rs | 31 +++- crates/cxx-qt-gen/src/writer/rust/mod.rs | 161 +----------------- 4 files changed, 173 insertions(+), 162 deletions(-) create mode 100644 crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs 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..ea96b3d90 --- /dev/null +++ b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs @@ -0,0 +1,142 @@ +// SPDX-FileCopyrightText: 2023 Klarälvdalens Datakonsult AB, a KDAB Group company +// SPDX-FileContributor: Andrew Hayzen +// +// SPDX-License-Identifier: MIT OR Apache-2.0 + +use crate::generator::{naming::qobject::QObjectName, rust::qobject::GeneratedRustQObjectBlocks}; +use quote::quote; +use syn::Result; + +use super::fragment::RustFragmentPair; + +pub fn generate(qobject_ident: &QObjectName) -> Result { + let mut blocks = GeneratedRustQObjectBlocks::default(); + + let cpp_struct_ident = &qobject_ident.cpp_class.rust; + let rust_struct_ident = &qobject_ident.rust_struct.rust; + + 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 #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() + } + } + }, + ], + }; + + 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).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/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index f212b85ab..00a3c98be 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; diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 488024510..5d504836f 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -7,8 +7,9 @@ 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, }, }, parser::qobject::ParsedQObject, @@ -140,6 +141,10 @@ impl GeneratedRustQObject { &namespace_idents, )?); + generated.blocks.append(&mut cxxqttype::generate( + &qobject_idents, + )?); + Ok(generated) } } @@ -268,7 +273,7 @@ mod tests { let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) .unwrap(); - assert_eq!(rust.blocks.cxx_mod_contents.len(), 4); + assert_eq!(rust.blocks.cxx_mod_contents.len(), 6); assert_tokens_eq( &rust.blocks.cxx_mod_contents[0], quote! { @@ -309,5 +314,25 @@ mod tests { } }, ); + assert_tokens_eq( + &rust.blocks.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.blocks.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/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 194e4f100..66270c8d8 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -3,64 +3,10 @@ // // 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() - } - } - }, - ] -} - /// For a given GeneratedRustBlocks write this into a Rust TokenStream pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { // Build the module idents @@ -100,23 +46,9 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { let mut qobject_types = vec![]; for qobject in &generated.qobjects { - // Add the common blocks into the bridge which we need + // Add the blocks from the QObject 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; @@ -340,18 +272,6 @@ 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::*; @@ -373,24 +293,6 @@ mod tests { } } - - 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() - } - } } } .into_token_stream() @@ -430,17 +332,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,18 +339,6 @@ 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::*; @@ -482,24 +361,6 @@ mod tests { } } - impl core::ops::Deref for FirstObject { - type Target = FirstObjectRust; - - fn deref(&self) -> &Self::Target { - self.cxx_qt_ffi_rust() - } - } - - 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; @@ -508,24 +369,6 @@ mod tests { } } - - impl core::ops::Deref for SecondObject { - type Target = SecondObjectRust; - - fn deref(&self) -> &Self::Target { - 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() - } - } } } .into_token_stream() From 1862e8eb83b31dd713b04e927674a4c6b3eeb167 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 12:27:57 +0100 Subject: [PATCH 02/11] cxx-qt-gen: parse types in the CXX bridge to generate qualified mappings Related to #404 --- crates/cxx-qt-gen/src/parser/cxxqtdata.rs | 176 +++++++++++++++++++--- crates/cxx-qt-gen/src/parser/mod.rs | 12 +- 2 files changed, 168 insertions(+), 20 deletions(-) diff --git a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index 6098db63f..78bddbc55 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. @@ -100,21 +105,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 +138,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 +150,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 +180,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(()) } @@ -549,9 +571,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 +596,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 +622,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 +650,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 +664,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 +697,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 +710,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 +744,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 +759,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 +790,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 +803,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 +827,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 +840,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..71f3b6c44 100644 --- a/crates/cxx-qt-gen/src/parser/mod.rs +++ b/crates/cxx-qt-gen/src/parser/mod.rs @@ -77,7 +77,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,7 +90,11 @@ 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 From fc62e5d00318f1f466b49bff85074319d72c034f Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 12:45:23 +0100 Subject: [PATCH 03/11] cxx-qt-gen: use qualified mappings in rust generation This means that we refer to MyObject as ffi::MyObject when it's a type. Related to #404 --- crates/cxx-qt-gen/src/generator/rust/mod.rs | 4 +- .../src/generator/rust/property/getter.rs | 6 +- .../src/generator/rust/property/mod.rs | 21 +++- .../src/generator/rust/property/setter.rs | 6 +- .../cxx-qt-gen/src/generator/rust/qobject.rs | 38 ++++-- .../cxx-qt-gen/src/generator/rust/signals.rs | 39 +++++-- crates/cxx-qt-gen/src/generator/utils/rust.rs | 110 +++++++++++++----- crates/cxx-qt-gen/src/parser/mod.rs | 21 +++- crates/cxx-qt-gen/src/writer/rust/mod.rs | 4 + crates/cxx-qt-gen/test_outputs/inheritance.rs | 1 + crates/cxx-qt-gen/test_outputs/invokables.rs | 1 + .../test_outputs/passthrough_and_naming.rs | 17 +-- crates/cxx-qt-gen/test_outputs/properties.rs | 13 ++- crates/cxx-qt-gen/test_outputs/signals.rs | 21 ++-- 14 files changed, 218 insertions(+), 84 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index 00a3c98be..0ba79308a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -43,7 +43,9 @@ impl GeneratedRustBlocks { .cxx_qt_data .qobjects .values() - .map(GeneratedRustQObject::from) + .map(|qobject| { + GeneratedRustQObject::from(qobject, &parser.cxx_qt_data.qualified_mappings) + }) .collect::>>()?, }) } 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..f8a2dcbf1 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/getter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/getter.rs @@ -9,19 +9,21 @@ use crate::generator::{ utils::rust::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); RustFragmentPair { cxx_bridge: vec![quote! { 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..42f0f22de 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs @@ -14,13 +14,15 @@ use crate::{ }, 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, + qualified_mappings: &BTreeMap, ) -> Result { let mut generated = GeneratedRustQObjectBlocks::default(); let mut signals = vec![]; @@ -29,7 +31,7 @@ pub fn generate_rust_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); 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..8b40983b8 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs @@ -9,12 +9,14 @@ use crate::generator::{ utils::rust::{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 +24,7 @@ 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); // Determine if unsafe is required due to an unsafe type let has_unsafe = if syn_type_is_cxx_bridge_unsafe(cxx_ty) { diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 5d504836f..b11fd40ca 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -3,6 +3,8 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::{ generator::{ naming::{namespace::NamespaceName, qobject::QObjectName}, @@ -15,7 +17,7 @@ use crate::{ parser::qobject::ParsedQObject, }; use quote::quote; -use syn::{parse_quote, Ident, ImplItem, Item, Result}; +use syn::{parse_quote, Ident, ImplItem, Item, Path, Result}; #[derive(Default)] pub struct GeneratedRustQObjectBlocks { @@ -45,7 +47,10 @@ pub struct GeneratedRustQObject { } impl GeneratedRustQObject { - pub fn from(qobject: &ParsedQObject) -> Result { + pub fn from( + qobject: &ParsedQObject, + qualified_mappings: &BTreeMap, + ) -> Result { // Create the base object let qobject_idents = QObjectName::from(qobject); let namespace_idents = NamespaceName::from(qobject); @@ -77,6 +82,7 @@ impl GeneratedRustQObject { generated.blocks.append(&mut generate_rust_properties( &qobject.properties, &qobject_idents, + qualified_mappings, )?); generated.blocks.append(&mut generate_rust_invokables( &qobject.invokables, @@ -93,6 +99,7 @@ impl GeneratedRustQObject { generated.blocks.append(&mut generate_rust_signals( &qobject.signals, &qobject_idents, + qualified_mappings, )?); // If this type is a singleton then we need to add an include @@ -141,9 +148,9 @@ impl GeneratedRustQObject { &namespace_idents, )?); - generated.blocks.append(&mut cxxqttype::generate( - &qobject_idents, - )?); + generated + .blocks + .append(&mut cxxqttype::generate(&qobject_idents)?); Ok(generated) } @@ -231,8 +238,11 @@ mod tests { }; let parser = Parser::from(module).unwrap(); - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); + let rust = GeneratedRustQObject::from( + parser.cxx_qt_data.qobjects.values().next().unwrap(), + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(rust.cpp_struct_ident, "MyObject"); assert_eq!(rust.namespace_internals, "cxx_qt_my_object"); assert_eq!(rust.rust_struct_ident, "MyObjectRust"); @@ -251,8 +261,11 @@ mod tests { }; let parser = Parser::from(module).unwrap(); - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); + let rust = GeneratedRustQObject::from( + parser.cxx_qt_data.qobjects.values().next().unwrap(), + &BTreeMap::::default(), + ) + .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"); @@ -271,8 +284,11 @@ mod tests { }; let parser = Parser::from(module).unwrap(); - let rust = GeneratedRustQObject::from(parser.cxx_qt_data.qobjects.values().next().unwrap()) - .unwrap(); + let rust = GeneratedRustQObject::from( + parser.cxx_qt_data.qobjects.values().next().unwrap(), + &BTreeMap::::default(), + ) + .unwrap(); assert_eq!(rust.blocks.cxx_mod_contents.len(), 6); assert_tokens_eq( &rust.blocks.cxx_mod_contents[0], diff --git a/crates/cxx-qt-gen/src/generator/rust/signals.rs b/crates/cxx-qt-gen/src/generator/rust/signals.rs index 7ff52ed25..8d0acedac 100644 --- a/crates/cxx-qt-gen/src/generator/rust/signals.rs +++ b/crates/cxx-qt-gen/src/generator/rust/signals.rs @@ -3,6 +3,8 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 +use std::collections::BTreeMap; + use crate::{ generator::{ naming::{qobject::QObjectName, signals::QSignalName}, @@ -12,11 +14,12 @@ use crate::{ 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, + qualified_mappings: &BTreeMap, ) -> Result { let mut generated = GeneratedRustQObjectBlocks::default(); let qobject_name = &qobject_idents.cpp_class.rust; @@ -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,8 @@ 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 mut unsafe_block = None; let mut unsafe_call = Some(quote! { unsafe }); @@ -143,7 +148,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 +227,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 +300,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 +370,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/utils/rust.rs b/crates/cxx-qt-gen/src/generator/utils/rust.rs index 80ff3014f..93ec9df64 100644 --- a/crates/cxx-qt-gen/src/generator/utils/rust.rs +++ b/crates/cxx-qt-gen/src/generator/utils/rust.rs @@ -3,28 +3,38 @@ // // 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 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 +46,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 +76,35 @@ 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() { + if let Some(qualified_path) = qualified_mappings.get(ident) { + ty_path.path = qualified_path.clone(); + } + } + 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 +141,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 +172,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 +183,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 +194,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 +205,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 +216,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 +253,24 @@ 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_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/mod.rs b/crates/cxx-qt-gen/src/parser/mod.rs index 71f3b6c44..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. @@ -100,6 +102,13 @@ impl Parser { // 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 @@ -118,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] @@ -188,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 66270c8d8..62960b1c4 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -85,6 +85,8 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { // /// Internal CXX-Qt module, made public temporarily between API changes pub mod #cxx_qt_mod_ident { + // Temporary hack so that qualified types still work, this will be removed in the next commit + use super::*; use super::#cxx_mod_ident::*; use cxx_qt::CxxQtType; @@ -277,6 +279,7 @@ mod tests { use self::cxx_qt_ffi::*; #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] pub mod cxx_qt_ffi { + use super::*; use super::ffi::*; use cxx_qt::CxxQtType; @@ -344,6 +347,7 @@ mod tests { use self::cxx_qt_ffi::*; #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] pub mod cxx_qt_ffi { + use super::*; use super::ffi::*; use cxx_qt::CxxQtType; diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 75f2a8fbc..0fe654d26 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -74,6 +74,7 @@ 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 super::*; use cxx_qt::CxxQtType; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index f0b7c0c52..a77a0284c 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -174,6 +174,7 @@ 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 super::*; use cxx_qt::CxxQtType; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; 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..f7f087d8a 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -212,6 +212,7 @@ 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 super::*; use cxx_qt::CxxQtType; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; @@ -243,8 +244,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } @@ -257,8 +258,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } @@ -310,8 +311,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } @@ -324,8 +325,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 17f47e321..24d13c5ca 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -103,6 +103,7 @@ 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 super::*; use cxx_qt::CxxQtType; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; @@ -128,14 +129,14 @@ pub mod cxx_qt_ffi { impl MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial"] - pub fn trivial(&self) -> &QPoint { + 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) { + pub fn set_trivial(mut self: core::pin::Pin<&mut Self>, value: ffi::QPoint) { if self.trivial == value { return; } @@ -151,8 +152,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } @@ -165,8 +166,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index 3b3d10af3..b01871d21 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -130,6 +130,7 @@ 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 super::*; use cxx_qt::CxxQtType; #[doc(hidden)] type UniquePtr = cxx::UniquePtr; @@ -142,8 +143,8 @@ pub mod cxx_qt_ffi { #[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>), + 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) } @@ -156,13 +157,13 @@ pub mod cxx_qt_ffi { #[doc = "Note that this method uses a AutoConnection connection type."] #[must_use] pub fn on_data_changed( - self: core::pin::Pin<&mut MyObject>, + self: core::pin::Pin<&mut ffi::MyObject>, func: fn( - core::pin::Pin<&mut MyObject>, + core::pin::Pin<&mut ffi::MyObject>, first: i32, second: cxx::UniquePtr, - third: QPoint, - fourth: &'a QPoint, + third: ffi::QPoint, + fourth: &'a ffi::QPoint, ), ) -> cxx_qt_lib::QMetaObjectConnection { self.connect_data_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) @@ -176,13 +177,13 @@ pub mod cxx_qt_ffi { #[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>, + self: core::pin::Pin<&mut ffi::MyObject>, func: fn( - core::pin::Pin<&mut MyObject>, + core::pin::Pin<&mut ffi::MyObject>, first: i32, second: cxx::UniquePtr, - third: QPoint, - fourth: &'a QPoint, + third: ffi::QPoint, + fourth: &'a ffi::QPoint, ), ) -> cxx_qt_lib::QMetaObjectConnection { self.connect_base_class_new_data(func, cxx_qt_lib::ConnectionType::AutoConnection) From 963eaca02c33f5bac5dcf0b823ebac772ecbe04b Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 13:47:14 +0100 Subject: [PATCH 04/11] cxx-qt-gen: use qualified mappings in impl T as well Related to #404 --- .../src/generator/rust/cxxqttype.rs | 22 +++++++++---- .../src/generator/rust/property/getter.rs | 6 ++-- .../src/generator/rust/property/setter.rs | 9 ++++-- .../cxx-qt-gen/src/generator/rust/qobject.rs | 16 +++++++--- .../cxx-qt-gen/src/generator/rust/signals.rs | 6 ++-- .../src/generator/rust/threading.rs | 23 ++++++++++---- crates/cxx-qt-gen/src/generator/utils/rust.rs | 31 +++++++++++++++++-- crates/cxx-qt-gen/test_outputs/inheritance.rs | 6 ++-- crates/cxx-qt-gen/test_outputs/invokables.rs | 14 ++++----- .../test_outputs/passthrough_and_naming.rs | 26 ++++++++-------- crates/cxx-qt-gen/test_outputs/properties.rs | 18 +++++------ crates/cxx-qt-gen/test_outputs/signals.rs | 12 +++---- 12 files changed, 125 insertions(+), 64 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs index ea96b3d90..3da02005f 100644 --- a/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs +++ b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs @@ -3,17 +3,27 @@ // // SPDX-License-Identifier: MIT OR Apache-2.0 -use crate::generator::{naming::qobject::QObjectName, rust::qobject::GeneratedRustQObjectBlocks}; +use std::collections::BTreeMap; + +use crate::generator::{ + naming::qobject::QObjectName, rust::qobject::GeneratedRustQObjectBlocks, + 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) -> Result { +pub fn generate( + qobject_ident: &QObjectName, + qualified_mappings: &BTreeMap, +) -> Result { let mut blocks = GeneratedRustQObjectBlocks::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![ @@ -34,7 +44,7 @@ pub fn generate(qobject_ident: &QObjectName) -> Result &Self::Target { @@ -43,7 +53,7 @@ pub fn generate(qobject_ident: &QObjectName) -> Result &Self::Rust { @@ -81,7 +91,7 @@ mod tests { let qobject = create_parsed_qobject(); let qobject_idents = QObjectName::from(&qobject); - let generated = generate(&qobject_idents).unwrap(); + 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); 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 f8a2dcbf1..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,7 +6,7 @@ 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 std::collections::BTreeMap; @@ -24,6 +24,8 @@ pub fn generate( let ident = &idents.name.rust; let ident_str = ident.to_string(); 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! { @@ -33,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/setter.rs b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs index 8b40983b8..5be0b8851 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs @@ -6,7 +6,10 @@ 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 std::collections::BTreeMap; @@ -25,6 +28,8 @@ pub fn generate( let ident_str = ident.to_string(); let notify_ident = &idents.notify.rust; 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) { @@ -41,7 +46,7 @@ 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) { diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index b11fd40ca..313f58dae 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -13,6 +13,7 @@ use crate::{ 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, }; @@ -125,6 +126,7 @@ impl GeneratedRustQObject { generated.blocks.append(&mut threading::generate( &qobject_idents, &namespace_idents, + qualified_mappings, )?); } @@ -133,12 +135,15 @@ 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; + let qualified_impl = syn_ident_cxx_bridge_to_qualified_impl( + &qobject_idents.cpp_class.rust, + qualified_mappings, + ); generated .blocks .cxx_qt_mod_contents .push(syn::parse_quote! { - impl cxx_qt::Locking for #cpp_class_name_rust {} + impl cxx_qt::Locking for #qualified_impl {} }); } @@ -148,9 +153,10 @@ impl GeneratedRustQObject { &namespace_idents, )?); - generated - .blocks - .append(&mut cxxqttype::generate(&qobject_idents)?); + generated.blocks.append(&mut cxxqttype::generate( + &qobject_idents, + qualified_mappings, + )?); Ok(generated) } diff --git a/crates/cxx-qt-gen/src/generator/rust/signals.rs b/crates/cxx-qt-gen/src/generator/rust/signals.rs index 8d0acedac..3406e5251 100644 --- a/crates/cxx-qt-gen/src/generator/rust/signals.rs +++ b/crates/cxx-qt-gen/src/generator/rust/signals.rs @@ -9,7 +9,7 @@ use crate::{ generator::{ naming::{qobject::QObjectName, signals::QSignalName}, rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObjectBlocks}, - utils::rust::syn_type_cxx_bridge_to_qualified, + utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified}, }, parser::signals::ParsedSignal, }; @@ -64,6 +64,8 @@ pub fn generate_rust_signals( }; 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 }); @@ -94,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."] diff --git a/crates/cxx-qt-gen/src/generator/rust/threading.rs b/crates/cxx-qt-gen/src/generator/rust/threading.rs index 1f897dc3e..1bedea450 100644 --- a/crates/cxx-qt-gen/src/generator/rust/threading.rs +++ b/crates/cxx-qt-gen/src/generator/rust/threading.rs @@ -3,21 +3,25 @@ // // 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, + 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, + qualified_mappings: &BTreeMap, ) -> Result { let mut blocks = GeneratedRustQObjectBlocks::default(); @@ -30,6 +34,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,7 +87,7 @@ 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); @@ -93,7 +99,7 @@ pub fn generate( #[doc(hidden)] fn queue(cxx_qt_thread: &#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,7 +108,7 @@ 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) @@ -129,7 +135,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>, } }, ], @@ -159,7 +165,12 @@ mod tests { 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(), + ) + .unwrap(); assert_eq!(generated.cxx_mod_contents.len(), 2); assert_eq!(generated.cxx_qt_mod_contents.len(), 2); diff --git a/crates/cxx-qt-gen/src/generator/utils/rust.rs b/crates/cxx-qt-gen/src/generator/utils/rust.rs index 93ec9df64..93787f403 100644 --- a/crates/cxx-qt-gen/src/generator/utils/rust.rs +++ b/crates/cxx-qt-gen/src/generator/utils/rust.rs @@ -9,6 +9,23 @@ 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 @@ -78,9 +95,7 @@ pub(crate) fn syn_type_cxx_bridge_to_qualified( // If the path matches a known ident then used the qualified mapping if let Some(ident) = ty_path.path.get_ident() { - if let Some(qualified_path) = qualified_mappings.get(ident) { - ty_path.path = qualified_path.clone(); - } + ty_path.path = syn_ident_cxx_bridge_to_qualified_impl(ident, qualified_mappings); } return Type::Path(ty_path); @@ -271,6 +286,16 @@ mod tests { ); } + #[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/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index 0fe654d26..eedfbdfb6 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -79,18 +79,18 @@ pub mod cxx_qt_inheritance { #[doc(hidden)] type UniquePtr = cxx::UniquePtr; type MyObjectRust = super::MyObjectRust; - impl cxx_qt::Locking for MyObject {} + 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 MyObject { + impl core::ops::Deref for inheritance::MyObject { type Target = MyObjectRust; fn deref(&self) -> &Self::Target { self.cxx_qt_ffi_rust() } } - impl cxx_qt::CxxQtType for MyObject { + impl cxx_qt::CxxQtType for inheritance::MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index a77a0284c..306ca4a13 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -179,7 +179,7 @@ pub mod cxx_qt_ffi { #[doc(hidden)] type UniquePtr = cxx::UniquePtr; type MyObjectRust = super::MyObjectRust; - impl cxx_qt::Threading for MyObject { + impl cxx_qt::Threading for ffi::MyObject { type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; type ThreadingTypeId = cxx::type_id!("cxx_qt::my_object::MyObjectCxxQtThread"); fn qt_thread(&self) -> MyObjectCxxQtThread { @@ -191,13 +191,13 @@ pub mod cxx_qt_ffi { f: F, ) -> std::result::Result<(), cxx::Exception> where - F: FnOnce(core::pin::Pin<&mut MyObject>), + F: FnOnce(core::pin::Pin<&mut ffi::MyObject>), F: Send + 'static, { #[allow(clippy::boxed_local)] #[doc(hidden)] fn func( - obj: core::pin::Pin<&mut MyObject>, + obj: core::pin::Pin<&mut ffi::MyObject>, arg: std::boxed::Box, ) { (arg.inner)(obj) @@ -218,9 +218,9 @@ pub mod cxx_qt_ffi { } #[doc(hidden)] pub struct MyObjectCxxQtThreadQueuedFn { - inner: std::boxed::Box) + Send>, + inner: std::boxed::Box) + Send>, } - impl cxx_qt::Locking for MyObject {} + impl cxx_qt::Locking for ffi::MyObject {} #[doc(hidden)] pub fn route_arguments_my_object_0( arg0: i32, @@ -257,13 +257,13 @@ pub mod cxx_qt_ffi { ) { >::initialize(qobject, ()); } - impl core::ops::Deref for MyObject { + 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 { + impl cxx_qt::CxxQtType for ffi::MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() 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 f7f087d8a..a41b8899a 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -218,14 +218,14 @@ pub mod cxx_qt_ffi { type UniquePtr = cxx::UniquePtr; use super::MyTrait; type MyObjectRust = super::MyObjectRust; - impl MyObject { + impl ffi::MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { &self.property_name } } - impl MyObject { + 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) { @@ -236,7 +236,7 @@ pub mod cxx_qt_ffi { self.as_mut().property_name_changed(); } } - impl MyObject { + 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."] @@ -250,7 +250,7 @@ pub mod cxx_qt_ffi { self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl MyObject { + 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."] @@ -264,18 +264,18 @@ pub mod cxx_qt_ffi { self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObject {} + 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 MyObject { + 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 { + impl cxx_qt::CxxQtType for ffi::MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() @@ -285,14 +285,14 @@ pub mod cxx_qt_ffi { } } type SecondObjectRust = super::SecondObjectRust; - impl SecondObject { + impl ffi::SecondObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] pub fn property_name(&self) -> &i32 { &self.property_name } } - impl SecondObject { + 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) { @@ -303,7 +303,7 @@ pub mod cxx_qt_ffi { self.as_mut().property_name_changed(); } } - impl SecondObject { + 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."] @@ -317,7 +317,7 @@ pub mod cxx_qt_ffi { self.connect_property_name_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl SecondObject { + 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."] @@ -335,13 +335,13 @@ pub mod cxx_qt_ffi { pub fn create_rs_second_object_rust() -> std::boxed::Box { std::boxed::Box::new(core::default::Default::default()) } - impl core::ops::Deref for SecondObject { + impl core::ops::Deref for ffi::SecondObject { type Target = SecondObjectRust; fn deref(&self) -> &Self::Target { self.cxx_qt_ffi_rust() } } - impl cxx_qt::CxxQtType for SecondObject { + impl cxx_qt::CxxQtType for ffi::SecondObject { type Rust = SecondObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 24d13c5ca..3ddb0ba4f 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -108,14 +108,14 @@ pub mod cxx_qt_ffi { #[doc(hidden)] type UniquePtr = cxx::UniquePtr; type MyObjectRust = super::MyObjectRust; - impl MyObject { + impl ffi::MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "primitive"] pub fn primitive(&self) -> &i32 { &self.primitive } } - impl MyObject { + impl ffi::MyObject { #[doc = "Setter for the Q_PROPERTY "] #[doc = "primitive"] pub fn set_primitive(mut self: core::pin::Pin<&mut Self>, value: i32) { @@ -126,14 +126,14 @@ pub mod cxx_qt_ffi { self.as_mut().primitive_changed(); } } - impl MyObject { + impl ffi::MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "trivial"] pub fn trivial(&self) -> &ffi::QPoint { &self.trivial } } - impl MyObject { + 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) { @@ -144,7 +144,7 @@ pub mod cxx_qt_ffi { self.as_mut().trivial_changed(); } } - impl MyObject { + 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."] @@ -158,7 +158,7 @@ pub mod cxx_qt_ffi { self.connect_primitive_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl MyObject { + 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."] @@ -172,18 +172,18 @@ pub mod cxx_qt_ffi { self.connect_trivial_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObject {} + 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 MyObject { + 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 { + impl cxx_qt::CxxQtType for ffi::MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() diff --git a/crates/cxx-qt-gen/test_outputs/signals.rs b/crates/cxx-qt-gen/test_outputs/signals.rs index b01871d21..11ee9d874 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -135,7 +135,7 @@ pub mod cxx_qt_ffi { #[doc(hidden)] type UniquePtr = cxx::UniquePtr; type MyObjectRust = super::MyObjectRust; - impl MyObject { + 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."] @@ -149,7 +149,7 @@ pub mod cxx_qt_ffi { self.connect_ready(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl MyObject { + 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."] @@ -169,7 +169,7 @@ pub mod cxx_qt_ffi { self.connect_data_changed(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl MyObject { + 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."] @@ -189,18 +189,18 @@ pub mod cxx_qt_ffi { self.connect_base_class_new_data(func, cxx_qt_lib::ConnectionType::AutoConnection) } } - impl cxx_qt::Locking for MyObject {} + 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 MyObject { + 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 { + impl cxx_qt::CxxQtType for ffi::MyObject { type Rust = MyObjectRust; fn rust(&self) -> &Self::Rust { self.cxx_qt_ffi_rust() From 8092596479a3d8a1e51e675b68f179da885ffad3 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 14:57:26 +0100 Subject: [PATCH 05/11] cxx-qt-gen: use qualified name for T in constructor generation Related to #404 --- .../src/generator/rust/constructor.rs | 27 ++++++++++++++----- .../cxx-qt-gen/src/generator/rust/qobject.rs | 1 + crates/cxx-qt-gen/test_outputs/invokables.rs | 15 ++++++----- 3 files changed, 30 insertions(+), 13 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index 1b0297f64..15eaa8788 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -3,11 +3,13 @@ // // 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, + utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, syn_type_is_cxx_bridge_unsafe}, }, parser::constructor::Constructor, }; @@ -15,7 +17,9 @@ 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, Ident, Item, Path, Result, Type, +}; const CONSTRUCTOR_ARGUMENTS: &str = "CxxQtConstructorArguments"; const BASE_ARGUMENTS: &str = "CxxQtConstructorBaseArguments"; @@ -136,6 +140,7 @@ pub fn generate( constructors: &[Constructor], qobject_idents: &QObjectName, namespace: &NamespaceName, + qualified_mappings: &BTreeMap, ) -> Result { if constructors.is_empty() { return Ok(generate_default_constructor(qobject_idents, namespace)); @@ -146,6 +151,8 @@ pub fn generate( 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; @@ -281,7 +288,7 @@ 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,)*)>> ::route_arguments((#(#assign_arguments,)*)); #arguments_rust { base: #init_base_arguments, @@ -295,7 +302,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> { - std::boxed::Box::new(<#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::new((#(#extract_new_arguments,)*))) + std::boxed::Box::new(<#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>>::new((#(#extract_new_arguments,)*))) } }, parse_quote_spanned! { @@ -303,10 +310,10 @@ pub fn generate( #[doc(hidden)] #[allow(unused_variables)] pub fn #initialize_rust( - qobject: core::pin::Pin<&mut #qobject_name_rust>, + qobject: core::pin::Pin<&mut #qobject_name_rust_qualified>, initialize_arguments: #initialize_arguments_rust ) { - <#qobject_name_rust as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( + <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( qobject, (#(#extract_initialize_arguments,)*)); } @@ -340,7 +347,13 @@ mod tests { } fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObjectBlocks { - generate(constructors, &mock_name(), &mock_namespace()).unwrap() + generate( + constructors, + &mock_name(), + &mock_namespace(), + &BTreeMap::::default(), + ) + .unwrap() } #[test] diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 313f58dae..44834a6ba 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -151,6 +151,7 @@ impl GeneratedRustQObject { &qobject.constructors, &qobject_idents, &namespace_idents, + qualified_mappings, )?); generated.blocks.append(&mut cxxqttype::generate( diff --git a/crates/cxx-qt-gen/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index 306ca4a13..a60bf6b34 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -229,7 +229,9 @@ pub mod cxx_qt_ffi { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = - >::route_arguments((arg0, arg1)); + >::route_arguments(( + arg0, arg1, + )); CxxQtConstructorArgumentsMyObject0 { base: CxxQtConstructorBaseArgumentsMyObject0 { arg0: base_arguments.0, @@ -245,17 +247,18 @@ pub mod cxx_qt_ffi { pub fn new_rs_my_object_0( new_arguments: CxxQtConstructorNewArgumentsMyObject0, ) -> std::boxed::Box { - std::boxed::Box::new(>::new( - (new_arguments.arg0,), - )) + std::boxed::Box::new(>::new((new_arguments.arg0,))) } #[doc(hidden)] #[allow(unused_variables)] pub fn initialize_my_object_0( - qobject: core::pin::Pin<&mut MyObject>, + qobject: core::pin::Pin<&mut ffi::MyObject>, initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0, ) { - >::initialize(qobject, ()); + >::initialize(qobject, ()); } impl core::ops::Deref for ffi::MyObject { type Target = MyObjectRust; From da8a19e1595802650070c0a1bfca0c7d044d753a Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 13:51:54 +0100 Subject: [PATCH 06/11] cxx-qt-gen: use CxxQtType in the setter as it needs rust_mut() Related to #404 --- crates/cxx-qt-gen/src/generator/rust/property/mod.rs | 3 +++ crates/cxx-qt-gen/src/generator/rust/property/setter.rs | 1 + crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs | 2 ++ crates/cxx-qt-gen/test_outputs/properties.rs | 2 ++ 4 files changed, 8 insertions(+) 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 42f0f22de..6d02f2a0c 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs @@ -140,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; } @@ -192,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; } @@ -244,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 5be0b8851..317fb08f1 100644 --- a/crates/cxx-qt-gen/src/generator/rust/property/setter.rs +++ b/crates/cxx-qt-gen/src/generator/rust/property/setter.rs @@ -50,6 +50,7 @@ pub fn generate( #[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/test_outputs/passthrough_and_naming.rs b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs index a41b8899a..67aae96a8 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -229,6 +229,7 @@ pub mod cxx_qt_ffi { #[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; } @@ -296,6 +297,7 @@ pub mod cxx_qt_ffi { #[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; } diff --git a/crates/cxx-qt-gen/test_outputs/properties.rs b/crates/cxx-qt-gen/test_outputs/properties.rs index 3ddb0ba4f..383d352ae 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -119,6 +119,7 @@ pub mod cxx_qt_ffi { #[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; } @@ -137,6 +138,7 @@ pub mod cxx_qt_ffi { #[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; } From 147724085aa360bd0cf1becd4b7ed6e4c633909d Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 15:31:43 +0100 Subject: [PATCH 07/11] cxx-qt-gen: ensure that constructor and threading free methods are qualified Related to #404 --- .../src/generator/rust/constructor.rs | 46 ++++++++++--------- crates/cxx-qt-gen/src/generator/rust/mod.rs | 6 ++- .../cxx-qt-gen/src/generator/rust/qobject.rs | 7 +++ .../src/generator/rust/threading.rs | 32 +++++++------ crates/cxx-qt-gen/test_outputs/invokables.rs | 28 +++++------ 5 files changed, 69 insertions(+), 50 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index 15eaa8788..66004fe66 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -141,6 +141,7 @@ pub fn generate( qobject_idents: &QObjectName, namespace: &NamespaceName, qualified_mappings: &BTreeMap, + module_ident: &Ident, ) -> Result { if constructors.is_empty() { return Ok(generate_default_constructor(qobject_idents, namespace)); @@ -280,7 +281,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_parameters),*) -> #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)] @@ -290,10 +291,10 @@ pub fn generate( initialize_arguments ) = <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>> ::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, } } }, @@ -301,7 +302,7 @@ 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> { + 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,)*)>>::new((#(#extract_new_arguments,)*))) } }, @@ -311,7 +312,7 @@ pub fn generate( #[allow(unused_variables)] pub fn #initialize_rust( qobject: core::pin::Pin<&mut #qobject_name_rust_qualified>, - initialize_arguments: #initialize_arguments_rust + initialize_arguments: #module_ident::#initialize_arguments_rust ) { <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( qobject, @@ -327,6 +328,8 @@ mod tests { use super::*; use crate::tests::assert_tokens_eq; + use quote::format_ident; + fn mock_constructor() -> Constructor { Constructor { new_arguments: vec![], @@ -352,6 +355,7 @@ mod tests { &mock_name(), &mock_namespace(), &BTreeMap::::default(), + &format_ident!("ffi"), ) .unwrap() } @@ -463,17 +467,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 }, } } }, @@ -483,7 +487,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(()) ) @@ -497,7 +501,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, ()); } @@ -584,24 +588,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, }, } @@ -613,7 +617,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,))) @@ -627,7 +631,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/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index 0ba79308a..5c6550c32 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -44,7 +44,11 @@ impl GeneratedRustBlocks { .qobjects .values() .map(|qobject| { - GeneratedRustQObject::from(qobject, &parser.cxx_qt_data.qualified_mappings) + GeneratedRustQObject::from( + qobject, + &parser.cxx_qt_data.qualified_mappings, + &parser.passthrough_module.ident, + ) }) .collect::>>()?, }) diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 44834a6ba..290861f9d 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -51,6 +51,7 @@ impl GeneratedRustQObject { pub fn from( qobject: &ParsedQObject, qualified_mappings: &BTreeMap, + module_ident: &Ident, ) -> Result { // Create the base object let qobject_idents = QObjectName::from(qobject); @@ -127,6 +128,7 @@ impl GeneratedRustQObject { &qobject_idents, &namespace_idents, qualified_mappings, + module_ident, )?); } @@ -152,6 +154,7 @@ impl GeneratedRustQObject { &qobject_idents, &namespace_idents, qualified_mappings, + module_ident, )?); generated.blocks.append(&mut cxxqttype::generate( @@ -230,6 +233,7 @@ mod tests { use crate::parser::Parser; use crate::tests::assert_tokens_eq; + use quote::format_ident; use syn::{parse_quote, ItemMod}; #[test] @@ -248,6 +252,7 @@ mod tests { let rust = GeneratedRustQObject::from( parser.cxx_qt_data.qobjects.values().next().unwrap(), &BTreeMap::::default(), + &format_ident!("ffi"), ) .unwrap(); assert_eq!(rust.cpp_struct_ident, "MyObject"); @@ -271,6 +276,7 @@ mod tests { let rust = GeneratedRustQObject::from( parser.cxx_qt_data.qobjects.values().next().unwrap(), &BTreeMap::::default(), + &format_ident!("ffi"), ) .unwrap(); assert_eq!(rust.cpp_struct_ident, "MyObject"); @@ -294,6 +300,7 @@ mod tests { let rust = GeneratedRustQObject::from( parser.cxx_qt_data.qobjects.values().next().unwrap(), &BTreeMap::::default(), + &format_ident!("ffi"), ) .unwrap(); assert_eq!(rust.blocks.cxx_mod_contents.len(), 6); diff --git a/crates/cxx-qt-gen/src/generator/rust/threading.rs b/crates/cxx-qt-gen/src/generator/rust/threading.rs index 1bedea450..b244748a6 100644 --- a/crates/cxx-qt-gen/src/generator/rust/threading.rs +++ b/crates/cxx-qt-gen/src/generator/rust/threading.rs @@ -22,6 +22,7 @@ pub fn generate( qobject_ident: &QObjectName, namespace_ident: &NamespaceName, qualified_mappings: &BTreeMap, + module_ident: &Ident, ) -> Result { let mut blocks = GeneratedRustQObjectBlocks::default(); @@ -91,13 +92,13 @@ pub fn generate( 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 #qualified_impl>), F: Send + 'static, @@ -114,19 +115,19 @@ pub fn generate( (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); } } }, @@ -159,6 +160,8 @@ 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(); @@ -169,6 +172,7 @@ mod tests { &qobject_idents, &namespace_ident, &BTreeMap::::default(), + &format_ident!("ffi"), ) .unwrap(); @@ -231,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, @@ -254,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/test_outputs/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index a60bf6b34..c8d14301f 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -182,12 +182,12 @@ pub mod cxx_qt_ffi { impl cxx_qt::Threading for ffi::MyObject { type BoxedQueuedFn = MyObjectCxxQtThreadQueuedFn; type ThreadingTypeId = cxx::type_id!("cxx_qt::my_object::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, + cxx_qt_thread: &ffi::MyObjectCxxQtThread, f: F, ) -> std::result::Result<(), cxx::Exception> where @@ -205,15 +205,15 @@ pub mod cxx_qt_ffi { 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 { - cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) + fn threading_clone(cxx_qt_thread: &ffi::MyObjectCxxQtThread) -> ffi::MyObjectCxxQtThread { + ffi::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 threading_drop(cxx_qt_thread: &mut ffi::MyObjectCxxQtThread) { + ffi::cxx_qt_ffi_my_object_threading_drop(cxx_qt_thread); } } #[doc(hidden)] @@ -225,19 +225,19 @@ pub mod cxx_qt_ffi { pub fn route_arguments_my_object_0( arg0: i32, arg1: *mut QObject, - ) -> CxxQtConstructorArgumentsMyObject0 { + ) -> ffi::CxxQtConstructorArgumentsMyObject0 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = >::route_arguments(( arg0, arg1, )); - CxxQtConstructorArgumentsMyObject0 { - base: CxxQtConstructorBaseArgumentsMyObject0 { + ffi::CxxQtConstructorArgumentsMyObject0 { + base: ffi::CxxQtConstructorBaseArgumentsMyObject0 { arg0: base_arguments.0, }, - initialize: CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, - new: CxxQtConstructorNewArgumentsMyObject0 { + initialize: ffi::CxxQtConstructorInitializeArgumentsMyObject0 { not_empty: 0 }, + new: ffi::CxxQtConstructorNewArgumentsMyObject0 { arg0: new_arguments.0, }, } @@ -245,7 +245,7 @@ pub mod cxx_qt_ffi { #[doc(hidden)] #[allow(unused_variables)] pub fn new_rs_my_object_0( - new_arguments: CxxQtConstructorNewArgumentsMyObject0, + new_arguments: ffi::CxxQtConstructorNewArgumentsMyObject0, ) -> std::boxed::Box { std::boxed::Box::new(, - initialize_arguments: CxxQtConstructorInitializeArgumentsMyObject0, + initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject0, ) { >::initialize(qobject, ()); } From 67c8f1a71d7bd7e765a33ccd443174d67a193291 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 16:28:36 +0100 Subject: [PATCH 08/11] cxx-qt-gen: ensure that constructor parameters are qualified in impl Related to #404 --- .../src/generator/rust/constructor.rs | 37 ++++++++++++++----- crates/cxx-qt-gen/test_inputs/invokables.rs | 2 + crates/cxx-qt-gen/test_outputs/invokables.rs | 10 +++-- 3 files changed, 36 insertions(+), 13 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index 66004fe66..a84670cfd 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -9,7 +9,10 @@ use crate::{ generator::{ naming::{namespace::NamespaceName, qobject::QObjectName, CombinedIdent}, rust::qobject::GeneratedRustQObjectBlocks, - utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, 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, + }, }, parser::constructor::Constructor, }; @@ -18,7 +21,8 @@ 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, Path, Result, Type, + parse_quote, parse_quote_spanned, spanned::Spanned, Expr, FnArg, Ident, Item, Path, Result, + Type, }; const CONSTRUCTOR_ARGUMENTS: &str = "CxxQtConstructorArguments"; @@ -179,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 @@ -281,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),*) -> #module_ident::#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)] @@ -289,7 +308,7 @@ pub fn generate( new_arguments, base_arguments, initialize_arguments - ) = <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>> + ) = <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>> ::route_arguments((#(#assign_arguments,)*)); #module_ident::#arguments_rust { base: #module_ident::#init_base_arguments, @@ -303,7 +322,7 @@ pub fn generate( #[doc(hidden)] #[allow(unused_variables)] 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,)*)>>::new((#(#extract_new_arguments,)*))) + std::boxed::Box::new(<#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::new((#(#extract_new_arguments,)*))) } }, parse_quote_spanned! { @@ -314,7 +333,7 @@ pub fn generate( qobject: core::pin::Pin<&mut #qobject_name_rust_qualified>, initialize_arguments: #module_ident::#initialize_arguments_rust ) { - <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types,)*)>>::initialize( + <#qobject_name_rust_qualified as cxx_qt::Constructor<(#(#argument_types_qualified,)*)>>::initialize( qobject, (#(#extract_initialize_arguments,)*)); } 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/invokables.rs b/crates/cxx-qt-gen/test_outputs/invokables.rs index c8d14301f..e90fa2d80 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 >); @@ -224,12 +226,12 @@ pub mod cxx_qt_ffi { #[doc(hidden)] pub fn route_arguments_my_object_0( arg0: i32, - arg1: *mut QObject, + arg1: *mut ffi::QObject, ) -> ffi::CxxQtConstructorArgumentsMyObject0 { #[allow(unused_variables)] #[allow(clippy::let_unit_value)] let (new_arguments, base_arguments, initialize_arguments) = - >::route_arguments(( + >::route_arguments(( arg0, arg1, )); ffi::CxxQtConstructorArgumentsMyObject0 { @@ -249,7 +251,7 @@ pub mod cxx_qt_ffi { ) -> std::boxed::Box { std::boxed::Box::new(>::new((new_arguments.arg0,))) } #[doc(hidden)] @@ -258,7 +260,7 @@ pub mod cxx_qt_ffi { qobject: core::pin::Pin<&mut ffi::MyObject>, initialize_arguments: ffi::CxxQtConstructorInitializeArgumentsMyObject0, ) { - >::initialize(qobject, ()); + >::initialize(qobject, ()); } impl core::ops::Deref for ffi::MyObject { type Target = MyObjectRust; From 03efafe3f54c966f8bacdce6d446d1344bc96390 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Wed, 19 Jul 2023 17:59:57 +0100 Subject: [PATCH 09/11] cxx-qt-gen: remove hidden module Related to #404 --- .../cxx-qt-gen/src/generator/rust/qobject.rs | 12 +- crates/cxx-qt-gen/src/writer/rust/mod.rs | 93 ++----- crates/cxx-qt-gen/test_outputs/inheritance.rs | 42 ++- crates/cxx-qt-gen/test_outputs/invokables.rs | 176 ++++++------- .../test_outputs/passthrough_and_naming.rs | 245 +++++++++--------- crates/cxx-qt-gen/test_outputs/properties.rs | 158 ++++++----- crates/cxx-qt-gen/test_outputs/signals.rs | 152 +++++------ 7 files changed, 379 insertions(+), 499 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 290861f9d..15443a7bf 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -18,7 +18,7 @@ use crate::{ parser::qobject::ParsedQObject, }; use quote::quote; -use syn::{parse_quote, Ident, ImplItem, Item, Path, Result}; +use syn::{Ident, ImplItem, Item, Path, Result}; #[derive(Default)] pub struct GeneratedRustQObjectBlocks { @@ -70,16 +70,6 @@ impl GeneratedRustQObject { .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; - } - }); - // Generate methods for the properties, invokables, signals generated.blocks.append(&mut generate_rust_properties( &qobject.properties, diff --git a/crates/cxx-qt-gen/src/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 62960b1c4..1421d4ae4 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -5,14 +5,10 @@ use crate::generator::rust::GeneratedRustBlocks; use proc_macro2::TokenStream; -use quote::{format_ident, quote, ToTokens}; +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(); @@ -44,24 +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 blocks from the QObject cxx_mod_contents.extend_from_slice(&qobject.blocks.cxx_mod_contents); cxx_qt_mod_contents.extend_from_slice(&qobject.blocks.cxx_qt_mod_contents); - - // 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; - }) } // Inject the CXX blocks @@ -71,30 +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 { - // Temporary hack so that qualified types still work, this will be removed in the next commit - use super::*; - 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() } @@ -276,25 +239,14 @@ mod tests { } } - use self::cxx_qt_ffi::*; - #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] - pub mod cxx_qt_ffi { - use super::*; - 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) { - } } } } @@ -344,34 +296,23 @@ mod tests { } } - use self::cxx_qt_ffi::*; - #[doc = r" Internal CXX-Qt module, made public temporarily between API changes"] - pub mod cxx_qt_ffi { - use super::*; - use super::ffi::*; - use cxx_qt::CxxQtType; + use module::Struct; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; + #[derive(Default)] + pub struct FirstObjectRust; - use module::Struct; + impl FirstObjectRust { + fn rust_method(&self) { - #[derive(Default)] - pub struct FirstObjectRust; - - impl FirstObjectRust { - fn rust_method(&self) { - - } } + } - #[derive(Default)] - pub struct SecondObjectRust; + #[derive(Default)] + pub struct SecondObjectRust; - impl SecondObjectRust { - fn rust_method(&self) { + impl SecondObjectRust { + fn rust_method(&self) { - } } } } diff --git a/crates/cxx-qt-gen/test_outputs/inheritance.rs b/crates/cxx-qt-gen/test_outputs/inheritance.rs index eedfbdfb6..fa5e5a156 100644 --- a/crates/cxx-qt-gen/test_outputs/inheritance.rs +++ b/crates/cxx-qt-gen/test_outputs/inheritance.rs @@ -70,33 +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 super::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - 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 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 inheritance::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 inheritance::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 e90fa2d80..ca8125c49 100644 --- a/crates/cxx-qt-gen/test_outputs/invokables.rs +++ b/crates/cxx-qt-gen/test_outputs/invokables.rs @@ -172,109 +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 super::*; - 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 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)] - 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 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)] - fn threading_clone(cxx_qt_thread: &ffi::MyObjectCxxQtThread) -> ffi::MyObjectCxxQtThread { - ffi::cxx_qt_ffi_my_object_threading_clone(cxx_qt_thread) - } + 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_drop(cxx_qt_thread: &mut ffi::MyObjectCxxQtThread) { - ffi::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 ffi::MyObject {} #[doc(hidden)] - pub fn route_arguments_my_object_0( - arg0: i32, - arg1: *mut ffi::QObject, - ) -> ffi::CxxQtConstructorArgumentsMyObject0 { - #[allow(unused_variables)] - #[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, - }, - } + 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: ffi::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 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() - } +} +#[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 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() - } +} +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 67aae96a8..73e7e3196 100644 --- a/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs +++ b/crates/cxx-qt-gen/test_outputs/passthrough_and_naming.rs @@ -208,148 +208,137 @@ 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 super::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - use super::MyTrait; - type MyObjectRust = super::MyObjectRust; - impl ffi::MyObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "property_name"] - pub fn property_name(&self) -> &i32 { - &self.property_name - } +use super::MyTrait; +impl ffi::MyObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "property_name"] + pub fn property_name(&self) -> &i32 { + &self.property_name } - 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 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 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 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 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 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 ffi::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 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() } - 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() - } + 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 ffi::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 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 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 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 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 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) - } +} +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 ffi::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 ffi::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 383d352ae..674e174f4 100644 --- a/crates/cxx-qt-gen/test_outputs/properties.rs +++ b/crates/cxx-qt-gen/test_outputs/properties.rs @@ -99,99 +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 super::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - impl ffi::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 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 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 ffi::MyObject { - #[doc = "Getter for the Q_PROPERTY "] - #[doc = "trivial"] - pub fn trivial(&self) -> &ffi::QPoint { - &self.trivial - } +} +impl ffi::MyObject { + #[doc = "Getter for the Q_PROPERTY "] + #[doc = "trivial"] + pub fn trivial(&self) -> &ffi::QPoint { + &self.trivial } - 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 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 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 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 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 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 ffi::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 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() } - 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() - } + 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 11ee9d874..1a57d2f11 100644 --- a/crates/cxx-qt-gen/test_outputs/signals.rs +++ b/crates/cxx-qt-gen/test_outputs/signals.rs @@ -126,87 +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 super::*; - use cxx_qt::CxxQtType; - #[doc(hidden)] - type UniquePtr = cxx::UniquePtr; - type MyObjectRust = super::MyObjectRust; - 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 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 = "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 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() - } +} +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() } } From 8520c59164526daf8a129f61fd61f63a5c144741 Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Fri, 21 Jul 2023 12:00:37 +0100 Subject: [PATCH 10/11] cxx-qt-gen: leave use statements in the CXX bridge Related to #404 --- crates/cxx-qt-gen/src/generator/rust/mod.rs | 25 +------------------ crates/cxx-qt-gen/src/parser/cxxqtdata.rs | 19 -------------- .../test_outputs/passthrough_and_naming.rs | 2 +- 3 files changed, 2 insertions(+), 44 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/mod.rs b/crates/cxx-qt-gen/src/generator/rust/mod.rs index 5c6550c32..5906c1f61 100644 --- a/crates/cxx-qt-gen/src/generator/rust/mod.rs +++ b/crates/cxx-qt-gen/src/generator/rust/mod.rs @@ -37,7 +37,7 @@ 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 @@ -124,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/parser/cxxqtdata.rs b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs index 78bddbc55..65a3b7ee1 100644 --- a/crates/cxx-qt-gen/src/parser/cxxqtdata.rs +++ b/crates/cxx-qt-gen/src/parser/cxxqtdata.rs @@ -62,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 { @@ -202,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)), } @@ -523,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(); 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 73e7e3196..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,7 +209,6 @@ pub mod ffi { fn cxx_qt_ffi_rust_mut(self: Pin<&mut SecondObject>) -> Pin<&mut SecondObjectRust>; } } -use super::MyTrait; impl ffi::MyObject { #[doc = "Getter for the Q_PROPERTY "] #[doc = "property_name"] From e49b9db650580b7126959fbd55b9da444e50070e Mon Sep 17 00:00:00 2001 From: Andrew Hayzen Date: Tue, 25 Jul 2023 15:12:21 +0100 Subject: [PATCH 11/11] cxx-qt-gen: remove unused members from generated qobject --- .../src/generator/rust/constructor.rs | 19 +- .../src/generator/rust/cxxqttype.rs | 6 +- .../cxx-qt-gen/src/generator/rust/inherit.rs | 8 +- .../src/generator/rust/invokable.rs | 6 +- .../src/generator/rust/property/mod.rs | 6 +- .../cxx-qt-gen/src/generator/rust/qobject.rs | 128 +++----------- .../cxx-qt-gen/src/generator/rust/signals.rs | 6 +- .../src/generator/rust/threading.rs | 6 +- crates/cxx-qt-gen/src/writer/rust/mod.rs | 164 ++++++++---------- 9 files changed, 128 insertions(+), 221 deletions(-) diff --git a/crates/cxx-qt-gen/src/generator/rust/constructor.rs b/crates/cxx-qt-gen/src/generator/rust/constructor.rs index a84670cfd..c6e153b0a 100644 --- a/crates/cxx-qt-gen/src/generator/rust/constructor.rs +++ b/crates/cxx-qt-gen/src/generator/rust/constructor.rs @@ -8,7 +8,7 @@ use std::collections::BTreeMap; use crate::{ generator::{ naming::{namespace::NamespaceName, qobject::QObjectName, CombinedIdent}, - rust::qobject::GeneratedRustQObjectBlocks, + rust::qobject::GeneratedRustQObject, utils::rust::{ syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified, syn_type_is_cxx_bridge_unsafe, @@ -65,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!( @@ -74,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"] @@ -146,12 +146,12 @@ pub fn generate( namespace: &NamespaceName, qualified_mappings: &BTreeMap, module_ident: &Ident, -) -> Result { +) -> 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; @@ -368,7 +368,7 @@ mod tests { NamespaceName::from_pair_str("ffi", &format_ident!("MyObject")) } - fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObjectBlocks { + fn generate_mocked(constructors: &[Constructor]) -> GeneratedRustQObject { generate( constructors, &mock_name(), @@ -430,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( @@ -528,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], diff --git a/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs index 3da02005f..6153bc796 100644 --- a/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs +++ b/crates/cxx-qt-gen/src/generator/rust/cxxqttype.rs @@ -6,7 +6,7 @@ use std::collections::BTreeMap; use crate::generator::{ - naming::qobject::QObjectName, rust::qobject::GeneratedRustQObjectBlocks, + naming::qobject::QObjectName, rust::qobject::GeneratedRustQObject, utils::rust::syn_ident_cxx_bridge_to_qualified_impl, }; use quote::quote; @@ -17,8 +17,8 @@ use super::fragment::RustFragmentPair; pub fn generate( qobject_ident: &QObjectName, qualified_mappings: &BTreeMap, -) -> Result { - let mut blocks = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut blocks = GeneratedRustQObject::default(); let cpp_struct_ident = &qobject_ident.cpp_class.rust; let rust_struct_ident = &qobject_ident.rust_struct.rust; 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/property/mod.rs b/crates/cxx-qt-gen/src/generator/rust/property/mod.rs index 6d02f2a0c..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,7 +10,7 @@ pub mod signal; use crate::{ generator::{ naming::{property::QPropertyName, qobject::QObjectName}, - rust::qobject::GeneratedRustQObjectBlocks, + rust::qobject::GeneratedRustQObject, }, parser::property::ParsedQProperty, }; @@ -23,8 +23,8 @@ pub fn generate_rust_properties( properties: &Vec, qobject_idents: &QObjectName, qualified_mappings: &BTreeMap, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut generated = GeneratedRustQObject::default(); let mut signals = vec![]; for property in properties { diff --git a/crates/cxx-qt-gen/src/generator/rust/qobject.rs b/crates/cxx-qt-gen/src/generator/rust/qobject.rs index 15443a7bf..21a1fafe1 100644 --- a/crates/cxx-qt-gen/src/generator/rust/qobject.rs +++ b/crates/cxx-qt-gen/src/generator/rust/qobject.rs @@ -21,33 +21,20 @@ use quote::quote; 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, qualified_mappings: &BTreeMap, @@ -57,38 +44,31 @@ impl GeneratedRustQObject { 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)?); + 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, @@ -106,7 +86,6 @@ impl GeneratedRustQObject { implementation: vec![], }; generated - .blocks .cxx_mod_contents .append(&mut fragment.cxx_bridge_as_items()?); } @@ -114,7 +93,7 @@ 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, @@ -131,15 +110,12 @@ impl GeneratedRustQObject { &qobject_idents.cpp_class.rust, qualified_mappings, ); - generated - .blocks - .cxx_qt_mod_contents - .push(syn::parse_quote! { - impl cxx_qt::Locking for #qualified_impl {} - }); + 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, @@ -147,7 +123,7 @@ impl GeneratedRustQObject { module_ident, )?); - generated.blocks.append(&mut cxxqttype::generate( + generated.append(&mut cxxqttype::generate( &qobject_idents, qualified_mappings, )?); @@ -160,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() @@ -181,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(); @@ -226,54 +200,6 @@ mod tests { 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(), - &BTreeMap::::default(), - &format_ident!("ffi"), - ) - .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(), - &BTreeMap::::default(), - &format_ident!("ffi"), - ) - .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! { @@ -293,9 +219,9 @@ mod tests { &format_ident!("ffi"), ) .unwrap(); - assert_eq!(rust.blocks.cxx_mod_contents.len(), 6); + 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 "] @@ -309,7 +235,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[1], + &rust.cxx_mod_contents[1], quote! { extern "Rust" { type MyObjectRust; @@ -317,7 +243,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[2], + &rust.cxx_mod_contents[2], quote! { unsafe extern "C++" { include!(); @@ -325,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"] @@ -335,7 +261,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[4], + &rust.cxx_mod_contents[4], quote! { unsafe extern "C++" { #[cxx_name = "unsafeRust"] @@ -345,7 +271,7 @@ mod tests { }, ); assert_tokens_eq( - &rust.blocks.cxx_mod_contents[5], + &rust.cxx_mod_contents[5], quote! { unsafe extern "C++" { #[cxx_name = "unsafeRustMut"] diff --git a/crates/cxx-qt-gen/src/generator/rust/signals.rs b/crates/cxx-qt-gen/src/generator/rust/signals.rs index 3406e5251..4891d14cd 100644 --- a/crates/cxx-qt-gen/src/generator/rust/signals.rs +++ b/crates/cxx-qt-gen/src/generator/rust/signals.rs @@ -8,7 +8,7 @@ use std::collections::BTreeMap; use crate::{ generator::{ naming::{qobject::QObjectName, signals::QSignalName}, - rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObjectBlocks}, + rust::{fragment::RustFragmentPair, qobject::GeneratedRustQObject}, utils::rust::{syn_ident_cxx_bridge_to_qualified_impl, syn_type_cxx_bridge_to_qualified}, }, parser::signals::ParsedSignal, @@ -20,8 +20,8 @@ pub fn generate_rust_signals( signals: &Vec, qobject_idents: &QObjectName, qualified_mappings: &BTreeMap, -) -> Result { - let mut generated = GeneratedRustQObjectBlocks::default(); +) -> Result { + let mut generated = GeneratedRustQObject::default(); let qobject_name = &qobject_idents.cpp_class.rust; // Create the methods for the other signals diff --git a/crates/cxx-qt-gen/src/generator/rust/threading.rs b/crates/cxx-qt-gen/src/generator/rust/threading.rs index b244748a6..60f3b4a6d 100644 --- a/crates/cxx-qt-gen/src/generator/rust/threading.rs +++ b/crates/cxx-qt-gen/src/generator/rust/threading.rs @@ -10,7 +10,7 @@ use crate::generator::{ 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; @@ -23,8 +23,8 @@ pub fn generate( namespace_ident: &NamespaceName, qualified_mappings: &BTreeMap, module_ident: &Ident, -) -> Result { - let mut blocks = GeneratedRustQObjectBlocks::default(); +) -> 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; diff --git a/crates/cxx-qt-gen/src/writer/rust/mod.rs b/crates/cxx-qt-gen/src/writer/rust/mod.rs index 1421d4ae4..9586d9e8d 100644 --- a/crates/cxx-qt-gen/src/writer/rust/mod.rs +++ b/crates/cxx-qt-gen/src/writer/rust/mod.rs @@ -42,8 +42,8 @@ pub fn write_rust(generated: &GeneratedRustBlocks) -> TokenStream { for qobject in &generated.qobjects { // Add the blocks from the QObject - cxx_mod_contents.extend_from_slice(&qobject.blocks.cxx_mod_contents); - cxx_qt_mod_contents.extend_from_slice(&qobject.blocks.cxx_qt_mod_contents); + 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 @@ -66,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 @@ -87,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) { - } } - }, - ], - }, + } + }, + ], }], } } @@ -138,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) { + } - }, - ], - }, + } + }, + ], }, ], }